UNPKG

@sanity/sdk

Version:
1,285 lines (1,284 loc) 76.1 kB
import * as _sanity_client12 from "@sanity/client"; import { ClientConfig, ClientError, ClientPerspective, ListenEvent, ResponseQueryOptions, SanityClient, SanityDocument as SanityDocument$1, SanityProject as SanityProject$1, StackablePerspective } from "@sanity/client"; import { Observable, Subject } from "rxjs"; import { CurrentUser, CurrentUser as CurrentUser$1, Mutation, PatchOperations, Role, SanityDocument, SanityDocument as SanityDocument$2, SanityDocumentLike } from "@sanity/types"; import * as _sanity_comlink3 from "@sanity/comlink"; import { ChannelInput, ChannelInstance, Controller, Message, Node, NodeInput, Status } from "@sanity/comlink"; import { PatchMutation } from "@sanity/mutate/_unstable_store"; import { SanityDocument as SanityDocument$3, SanityProjectionResult, SanityQueryResult } from "groq"; import { ExprNode } from "groq-js"; import { CanvasResource, MediaResource, StudioResource } from "@sanity/message-protocol"; import { getIndexForKey, getPathDepth, joinPaths, jsonMatch, slicePath, stringifyPath } from "@sanity/json-match"; /** * Configuration for an authentication provider * @public */ interface AuthProvider { /** * Unique identifier for the auth provider (e.g., 'google', 'github') */ name: string; /** * Display name for the auth provider in the UI */ title: string; /** * Complete authentication URL including callback and token parameters */ url: string; /** * Optional URL for direct sign-up flow */ signUpUrl?: string; } /** * Configuration options for creating an auth store. * * @public */ interface AuthConfig { /** * The initial location href to use when handling auth callbacks. * Defaults to the current window location if available. */ initialLocationHref?: string; /** * Factory function to create a SanityClient instance. * Defaults to the standard Sanity client factory if not provided. */ clientFactory?: (config: ClientConfig) => SanityClient; /** * Custom authentication providers to use instead of or in addition to the default ones. * Can be an array of providers or a function that takes the default providers and returns * a modified array or a Promise resolving to one. */ providers?: AuthProvider[] | ((prev: AuthProvider[]) => AuthProvider[] | Promise<AuthProvider[]>); /** * The API hostname for requests. Usually leave this undefined, but it can be set * if using a custom domain or CNAME for the API endpoint. */ apiHost?: string; /** * Storage implementation to persist authentication state. * Defaults to `localStorage` if available. */ storageArea?: Storage; /** * A callback URL for your application. * If none is provided, the auth API will redirect back to the current location (`location.href`). * When handling callbacks, this URL's pathname is checked to ensure it matches the callback. */ callbackUrl?: string; /** * A static authentication token to use instead of handling the OAuth flow. * When provided, the auth store will remain in a logged-in state with this token, * ignoring any storage or callback handling. */ token?: string; } /** * Represents the minimal configuration required to identify a Sanity project. * @public */ interface ProjectHandle<TProjectId extends string = string> { projectId?: TProjectId; } /** * @public */ type ReleasePerspective = { releaseName: string; excludedPerspectives?: StackablePerspective[]; }; /** * @public */ interface PerspectiveHandle { perspective?: ClientPerspective | ReleasePerspective; } /** * @public */ interface DatasetHandle<TDataset extends string = string, TProjectId extends string = string> extends ProjectHandle<TProjectId>, PerspectiveHandle { dataset?: TDataset; } /** * Identifies a specific document type within a Sanity dataset and project. * Includes `projectId`, `dataset`, and `documentType`. * Optionally includes a `documentId` and `liveEdit` flag. * @public */ interface DocumentTypeHandle<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string> extends DatasetHandle<TDataset, TProjectId> { documentId?: string; documentType: TDocumentType; /** * Indicates whether this document uses liveEdit mode. * When `true`, the document does not use the draft/published model and edits are applied directly to the document. * @see https://www.sanity.io/docs/content-lake/drafts#ca0663a8f002 */ liveEdit?: boolean; } /** * Uniquely identifies a specific document within a Sanity dataset and project. * Includes `projectId`, `dataset`, `documentType`, and the required `documentId`. * Commonly used by document-related hooks and components to reference a document without fetching its full content initially. * @public */ interface DocumentHandle<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string> extends DocumentTypeHandle<TDocumentType, TDataset, TProjectId> { documentId: string; } /** * Represents the complete configuration for a Sanity SDK instance * @public */ interface SanityConfig extends DatasetHandle, PerspectiveHandle { /** * Authentication configuration for the instance * @remarks Merged with parent configurations when using createChild */ auth?: AuthConfig; /** * Studio mode configuration for use of the SDK in a Sanity Studio * @remarks Controls whether studio mode features are enabled */ studioMode?: { enabled: boolean; }; } declare const SOURCE_ID = "__sanity_internal_sourceId"; /** * A document source can be used for querying. * * @beta * @see datasetSource Construct a document source for a given projectId and dataset. * @see mediaLibrarySource Construct a document source for a mediaLibraryId. * @see canvasSource Construct a document source for a canvasId. */ type DocumentSource = { [SOURCE_ID]: ['media-library', string] | ['canvas', string] | { projectId: string; dataset: string; }; }; /** * Returns a document source for a projectId and dataset. * * @beta */ declare function datasetSource(projectId: string, dataset: string): DocumentSource; /** * Returns a document source for a Media Library. * * @beta */ declare function mediaLibrarySource(id: string): DocumentSource; /** * Returns a document source for a Canvas. * * @beta */ declare function canvasSource(id: string): DocumentSource; /** * Represents a Sanity.io resource instance with its own configuration and lifecycle * @remarks Instances form a hierarchy through parent/child relationships * * @public */ interface SanityInstance { /** * Unique identifier for this instance * @remarks Generated using crypto.randomUUID() */ readonly instanceId: string; /** * Resolved configuration for this instance * @remarks Merges values from parent instances where appropriate */ readonly config: SanityConfig; /** * Checks if the instance has been disposed * @returns true if dispose() has been called */ isDisposed(): boolean; /** * Disposes the instance and cleans up associated resources * @remarks Triggers all registered onDispose callbacks */ dispose(): void; /** * Registers a callback to be invoked when the instance is disposed * @param cb - Callback to execute on disposal * @returns Function to unsubscribe the callback */ onDispose(cb: () => void): () => void; /** * Gets the parent instance in the hierarchy * @returns Parent instance or undefined if this is the root */ getParent(): SanityInstance | undefined; /** * Creates a child instance with merged configuration * @param config - Configuration to merge with parent values * @remarks Child instances inherit parent configuration but can override values */ createChild(config: SanityConfig): SanityInstance; /** * Traverses the instance hierarchy to find the first instance whose configuration * matches the given target config using a shallow comparison. * @param targetConfig - A partial configuration object containing key-value pairs to match. * @returns The first matching instance or undefined if no match is found. */ match(targetConfig: Partial<SanityConfig>): SanityInstance | undefined; } /** * Creates a new Sanity resource instance * @param config - Configuration for the instance (optional) * @returns A configured SanityInstance * @remarks When creating child instances, configurations are merged with parent values * * @public */ declare function createSanityInstance(config?: SanityConfig): SanityInstance; /** @alpha */ type AgentGenerateOptions = Parameters<SanityClient['observable']['agent']['action']['generate']>[0]; /** @alpha */ type AgentTransformOptions = Parameters<SanityClient['observable']['agent']['action']['transform']>[0]; /** @alpha */ type AgentTranslateOptions = Parameters<SanityClient['observable']['agent']['action']['translate']>[0]; /** @alpha */ type AgentPromptOptions = Parameters<SanityClient['agent']['action']['prompt']>[0]; /** @alpha */ type AgentPatchOptions = Parameters<SanityClient['agent']['action']['patch']>[0]; /** @alpha */ type AgentGenerateResult = Awaited<ReturnType<SanityClient['observable']['agent']['action']['generate']>>; /** @alpha */ type AgentTransformResult = Awaited<ReturnType<SanityClient['observable']['agent']['action']['transform']>>; /** @alpha */ type AgentTranslateResult = Awaited<ReturnType<SanityClient['observable']['agent']['action']['translate']>>; /** @alpha */ type AgentPromptResult = Awaited<ReturnType<SanityClient['agent']['action']['prompt']>>; /** @alpha */ type AgentPatchResult = Awaited<ReturnType<SanityClient['agent']['action']['patch']>>; /** * Generates a new document using the agent. * @param instance - The Sanity instance. * @param options - The options for the agent generate action. See the [Agent Actions API](https://www.sanity.io/docs/agent-actions/introduction) for more details. * @returns An Observable emitting the result of the agent generate action. * @alpha */ declare function agentGenerate(instance: SanityInstance, options: AgentGenerateOptions): AgentGenerateResult; /** * Transforms a document using the agent. * @param instance - The Sanity instance. * @param options - The options for the agent transform action. See the [Agent Actions API](https://www.sanity.io/docs/agent-actions/introduction) for more details. * @returns An Observable emitting the result of the agent transform action. * @alpha */ declare function agentTransform(instance: SanityInstance, options: AgentTransformOptions): AgentTransformResult; /** * Translates a document using the agent. * @param instance - The Sanity instance. * @param options - The options for the agent translate action. See the [Agent Actions API](https://www.sanity.io/docs/agent-actions/introduction) for more details. * @returns An Observable emitting the result of the agent translate action. * @alpha */ declare function agentTranslate(instance: SanityInstance, options: AgentTranslateOptions): AgentTranslateResult; /** * Prompts the agent using the same instruction template format as the other actions, but returns text or json instead of acting on a document. * @param instance - The Sanity instance. * @param options - The options for the agent prompt action. See the [Agent Actions API](https://www.sanity.io/docs/agent-actions/introduction) for more details. * @returns An Observable emitting the result of the agent prompt action. * @alpha */ declare function agentPrompt(instance: SanityInstance, options: AgentPromptOptions): Observable<AgentPromptResult>; /** * Patches a document using the agent. * @param instance - The Sanity instance. * @param options - The options for the agent patch action. See the [Agent Actions API](https://www.sanity.io/docs/agent-actions/introduction) for more details. * @returns An Observable emitting the result of the agent patch action. * @alpha */ declare function agentPatch(instance: SanityInstance, options: AgentPatchOptions): Observable<AgentPatchResult>; /** * Represents the various states the authentication type can be in. * * @public */ declare enum AuthStateType { LOGGED_IN = "logged-in", LOGGING_IN = "logging-in", ERROR = "error", LOGGED_OUT = "logged-out", } /** * Represents a store action that has been bound to a specific store instance */ type BoundStoreAction<_TState, TParams extends unknown[], TReturn> = (instance: SanityInstance, ...params: TParams) => TReturn; /** * Represents the various states the authentication can be in. * * @public */ type AuthState = LoggedInAuthState | LoggedOutAuthState | LoggingInAuthState | ErrorAuthState; /** * Logged-in state from the auth state. * @public */ type LoggedInAuthState = { type: AuthStateType.LOGGED_IN; token: string; currentUser: CurrentUser$1 | null; lastTokenRefresh?: number; }; /** * Logged-out state from the auth state. * @public */ type LoggedOutAuthState = { type: AuthStateType.LOGGED_OUT; isDestroyingSession: boolean; }; /** * Logging-in state from the auth state. * @public */ type LoggingInAuthState = { type: AuthStateType.LOGGING_IN; isExchangingToken: boolean; }; /** * Error state from the auth state. * @public */ type ErrorAuthState = { type: AuthStateType.ERROR; error: unknown; }; /** * Represents the various states the authentication can be in. * * @public */ interface DashboardContext { mode?: string; env?: string; orgId?: string; } /** * The method of authentication used. * @internal */ type AuthMethodOptions = 'localstorage' | 'cookie' | undefined; /** * @public */ interface AuthStoreState { authState: AuthState; providers?: AuthProvider[]; options: { initialLocationHref: string; clientFactory: (config: ClientConfig) => SanityClient; customProviders: AuthConfig['providers']; storageKey: string; storageArea: Storage | undefined; apiHost: string | undefined; loginUrl: string; callbackUrl: string | undefined; providedToken: string | undefined; authMethod: AuthMethodOptions; }; dashboardContext?: DashboardContext; } /** * @public */ declare const getCurrentUserState: BoundStoreAction<AuthStoreState, [], StateSource<CurrentUser$1 | null>>; /** * @public */ declare const getTokenState: BoundStoreAction<AuthStoreState, [], StateSource<string | null>>; /** * @public */ declare const getLoginUrlState: BoundStoreAction<AuthStoreState, [], StateSource<string>>; /** * @public */ declare const getAuthState: BoundStoreAction<AuthStoreState, [], StateSource<AuthState>>; /** * @public */ declare const getDashboardOrganizationId: BoundStoreAction<AuthStoreState, [], StateSource<string | undefined>>; /** * Returns a state source indicating if the SDK is running within a dashboard context. * @public */ declare const getIsInDashboardState: BoundStoreAction<AuthStoreState, [], StateSource<boolean>>; /** * Action to explicitly set the authentication token. * Used internally by the Comlink token refresh. * @internal */ declare const setAuthToken: BoundStoreAction<AuthStoreState, [token: string | null], void>; /** * Error message returned by the organization verification * @public */ interface OrgVerificationResult { error: string | null; } /** * Creates an observable that emits the organization verification state for a given instance. * It combines the dashboard organization ID (from auth context) with the * project's actual organization ID (fetched via getProjectState) and compares them. * @public */ declare function observeOrganizationVerificationState(instance: SanityInstance, projectIds: string[]): Observable<OrgVerificationResult>; /** * @public */ declare const handleAuthCallback: BoundStoreAction<AuthStoreState, [locationHref?: string | undefined], Promise<string | false>>; /** * @public */ declare const logout: BoundStoreAction<AuthStoreState, [], Promise<void>>; /** @internal */ type ApiErrorBody = { error?: { type?: string; description?: string; }; type?: string; description?: string; message?: string; }; /** @internal Extracts the structured API error body from a ClientError, if present. */ declare function getClientErrorApiBody(error: ClientError): ApiErrorBody | undefined; /** @internal Returns the error type string from an API error body, if available. */ declare function getClientErrorApiType(error: ClientError): string | undefined; /** @internal Returns the error description string from an API error body, if available. */ declare function getClientErrorApiDescription(error: ClientError): string | undefined; /** @internal True if the error represents a projectUserNotFoundError. */ declare function isProjectUserNotFoundClientError(error: ClientError): boolean; type AllowedClientConfigKey = 'useCdn' | 'token' | 'perspective' | 'apiHost' | 'proxy' | 'withCredentials' | 'timeout' | 'maxRetries' | 'dataset' | 'projectId' | 'requestTagPrefix' | 'useProjectHostname'; /** * States tracked by the client store * @public */ interface ClientStoreState { token: string | null; clients: { [TKey in string]?: SanityClient }; authMethod?: 'localstorage' | 'cookie'; } /** * Options used when retrieving a client instance from the client store. * * This interface extends the base {@link ClientConfig} and adds: * * - **apiVersion:** A required string indicating the API version for the client. * - **scope:** An optional flag to choose between the project-specific client * ('project') and the global client ('global'). When set to `'global'`, the * global client is used. * * These options are utilized by `getClient` and `getClientState` to configure and * return appropriate client instances that automatically handle authentication * updates and configuration changes. * * @public */ interface ClientOptions extends Pick<ClientConfig, AllowedClientConfigKey> { /** * An optional flag to choose between the default client (typically project-level) * and the global client ('global'). When set to `'global'`, the global client * is used. */ 'scope'?: 'default' | 'global'; /** * A required string indicating the API version for the client. */ 'apiVersion': string; /** * @internal */ '~experimental_resource'?: ClientConfig['~experimental_resource']; /** * @internal */ 'source'?: DocumentSource; } /** * Retrieves a Sanity client instance configured with the provided options. * * This function returns a client instance configured for the project or as a * global client based on the options provided. It ensures efficient reuse of * client instances by returning the same instance for the same options. * For automatic handling of authentication token updates, consider using * `getClientState`. * * @public */ declare const getClient: BoundStoreAction<ClientStoreState, [options: ClientOptions], SanityClient>; /** * Returns a state source for the Sanity client instance. * * This function provides a subscribable state source that emits updated client * instances whenever relevant configurations change (such as authentication tokens). * Use this when you need to react to client configuration changes in your application. * * @public */ declare const getClientState: BoundStoreAction<ClientStoreState, [options: ClientOptions], StateSource<SanityClient>>; /** * Message sent from a containing app to an iframe * @public */ type FrameMessage = Message; /** * Message sent from an iframe to a containing app * @public */ type WindowMessage = Message; /** * Message from SDK (iframe) to Parent (dashboard) to request a new token * @internal */ type RequestNewTokenMessage = { type: 'dashboard/v1/auth/tokens/create'; payload?: undefined; }; /** * Message from Parent (dashboard) to SDK (iframe) with the new token * @internal */ type NewTokenResponseMessage = { type: 'dashboard/v1/auth/tokens/create'; payload: { token: string | null; error?: string; }; }; /** * Individual channel with its relevant options * @public */ interface ChannelEntry { channel: ChannelInstance<FrameMessage, WindowMessage>; options: ChannelInput; refCount: number; } /** * Internal state tracking comlink connections * @public */ interface ComlinkControllerState { controller: Controller | null; controllerOrigin: string | null; channels: Map<string, ChannelEntry>; } /** * Calls the destroy method on the controller and resets the controller state. * @public */ declare const destroyController: BoundStoreAction<ComlinkControllerState, [], void>; /** * Retrieve or create a channel to be used for communication between * an application and the controller. * @public */ declare const getOrCreateChannel: BoundStoreAction<ComlinkControllerState, [options: ChannelInput], ChannelInstance<_sanity_comlink3.Message, _sanity_comlink3.Message>>; /** * Initializes or fetches a controller to handle communication * between an application and iframes. * @public */ declare const getOrCreateController: BoundStoreAction<ComlinkControllerState, [targetOrigin: string], Controller>; /** * Signals to the store that the consumer has stopped using the channel * @public */ declare const releaseChannel: BoundStoreAction<ComlinkControllerState, [name: string], void>; /** * Individual node with its relevant options * @public */ interface NodeEntry { node: Node<WindowMessage, FrameMessage>; options: NodeInput; status: Status; statusUnsub?: () => void; } /** * Internal state tracking comlink connections * @public */ interface ComlinkNodeState { nodes: Map<string, NodeEntry>; subscriptions: Map<string, Set<symbol>>; } /** * Signals to the store that the consumer has stopped using the node * @public */ declare const releaseNode: BoundStoreAction<ComlinkNodeState, [name: string], void>; /** * Retrieve or create a node to be used for communication between * an application and the controller -- specifically, a node should * be created within a frame / window to communicate with the controller. * @public */ declare const getOrCreateNode: BoundStoreAction<ComlinkNodeState, [options: NodeInput], Node<_sanity_comlink3.Message, _sanity_comlink3.Message>>; /** * @public */ interface NodeState { node: Node<WindowMessage, FrameMessage>; status: Status | undefined; } /** * Provides a subscribable state source for a node by name * @param instance - The Sanity instance to get the node state for * @param nodeInput - The configuration for the node to get the state for * @returns A subscribable state source for the node * @public */ declare const getNodeState: BoundStoreAction<ComlinkNodeState, [NodeInput], StateSource<NodeState | undefined>>; /** * Creates or validates a `DocumentHandle` object. * Ensures the provided object conforms to the `DocumentHandle` interface. * @param handle - The object containing document identification properties. * @returns The validated `DocumentHandle` object. * @public */ declare function createDocumentHandle<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string>(handle: DocumentHandle<TDocumentType, TDataset, TProjectId>): DocumentHandle<TDocumentType, TDataset, TProjectId>; /** * Creates or validates a `DocumentTypeHandle` object. * Ensures the provided object conforms to the `DocumentTypeHandle` interface. * @param handle - The object containing document type identification properties. * @returns The validated `DocumentTypeHandle` object. * @public */ declare function createDocumentTypeHandle<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string>(handle: DocumentTypeHandle<TDocumentType, TDataset, TProjectId>): DocumentTypeHandle<TDocumentType, TDataset, TProjectId>; /** * Creates or validates a `ProjectHandle` object. * Ensures the provided object conforms to the `ProjectHandle` interface. * @param handle - The object containing project identification properties. * @returns The validated `ProjectHandle` object. * @public */ declare function createProjectHandle<TProjectId extends string = string>(handle: ProjectHandle<TProjectId>): ProjectHandle<TProjectId>; /** * Creates or validates a `DatasetHandle` object. * Ensures the provided object conforms to the `DatasetHandle` interface. * @param handle - The object containing dataset identification properties. * @returns The validated `DatasetHandle` object. * @public */ declare function createDatasetHandle<TDataset extends string = string, TProjectId extends string = string>(handle: DatasetHandle<TDataset, TProjectId>): DatasetHandle<TDataset, TProjectId>; /** @public */ declare const getDatasetsState: BoundStoreAction<FetcherStoreState<[options?: ProjectHandle<string> | undefined], _sanity_client12.DatasetsResponse>, [options?: ProjectHandle<string> | undefined], StateSource<_sanity_client12.DatasetsResponse | undefined>>; /** @public */ declare const resolveDatasets: BoundStoreAction<FetcherStoreState<[options?: ProjectHandle<string> | undefined], _sanity_client12.DatasetsResponse>, [options?: ProjectHandle<string> | undefined], Promise<_sanity_client12.DatasetsResponse>>; /** * Represents an action to create a new document. * Specifies the document type and optionally a document ID (which will be treated as the published ID). * @beta */ interface CreateDocumentAction<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string> extends DocumentTypeHandle<TDocumentType, TDataset, TProjectId> { type: 'document.create'; /** * Optional initial field values for the document. * These values will be set when the document is created. * System fields (_id, _type, _rev, _createdAt, _updatedAt) are omitted as they are set automatically. */ initialValue?: Partial<Omit<SanityDocument$3<TDocumentType, `${TProjectId}.${TDataset}`>, '_id' | '_type' | '_rev' | '_createdAt' | '_updatedAt'>>; } /** * Represents an action to delete an existing document. * Requires the full document handle including the document ID. * @beta */ interface DeleteDocumentAction<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string> extends DocumentHandle<TDocumentType, TDataset, TProjectId> { type: 'document.delete'; } /** * Represents an action to edit an existing document using patches. * Requires the full document handle and an array of patch operations. * @beta */ interface EditDocumentAction<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string> extends DocumentHandle<TDocumentType, TDataset, TProjectId> { type: 'document.edit'; patches?: PatchOperations[]; } /** * Represents an action to publish the draft version of a document. * Requires the full document handle. * @beta */ interface PublishDocumentAction<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string> extends DocumentHandle<TDocumentType, TDataset, TProjectId> { type: 'document.publish'; } /** * Represents an action to unpublish a document, moving its published content to a draft. * Requires the full document handle. * @beta */ interface UnpublishDocumentAction<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string> extends DocumentHandle<TDocumentType, TDataset, TProjectId> { type: 'document.unpublish'; } /** * Represents an action to discard the draft changes of a document. * Requires the full document handle. * @beta */ interface DiscardDocumentAction<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string> extends DocumentHandle<TDocumentType, TDataset, TProjectId> { type: 'document.discard'; } /** * Union type representing all possible document actions within the SDK. * @beta */ type DocumentAction<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string> = CreateDocumentAction<TDocumentType, TDataset, TProjectId> | DeleteDocumentAction<TDocumentType, TDataset, TProjectId> | EditDocumentAction<TDocumentType, TDataset, TProjectId> | PublishDocumentAction<TDocumentType, TDataset, TProjectId> | UnpublishDocumentAction<TDocumentType, TDataset, TProjectId> | DiscardDocumentAction<TDocumentType, TDataset, TProjectId>; /** * Creates a `CreateDocumentAction` object. * @param doc - A handle identifying the document type, dataset, and project. An optional `documentId` can be provided. * @param initialValue - Optional initial field values for the document. (System fields are omitted as they are set automatically.) * @returns A `CreateDocumentAction` object ready for dispatch. * @beta */ declare function createDocument<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string>(doc: DocumentTypeHandle<TDocumentType, TDataset, TProjectId>, initialValue?: Partial<Omit<SanityDocument$3<TDocumentType, `${TProjectId}.${TDataset}`>, '_id' | '_type' | '_rev' | '_createdAt' | '_updatedAt'>>): CreateDocumentAction<TDocumentType, TDataset, TProjectId>; /** * Creates a `DeleteDocumentAction` object. * @param doc - A handle uniquely identifying the document to be deleted. * @returns A `DeleteDocumentAction` object ready for dispatch. * @beta */ declare function deleteDocument<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string>(doc: DocumentHandle<TDocumentType, TDataset, TProjectId>): DeleteDocumentAction<TDocumentType, TDataset, TProjectId>; /** * Creates an `EditDocumentAction` object with patches for modifying a document. * Accepts patches in either the standard `PatchOperations` format or as a `SanityMutatePatchMutation` from `@sanity/mutate`. * * @param doc - A handle uniquely identifying the document to be edited. * @param sanityMutatePatch - A patch mutation object from `@sanity/mutate`. * @returns An `EditDocumentAction` object ready for dispatch. * @beta */ declare function editDocument<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string>(doc: DocumentHandle<TDocumentType, TDataset, TProjectId>, sanityMutatePatch: PatchMutation): EditDocumentAction<TDocumentType, TDataset, TProjectId>; /** * Creates an `EditDocumentAction` object with patches for modifying a document. * * @param doc - A handle uniquely identifying the document to be edited. * @param patches - A single patch operation or an array of patch operations. * @returns An `EditDocumentAction` object ready for dispatch. * @beta */ declare function editDocument<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string>(doc: DocumentHandle<TDocumentType, TDataset, TProjectId>, patches?: PatchOperations | PatchOperations[]): EditDocumentAction<TDocumentType, TDataset, TProjectId>; /** * Creates a `PublishDocumentAction` object. * @param doc - A handle uniquely identifying the document to be published. * @returns A `PublishDocumentAction` object ready for dispatch. * @beta */ declare function publishDocument<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string>(doc: DocumentHandle<TDocumentType, TDataset, TProjectId>): PublishDocumentAction<TDocumentType, TDataset, TProjectId>; /** * Creates an `UnpublishDocumentAction` object. * @param doc - A handle uniquely identifying the document to be unpublished. * @returns An `UnpublishDocumentAction` object ready for dispatch. * @beta */ declare function unpublishDocument<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string>(doc: DocumentHandle<TDocumentType, TDataset, TProjectId>): UnpublishDocumentAction<TDocumentType, TDataset, TProjectId>; /** * Creates a `DiscardDocumentAction` object. * @param doc - A handle uniquely identifying the document whose draft changes are to be discarded. * @returns A `DiscardDocumentAction` object ready for dispatch. * @beta */ declare function discardDocument<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string>(doc: DocumentHandle<TDocumentType, TDataset, TProjectId>): DiscardDocumentAction<TDocumentType, TDataset, TProjectId>; /** * Represents a set of document that will go into `applyMutations`. Before * applying a mutation, it's expected that all relevant documents that the * mutations affect are included, including those that do not exist yet. * Documents that don't exist have a `null` value. */ type DocumentSet<TDocument extends SanityDocument$2 = SanityDocument$2> = { [TDocumentId in string]?: TDocument | null }; /** @beta */ interface ActionsResult<TDocument extends SanityDocument$3 = SanityDocument$3> { transactionId: string; documents: DocumentSet<TDocument>; previous: DocumentSet<TDocument>; previousRevs: { [documentId: string]: string | undefined; }; appeared: string[]; updated: string[]; disappeared: string[]; submitted: () => ReturnType<SanityClient['action']>; } /** @beta */ interface ApplyDocumentActionsOptions { /** * List of actions to apply. */ actions: DocumentAction[]; /** * Optionally provide an ID to be used as this transaction ID */ transactionId?: string; /** * Set this to true to prevent this action from being batched with others. */ disableBatching?: boolean; } /** @beta */ declare function applyDocumentActions<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string>(instance: SanityInstance, options: ApplyDocumentActionsOptions): Promise<ActionsResult<SanityDocument$3<TDocumentType, `${TProjectId}.${TDataset}`>>>; /** @beta */ declare function applyDocumentActions(instance: SanityInstance, options: ApplyDocumentActionsOptions): Promise<ActionsResult>; /** * Represents a reactive state source that provides synchronized access to store data * * @remarks * Designed to work with React's useSyncExternalStore hook. Provides three ways to access data: * 1. `getCurrent()` for synchronous current value access * 2. `subscribe()` for imperative change notifications * 3. `observable` for reactive stream access * * @public */ interface StateSource<T> { /** * Subscribes to state changes with optional callback * @param onStoreChanged - Called whenever relevant state changes occur * @returns Unsubscribe function to clean up the subscription */ subscribe: (onStoreChanged?: () => void) => () => void; /** * Gets the current derived state value * * @remarks * Safe to call without subscription. Will always return the latest value * based on the current store state and selector parameters. */ getCurrent: () => T; /** * Observable stream of state values * * @remarks * Shares a single underlying subscription between all observers. Emits: * - Immediately with current value on subscription * - On every relevant state change * - Errors if selector throws */ observable: Observable<T>; } /** * Context passed to selectors when deriving state * * @remarks * Provides access to both the current state value and the Sanity instance, * allowing selectors to use configuration values when computing derived state. * The context is memoized for each state object and instance combination * to optimize performance and prevent unnecessary recalculations. * * @example * ```ts * // Using both state and instance in a selector (psuedo example) * const getUserByProjectId = createStateSourceAction( * ({ state, instance }: SelectorContext<UsersState>, options?: ProjectHandle) => { * const allUsers = state.users * const projectId = options?.projectId ?? instance.config.projectId * return allUsers.filter(user => user.projectId === projectId) * } * ) * ``` */ interface SelectorContext<TState> { /** * The current state object from the store */ state: TState; /** * The Sanity instance associated with this state */ instance: SanityInstance; } /** * Function type for selecting derived state from store state and parameters * @public */ type Selector<TState, TParams extends unknown[], TReturn> = (context: SelectorContext<TState>, ...params: TParams) => TReturn; type ActionMap = { create: 'sanity.action.document.version.create'; createLiveEdit: 'sanity.action.document.create'; discard: 'sanity.action.document.version.discard'; unpublish: 'sanity.action.document.unpublish'; delete: 'sanity.action.document.delete'; edit: 'sanity.action.document.edit'; publish: 'sanity.action.document.publish'; }; type OptimisticLock = { ifDraftRevisionId?: string; ifPublishedRevisionId?: string; }; type HttpAction = { actionType: ActionMap['create']; publishedId: string; attributes: SanityDocumentLike; } | { actionType: ActionMap['createLiveEdit']; publishedId: string; attributes: SanityDocumentLike; } | { actionType: ActionMap['discard']; versionId: string; purge?: boolean; } | { actionType: ActionMap['unpublish']; draftId: string; publishedId: string; } | { actionType: ActionMap['delete']; publishedId: string; includeDrafts?: string[]; } | { actionType: ActionMap['edit']; draftId: string; publishedId: string; patch: PatchOperations; } | ({ actionType: ActionMap['publish']; draftId: string; publishedId: string; } & OptimisticLock); /** * Represents a transaction that is queued to be applied but has not yet been * applied. A transaction will remain in a queued state until all required * documents for the transactions are available locally. */ interface QueuedTransaction { /** * the ID of this transaction. this is generated client-side. */ transactionId: string; /** * the high-level actions associated with this transaction. note that these * actions don't mention draft IDs and is meant to abstract away the draft * model from users. */ actions: DocumentAction[]; /** * An optional flag set to disable this transaction from being batched with * other transactions. */ disableBatching?: boolean; } /** * Represents a transaction that has been applied locally but has not been * committed/transitioned-to-outgoing. These transactions are visible to the * user but may be rebased upon a new working document set. Applied transactions * also contain the resulting `outgoingActions` that will be submitted to * Content Lake. These `outgoingActions` depend on the state of the working * documents so they are recomputed on rebase and are only relevant to applied * actions (we cannot compute `outgoingActions` for queued transactions because * we haven't resolved the set of documents the actions are dependent on yet). * * In order to support better conflict resolution, the original `previous` set * is saved as the `base` set. */ interface AppliedTransaction extends QueuedTransaction { /** * the resulting set of documents after the actions have been applied */ working: DocumentSet; /** * the previous set of documents before the action was applied */ previous: DocumentSet; /** * the original `previous` document set captured when this action was * originally applied. this is used as a reference point to do a 3-way merge * if this applied transaction ever needs to be reapplied on a different * set of documents. */ base: DocumentSet; /** * the `_rev`s from `previous` document set */ previousRevs: { [TDocumentId in string]?: string }; /** * a timestamp for when this transaction was applied locally */ timestamp: string; /** * the resulting HTTP actions derived from the state of the `working` document * set. these are sent to Content Lake as-is when this transaction is batched * and transitioned into an outgoing transaction. */ outgoingActions: HttpAction[]; /** * similar to `outgoingActions` but comprised of mutations instead of action. * this left here for debugging purposes but could be used to send mutations * to Content Lake instead of actions. */ outgoingMutations: Mutation[]; } /** * Represents a set of applied transactions batched into a single outgoing * transaction. An outgoing transaction is the result of batching many applied * actions. An outgoing transaction may be reverted locally if the server * does not accept it. */ interface OutgoingTransaction extends AppliedTransaction { disableBatching: boolean; batchedTransactionIds: string[]; } interface UnverifiedDocumentRevision { transactionId: string; documentId: string; previousRev: string | undefined; timestamp: string; } type Grant = 'read' | 'update' | 'create' | 'history'; /** @beta */ interface PermissionDeniedReason { type: 'precondition' | 'access'; message: string; documentId?: string; } /** @beta */ type DocumentPermissionsResult = { allowed: false; message: string; reasons: PermissionDeniedReason[]; } | { allowed: true; message?: undefined; reasons?: undefined; }; /** @beta */ type DocumentEvent = ActionErrorEvent | TransactionRevertedEvent | TransactionAcceptedEvent | DocumentRebaseErrorEvent | DocumentEditedEvent | DocumentCreatedEvent | DocumentDeletedEvent | DocumentPublishedEvent | DocumentUnpublishedEvent | DocumentDiscardedEvent; /** * @beta * Event emitted when a precondition to applying an action fails. * (For example: when trying to edit a document that no longer exists.) */ interface ActionErrorEvent { type: 'error'; documentId: string; transactionId: string; message: string; error: unknown; } /** * @beta * Event emitted when a transaction is accepted. */ interface TransactionAcceptedEvent { type: 'accepted'; outgoing: OutgoingTransaction; result: Awaited<ReturnType<SanityClient['action']>>; } /** * @beta * Event emitted when a transaction is reverted. */ interface TransactionRevertedEvent { type: 'reverted'; message: string; error: unknown; outgoing: OutgoingTransaction; } /** * @beta * Event emitted when an attempt to apply local changes to a modified remote document fails. */ interface DocumentRebaseErrorEvent { type: 'rebase-error'; documentId: string; transactionId: string; message: string; error: unknown; } /** * @beta * Event emitted when a document is edited. */ interface DocumentEditedEvent { type: 'edited'; documentId: string; outgoing: OutgoingTransaction; } /** * @beta * Event emitted when a document is created. */ interface DocumentCreatedEvent { type: 'created'; documentId: string; outgoing: OutgoingTransaction; } /** * @beta * Event emitted when a document is deleted. */ interface DocumentDeletedEvent { type: 'deleted'; documentId: string; outgoing: OutgoingTransaction; } /** * @beta * Event emitted when a document is published. */ interface DocumentPublishedEvent { type: 'published'; documentId: string; outgoing: OutgoingTransaction; } /** * @beta * Event emitted when a document is unpublished. */ interface DocumentUnpublishedEvent { type: 'unpublished'; documentId: string; outgoing: OutgoingTransaction; } /** * @beta * Event emitted when a document version is discarded. */ interface DocumentDiscardedEvent { type: 'discarded'; documentId: string; outgoing: OutgoingTransaction; } /** * Split the entire path string on dots "outside" of any brackets. * * For example: * ``` * "friends[0].name" * ``` * * becomes: * * ``` * [...ParseSegment<"friends[0]">, ...ParseSegment<"name">] * ``` * * (We use a simple recursion that splits on the first dot.) */ type PathParts<TPath extends string> = TPath extends `${infer Head}.${infer Tail}` ? [Head, ...PathParts<Tail>] : TPath extends '' ? [] : [TPath]; /** * Given a type T and an array of "access keys" Parts, recursively index into T. * * If a part is a key, it looks up that property. * If T is an array and the part is a number, it "indexes" into the element type. */ type DeepGet<TValue, TPath extends readonly (string | number)[]> = TPath extends [] ? TValue : TPath extends readonly [infer THead, ...infer TTail] ? DeepGet<TValue extends undefined | null ? undefined : THead extends keyof TValue ? TValue[THead] : THead extends number ? TValue extends readonly (infer TElement)[] ? TElement | undefined : undefined : undefined, // Key/index doesn't exist TTail extends readonly (string | number)[] ? TTail : []> : never; /** * Given a document type TDocument and a JSON Match path string TPath, * compute the type found at that path. * @beta */ type JsonMatch<TDocument, TPath extends string> = DeepGet<TDocument, PathParts<TPath>>; interface SharedListener { events: Observable<ListenEvent<SanityDocument$1>>; dispose: () => void; } interface DocumentStoreState { documentStates: { [TDocumentId in string]?: DocumentState }; queued: QueuedTransaction[]; applied: AppliedTransaction[]; outgoing?: OutgoingTransaction; grants?: Record<Grant, ExprNode>; error?: unknown; sharedListener: SharedListener; fetchDocument: (documentId: string) => Observable<SanityDocument$3 | null>; events: Subject<DocumentEvent>; } interface DocumentState { id: string; /** * the "remote" local copy that matches the server. represents the last known * server state. this gets updated every time we confirm remote patches */ remote?: SanityDocument$3 | null; /** * the current ephemeral working copy that includes local optimistic changes * that have not yet been confirmed by the server */ local?: SanityDocument$3 | null; /** * the revision that our remote document is at */ remoteRev?: string | null; /** * Array of subscription IDs. This document state will be deleted if there are * no subscribers. */ subscriptions: string[]; /** * An object keyed by transaction ID of revisions sent out but that have not * yet been verified yet. When an applied transaction is transitioned to an * outgoing transaction, it also adds unverified revisions for each document * that is part of that outgoing transaction. Transactions are submitted to * the server with a locally generated transaction ID. This way we can observe * when our transaction comes back through the shared listener. Each listener * event that comes back contains a `previousRev`. If we see our own * transaction with a different `previousRev` than expected, we can rebase our * local transactions on top of this new remote. */ unverifiedRevisions?: { [TTransactionId in string]?: UnverifiedDocumentRevision }; } /** * @beta * Options for specifying a document and optionally a path within it. */ interface DocumentOptions<TPath extends string | undefined = undefined, TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string> extends DocumentHandle<TDocumentType, TDataset, TProjectId> { path?: TPath; } /** @beta */ declare function getDocumentState<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string>(instance: SanityInstance, options: DocumentOptions<undefined, TDocumentType, TDataset, TProjectId>): StateSource<SanityDocument$3<TDocumentType, `${TProjectId}.${TDataset}`> | undefined | null>; /** @beta */ declare function getDocumentState<TPath extends string = string, TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string>(instance: SanityInstance, options: DocumentOptions<TPath, TDocumentType, TDataset, TProjectId>): StateSource<JsonMatch<SanityDocument$3<TDocumentType, `${TProjectId}.${TDataset}`>, TPath> | undefined>; /** @beta */ declare function getDocumentState<TData>(instance: SanityInstance, options: DocumentOptions<string | undefined>): StateSource<TData | undefined | null>; /** @beta */ declare function resolveDocument<TDocumentType extends string = string, TDataset extends string = string, TProjectId extends string = string>(instance: SanityInstance, docHandle: DocumentHandle<TDocumentType, TDataset, TProjectId>): Promise<SanityDocument$3<TDocumentType, `${TProjectId}.${TDataset}`> | null>; /** @beta */ declare function resolveDocument<TData extends SanityDocument$3>(instance: SanityInstance, docHandle: DocumentHandle<string, string, string>): Promise<TData | null>; /** @beta */ declare const getDocumentSyncStatus: BoundStoreAction<DocumentStoreState, [doc: DocumentHandle<string, string, string>], StateSource<boolean | undefined>>; type PermissionsStateOptions = { actions: DocumentAction[]; }; /** @beta */ declare const getPermissionsState: BoundStoreAction<DocumentStoreState, [PermissionsStateOptions], StateSource<DocumentPermissionsResult | undefined>>; /** @beta */ declare const resolvePermissions: BoundStoreAction<DocumentStoreState, [options: PermissionsStateOptions], Promise<DocumentPermissionsResult>>; /** @beta */ declare const subscribeDocumentEvents: BoundStoreAction<DocumentStoreState, [eventHandler: (e: DocumentEvent) => void], () => void>; /** * @public */ interface FavoriteStatusResponse { isFavorited: boolean; } /** * @public */ interface FavoriteDocumentContext extends DocumentHandle { resourceId: string; resourceType: StudioResource['type'] | MediaResource['type'] | CanvasResource['type']; schemaName?: string; } /** * Gets a StateSource for the favorite status of a document. * @param instance - The Sanity instance. * @param context - The document context including ID, type, and resource information. * @returns A StateSource emitting `{ isFavorited: boolean }`. * @public */ declare const getFavoritesState: BoundStoreAction<FetcherStoreState<[FavoriteDocumentContext], FavoriteStatusResponse>, [