@sanity/client
Version:
Client for retrieving, creating and patching data from Sanity.io
1,384 lines (1,324 loc) • 74.3 kB
text/typescript
import {getPublishedId, getVersionId} from '@sanity/client/csm'
import {firstValueFrom, lastValueFrom, Observable} from 'rxjs'
import {AgentActionsClient, ObservableAgentsActionClient} from './agent/actions/AgentActionsClient'
import {AssetsClient, ObservableAssetsClient} from './assets/AssetsClient'
import {defaultConfig, initConfig} from './config'
import * as dataMethods from './data/dataMethods'
import {_listen} from './data/listen'
import {LiveClient} from './data/live'
import {ObservablePatch, Patch} from './data/patch'
import {ObservableTransaction, Transaction} from './data/transaction'
import {DatasetsClient, ObservableDatasetsClient} from './datasets/DatasetsClient'
import {ObservableProjectsClient, ProjectsClient} from './projects/ProjectsClient'
import {ObservableReleasesClient, ReleasesClient} from './releases/ReleasesClient'
import type {
Action,
AllDocumentIdsMutationOptions,
AllDocumentsMutationOptions,
Any,
BaseActionOptions,
BaseMutationOptions,
ClientConfig,
ClientReturn,
FilteredResponseQueryOptions,
FirstDocumentIdMutationOptions,
FirstDocumentMutationOptions,
HttpRequest,
IdentifiedSanityDocumentStub,
InitializedClientConfig,
MultipleActionResult,
MultipleMutationResult,
Mutation,
MutationSelection,
PatchOperations,
PatchSelection,
QueryOptions,
QueryParams,
QueryWithoutParams,
RawQuerylessQueryResponse,
RawQueryResponse,
RawRequestOptions,
SanityDocument,
SanityDocumentStub,
SingleActionResult,
SingleMutationResult,
UnfilteredResponseQueryOptions,
UnfilteredResponseWithoutQuery,
} from './types'
import {ObservableUsersClient, UsersClient} from './users/UsersClient'
import {deriveDocumentVersionId, getDocumentVersionId} from './util/createVersionId'
export type {
_listen,
AssetsClient,
DatasetsClient,
LiveClient,
ObservableAssetsClient,
ObservableDatasetsClient,
ObservableProjectsClient,
ObservableUsersClient,
ProjectsClient,
UsersClient,
}
/** @public */
export class ObservableSanityClient {
assets: ObservableAssetsClient
datasets: ObservableDatasetsClient
live: LiveClient
projects: ObservableProjectsClient
users: ObservableUsersClient
agent: {
action: ObservableAgentsActionClient
}
releases: ObservableReleasesClient
/**
* Private properties
*/
#clientConfig: InitializedClientConfig
#httpRequest: HttpRequest
/**
* Instance properties
*/
listen = _listen
constructor(httpRequest: HttpRequest, config: ClientConfig = defaultConfig) {
this.config(config)
this.#httpRequest = httpRequest
this.assets = new ObservableAssetsClient(this, this.#httpRequest)
this.datasets = new ObservableDatasetsClient(this, this.#httpRequest)
this.live = new LiveClient(this)
this.projects = new ObservableProjectsClient(this, this.#httpRequest)
this.users = new ObservableUsersClient(this, this.#httpRequest)
this.agent = {
action: new ObservableAgentsActionClient(this, this.#httpRequest),
}
this.releases = new ObservableReleasesClient(this, this.#httpRequest)
}
/**
* Clone the client - returns a new instance
*/
clone(): ObservableSanityClient {
return new ObservableSanityClient(this.#httpRequest, this.config())
}
/**
* Returns the current client configuration
*/
config(): InitializedClientConfig
/**
* Reconfigure the client. Note that this _mutates_ the current client.
*/
config(newConfig?: Partial<ClientConfig>): this
config(newConfig?: Partial<ClientConfig>): ClientConfig | this {
if (newConfig === undefined) {
return {...this.#clientConfig}
}
if (this.#clientConfig && this.#clientConfig.allowReconfigure === false) {
throw new Error(
'Existing client instance cannot be reconfigured - use `withConfig(newConfig)` to return a new client',
)
}
this.#clientConfig = initConfig(newConfig, this.#clientConfig || {})
return this
}
/**
* Clone the client with a new (partial) configuration.
*
* @param newConfig - New client configuration properties, shallowly merged with existing configuration
*/
withConfig(newConfig?: Partial<ClientConfig>): ObservableSanityClient {
const thisConfig = this.config()
return new ObservableSanityClient(this.#httpRequest, {
...thisConfig,
...newConfig,
stega: {
...(thisConfig.stega || {}),
...(typeof newConfig?.stega === 'boolean'
? {enabled: newConfig.stega}
: newConfig?.stega || {}),
},
})
}
/**
* Perform a GROQ-query against the configured dataset.
*
* @param query - GROQ-query to perform
*/
fetch<
R = Any,
Q extends QueryWithoutParams = QueryWithoutParams,
const G extends string = string,
>(query: G, params?: Q | QueryWithoutParams): Observable<ClientReturn<G, R>>
/**
* Perform a GROQ-query against the configured dataset.
*
* @param query - GROQ-query to perform
* @param params - Optional query parameters
* @param options - Optional request options
*/
fetch<
R = Any,
Q extends QueryWithoutParams | QueryParams = QueryParams,
const G extends string = string,
>(
query: G,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options?: FilteredResponseQueryOptions,
): Observable<ClientReturn<G, R>>
/**
* Perform a GROQ-query against the configured dataset.
*
* @param query - GROQ-query to perform
* @param params - Optional query parameters
* @param options - Request options
*/
fetch<
R = Any,
Q extends QueryWithoutParams | QueryParams = QueryParams,
const G extends string = string,
>(
query: string,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options: UnfilteredResponseQueryOptions,
): Observable<RawQueryResponse<ClientReturn<G, R>>>
/**
* Perform a GROQ-query against the configured dataset.
*
* @param query - GROQ-query to perform
* @param params - Optional query parameters
* @param options - Request options
*/
fetch<
R = Any,
Q extends QueryWithoutParams | QueryParams = QueryParams,
const G extends string = string,
>(
query: G,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options: UnfilteredResponseWithoutQuery,
): Observable<RawQuerylessQueryResponse<ClientReturn<G, R>>>
fetch<R, Q, const G extends string>(
query: G,
params?: Q,
options?: QueryOptions,
): Observable<RawQueryResponse<R> | R> {
return dataMethods._fetch<R, Q>(
this,
this.#httpRequest,
this.#clientConfig.stega,
query,
params,
options,
)
}
/**
* Fetch a single document with the given ID.
*
* @param id - Document ID to fetch
* @param options - Request options
*/
getDocument<R extends Record<string, Any> = Record<string, Any>>(
id: string,
options?: {signal?: AbortSignal; tag?: string; releaseId?: string},
): Observable<SanityDocument<R> | undefined> {
return dataMethods._getDocument<R>(this, this.#httpRequest, id, options)
}
/**
* Fetch multiple documents in one request.
* Should be used sparingly - performing a query is usually a better option.
* The order/position of documents is preserved based on the original array of IDs.
* If any of the documents are missing, they will be replaced by a `null` entry in the returned array
*
* @param ids - Document IDs to fetch
* @param options - Request options
*/
getDocuments<R extends Record<string, Any> = Record<string, Any>>(
ids: string[],
options?: {tag?: string},
): Observable<(SanityDocument<R> | null)[]> {
return dataMethods._getDocuments<R>(this, this.#httpRequest, ids, options)
}
/**
* Create a document. Requires a `_type` property. If no `_id` is provided, it will be generated by the database.
* Returns an observable that resolves to the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
create<R extends Record<string, Any> = Record<string, Any>>(
document: SanityDocumentStub<R>,
options: FirstDocumentMutationOptions,
): Observable<SanityDocument<R>>
/**
* Create a document. Requires a `_type` property. If no `_id` is provided, it will be generated by the database.
* Returns an observable that resolves to an array containing the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
create<R extends Record<string, Any> = Record<string, Any>>(
document: SanityDocumentStub<R>,
options: AllDocumentsMutationOptions,
): Observable<SanityDocument<R>[]>
/**
* Create a document. Requires a `_type` property. If no `_id` is provided, it will be generated by the database.
* Returns an observable that resolves to a mutation result object containing the ID of the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
create<R extends Record<string, Any> = Record<string, Any>>(
document: SanityDocumentStub<R>,
options: FirstDocumentIdMutationOptions,
): Observable<SingleMutationResult>
/**
* Create a document. Requires a `_type` property. If no `_id` is provided, it will be generated by the database.
* Returns an observable that resolves to a mutation result object containing the ID of the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
create<R extends Record<string, Any> = Record<string, Any>>(
document: SanityDocumentStub<R>,
options: AllDocumentIdsMutationOptions,
): Observable<MultipleMutationResult>
/**
* Create a document. Requires a `_type` property. If no `_id` is provided, it will be generated by the database.
* Returns an observable that resolves to the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
create<R extends Record<string, Any> = Record<string, Any>>(
document: SanityDocumentStub<R>,
options?: BaseMutationOptions,
): Observable<SanityDocument<R>>
create<R extends Record<string, Any> = Record<string, Any>>(
document: SanityDocumentStub<R>,
options?:
| AllDocumentIdsMutationOptions
| AllDocumentsMutationOptions
| BaseMutationOptions
| FirstDocumentIdMutationOptions
| FirstDocumentMutationOptions,
): Observable<
SanityDocument<R> | SanityDocument<R>[] | SingleMutationResult | MultipleMutationResult
> {
return dataMethods._create<R>(this, this.#httpRequest, document, 'create', options)
}
/**
* Create a document if no document with the same ID already exists.
* Returns an observable that resolves to the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
createIfNotExists<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options: FirstDocumentMutationOptions,
): Observable<SanityDocument<R>>
/**
* Create a document if no document with the same ID already exists.
* Returns an observable that resolves to an array containing the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
createIfNotExists<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options: AllDocumentsMutationOptions,
): Observable<SanityDocument<R>[]>
/**
* Create a document if no document with the same ID already exists.
* Returns an observable that resolves to a mutation result object containing the ID of the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
createIfNotExists<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options: FirstDocumentIdMutationOptions,
): Observable<SingleMutationResult>
/**
* Create a document if no document with the same ID already exists.
* Returns an observable that resolves to a mutation result object containing the ID of the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
createIfNotExists<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options: AllDocumentIdsMutationOptions,
): Observable<MultipleMutationResult>
/**
* Create a document if no document with the same ID already exists.
* Returns an observable that resolves to the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
createIfNotExists<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options?: BaseMutationOptions,
): Observable<SanityDocument<R>>
createIfNotExists<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options?:
| AllDocumentIdsMutationOptions
| AllDocumentsMutationOptions
| BaseMutationOptions
| FirstDocumentIdMutationOptions
| FirstDocumentMutationOptions,
): Observable<
SanityDocument<R> | SanityDocument<R>[] | SingleMutationResult | MultipleMutationResult
> {
return dataMethods._createIfNotExists<R>(this, this.#httpRequest, document, options)
}
/**
* Create a document if it does not exist, or replace a document with the same document ID
* Returns an observable that resolves to the created document.
*
* @param document - Document to either create or replace
* @param options - Mutation options
*/
createOrReplace<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options: FirstDocumentMutationOptions,
): Observable<SanityDocument<R>>
/**
* Create a document if it does not exist, or replace a document with the same document ID
* Returns an observable that resolves to an array containing the created document.
*
* @param document - Document to either create or replace
* @param options - Mutation options
*/
createOrReplace<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options: AllDocumentsMutationOptions,
): Observable<SanityDocument<R>[]>
/**
* Create a document if it does not exist, or replace a document with the same document ID
* Returns an observable that resolves to a mutation result object containing the ID of the created document.
*
* @param document - Document to either create or replace
* @param options - Mutation options
*/
createOrReplace<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options: FirstDocumentIdMutationOptions,
): Observable<SingleMutationResult>
/**
* Create a document if it does not exist, or replace a document with the same document ID
* Returns an observable that resolves to a mutation result object containing the created document ID.
*
* @param document - Document to either create or replace
* @param options - Mutation options
*/
createOrReplace<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options: AllDocumentIdsMutationOptions,
): Observable<MultipleMutationResult>
/**
* Create a document if it does not exist, or replace a document with the same document ID
* Returns an observable that resolves to the created document.
*
* @param document - Document to either create or replace
* @param options - Mutation options
*/
createOrReplace<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options?: BaseMutationOptions,
): Observable<SanityDocument<R>>
createOrReplace<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options?:
| AllDocumentIdsMutationOptions
| AllDocumentsMutationOptions
| BaseMutationOptions
| FirstDocumentIdMutationOptions
| FirstDocumentMutationOptions,
): Observable<
SanityDocument<R> | SanityDocument<R>[] | SingleMutationResult | MultipleMutationResult
> {
return dataMethods._createOrReplace<R>(this, this.#httpRequest, document, options)
}
/**
* @public
*
* Creates a new version of a published document.
*
* @remarks
* * Requires a document with a `_type` property.
* * Creating a version with no `releaseId` will create a new draft version of the published document.
* * If the `document._id` is defined, it should be a draft or release version ID that matches the version ID generated from `publishedId` and `releaseId`.
* * If the `document._id` is not defined, it will be generated from `publishedId` and `releaseId`.
* * To create a version of an unpublished document, use the `client.create` method.
*
* @category Versions
*
* @param params - Version action parameters:
* - `document` - The document to create as a new version (must include `_type`).
* - `publishedId` - The ID of the published document being versioned.
* - `releaseId` - The ID of the release to create the version for.
* @param options - Additional action options.
* @returns an observable that resolves to the `transactionId`.
*
* @example Creating a new version of a published document with a generated version ID
* ```ts
* client.observable.createVersion({
* // The document does not need to include an `_id` property since it will be generated from `publishedId` and `releaseId`
* document: {_type: 'myDocument', title: 'My Document'},
* publishedId: 'myDocument',
* releaseId: 'myRelease',
* })
*
* // The following document will be created:
* // {
* // _id: 'versions.myRelease.myDocument',
* // _type: 'myDocument',
* // title: 'My Document',
* // }
* ```
*
* @example Creating a new version of a published document with a specified version ID
* ```ts
* client.observable.createVersion({
* document: {_type: 'myDocument', _id: 'versions.myRelease.myDocument', title: 'My Document'},
* // `publishedId` and `releaseId` are not required since `document._id` has been specified
* })
*
* // The following document will be created:
* // {
* // _id: 'versions.myRelease.myDocument',
* // _type: 'myDocument',
* // title: 'My Document',
* // }
* ```
*
* @example Creating a new draft version of a published document
* ```ts
* client.observable.createVersion({
* document: {_type: 'myDocument', title: 'My Document'},
* publishedId: 'myDocument',
* })
*
* // The following document will be created:
* // {
* // _id: 'drafts.myDocument',
* // _type: 'myDocument',
* // title: 'My Document',
* // }
* ```
*/
createVersion<R extends Record<string, Any>>(
args: {
document: SanityDocumentStub<R>
publishedId: string
releaseId?: string
},
options?: BaseActionOptions,
): Observable<SingleActionResult | MultipleActionResult>
createVersion<R extends Record<string, Any>>(
args: {
document: IdentifiedSanityDocumentStub<R>
publishedId?: string
releaseId?: string
},
options?: BaseActionOptions,
): Observable<SingleActionResult | MultipleActionResult>
createVersion<R extends Record<string, Any>>(
{
document,
publishedId,
releaseId,
}: {
document: SanityDocumentStub<R> | IdentifiedSanityDocumentStub<R>
publishedId?: string
releaseId?: string
},
options?: BaseActionOptions,
): Observable<SingleActionResult | MultipleActionResult> {
const documentVersionId = deriveDocumentVersionId('createVersion', {
document,
publishedId,
releaseId,
})
const documentVersion = {...document, _id: documentVersionId}
const versionPublishedId = publishedId || getPublishedId(document._id)
return dataMethods._createVersion<R>(
this,
this.#httpRequest,
documentVersion,
versionPublishedId,
options,
)
}
/**
* Deletes a document with the given document ID.
* Returns an observable that resolves to the deleted document.
*
* @param id - Document ID to delete
* @param options - Options for the mutation
*/
delete<R extends Record<string, Any> = Record<string, Any>>(
id: string,
options: FirstDocumentMutationOptions,
): Observable<SanityDocument<R>>
/**
* Deletes a document with the given document ID.
* Returns an observable that resolves to an array containing the deleted document.
*
* @param id - Document ID to delete
* @param options - Options for the mutation
*/
delete<R extends Record<string, Any> = Record<string, Any>>(
id: string,
options: AllDocumentsMutationOptions,
): Observable<SanityDocument<R>[]>
/**
* Deletes a document with the given document ID.
* Returns an observable that resolves to a mutation result object containing the deleted document ID.
*
* @param id - Document ID to delete
* @param options - Options for the mutation
*/
delete(id: string, options: FirstDocumentIdMutationOptions): Observable<SingleMutationResult>
/**
* Deletes a document with the given document ID.
* Returns an observable that resolves to a mutation result object containing the deleted document ID.
*
* @param id - Document ID to delete
* @param options - Options for the mutation
*/
delete(id: string, options: AllDocumentIdsMutationOptions): Observable<MultipleMutationResult>
/**
* Deletes a document with the given document ID.
* Returns an observable that resolves to the deleted document.
*
* @param id - Document ID to delete
* @param options - Options for the mutation
*/
delete<R extends Record<string, Any> = Record<string, Any>>(
id: string,
options?: BaseMutationOptions,
): Observable<SanityDocument<R>>
/**
* Deletes one or more documents matching the given query or document ID.
* Returns an observable that resolves to first deleted document.
*
* @param selection - An object with either an `id` or `query` key defining what to delete
* @param options - Options for the mutation
*/
delete<R extends Record<string, Any> = Record<string, Any>>(
selection: MutationSelection,
options: FirstDocumentMutationOptions,
): Observable<SanityDocument<R>>
/**
* Deletes one or more documents matching the given query or document ID.
* Returns an observable that resolves to an array containing the deleted documents.
*
* @param selection - An object with either an `id` or `query` key defining what to delete
* @param options - Options for the mutation
*/
delete<R extends Record<string, Any> = Record<string, Any>>(
selection: MutationSelection,
options: AllDocumentsMutationOptions,
): Observable<SanityDocument<R>[]>
/**
* Deletes one or more documents matching the given query or document ID.
* Returns an observable that resolves to a mutation result object containing the ID of the first deleted document.
*
* @param selection - An object with either an `id` or `query` key defining what to delete
* @param options - Options for the mutation
*/
delete(
selection: MutationSelection,
options: FirstDocumentIdMutationOptions,
): Observable<SingleMutationResult>
/**
* Deletes one or more documents matching the given query or document ID.
* Returns an observable that resolves to a mutation result object containing the document IDs that were deleted.
*
* @param selection - An object with either an `id` or `query` key defining what to delete
* @param options - Options for the mutation
*/
delete(
selection: MutationSelection,
options: AllDocumentIdsMutationOptions,
): Observable<MultipleMutationResult>
/**
* Deletes one or more documents matching the given query or document ID.
* Returns an observable that resolves to first deleted document.
*
* @param selection - An object with either an `id` or `query` key defining what to delete
* @param options - Options for the mutation
*/
delete<R extends Record<string, Any> = Record<string, Any>>(
selection: MutationSelection,
options?: BaseMutationOptions,
): Observable<SanityDocument<R>>
delete<R extends Record<string, Any> = Record<string, Any>>(
selection: string | MutationSelection,
options?:
| AllDocumentIdsMutationOptions
| AllDocumentsMutationOptions
| BaseMutationOptions
| FirstDocumentIdMutationOptions
| FirstDocumentMutationOptions,
): Observable<
SanityDocument<R> | SanityDocument<R>[] | SingleMutationResult | MultipleMutationResult
> {
return dataMethods._delete<R>(this, this.#httpRequest, selection, options)
}
/**
* @public
*
* Deletes the draft or release version of a document.
*
* @remarks
* * Discarding a version with no `releaseId` will discard the draft version of the published document.
* * If the draft or release version does not exist, any error will throw.
*
* @param params - Version action parameters:
* - `releaseId` - The ID of the release to discard the document from.
* - `publishedId` - The published ID of the document to discard.
* @param purge - if `true` the document history is also discarded.
* @param options - Additional action options.
* @returns an observable that resolves to the `transactionId`.
*
* @example Discarding a release version of a document
* ```ts
* client.observable.discardVersion({publishedId: 'myDocument', releaseId: 'myRelease'})
* // The document with the ID `versions.myRelease.myDocument` will be discarded.
* ```
*
* @example Discarding a draft version of a document
* ```ts
* client.observable.discardVersion({publishedId: 'myDocument'})
* // The document with the ID `drafts.myDocument` will be discarded.
* ```
*/
discardVersion(
{releaseId, publishedId}: {releaseId?: string; publishedId: string},
purge?: boolean,
options?: BaseActionOptions,
): Observable<SingleActionResult | MultipleActionResult> {
const documentVersionId = getDocumentVersionId(publishedId, releaseId)
return dataMethods._discardVersion(this, this.#httpRequest, documentVersionId, purge, options)
}
/**
* @public
*
* Replaces an existing version document.
*
* @remarks
* * Requires a document with a `_type` property.
* * If the `document._id` is defined, it should be a draft or release version ID that matches the version ID generated from `publishedId` and `releaseId`.
* * If the `document._id` is not defined, it will be generated from `publishedId` and `releaseId`.
* * Replacing a version with no `releaseId` will replace the draft version of the published document.
* * At least one of the **version** or **published** documents must exist.
*
* @param params - Version action parameters:
* - `document` - The new document to replace the version with.
* - `releaseId` - The ID of the release where the document version is replaced.
* - `publishedId` - The ID of the published document to replace.
* @param options - Additional action options.
* @returns an observable that resolves to the `transactionId`.
*
* @example Replacing a release version of a published document with a generated version ID
* ```ts
* client.observable.replaceVersion({
* document: {_type: 'myDocument', title: 'My Document'},
* publishedId: 'myDocument',
* releaseId: 'myRelease',
* })
*
* // The following document will be patched:
* // {
* // _id: 'versions.myRelease.myDocument',
* // _type: 'myDocument',
* // title: 'My Document',
* // }
* ```
*
* @example Replacing a release version of a published document with a specified version ID
* ```ts
* client.observable.replaceVersion({
* document: {_type: 'myDocument', _id: 'versions.myRelease.myDocument', title: 'My Document'},
* // `publishedId` and `releaseId` are not required since `document._id` has been specified
* })
*
* // The following document will be patched:
* // {
* // _id: 'versions.myRelease.myDocument',
* // _type: 'myDocument',
* // title: 'My Document',
* // }
* ```
*
* @example Replacing a draft version of a published document
* ```ts
* client.observable.replaceVersion({
* document: {_type: 'myDocument', title: 'My Document'},
* publishedId: 'myDocument',
* })
*
* // The following document will be patched:
* // {
* // _id: 'drafts.myDocument',
* // _type: 'myDocument',
* // title: 'My Document',
* // }
* ```
*/
replaceVersion<R extends Record<string, Any>>(
args: {
document: SanityDocumentStub<R>
publishedId: string
releaseId?: string
},
options?: BaseActionOptions,
): Observable<SingleActionResult | MultipleActionResult>
replaceVersion<R extends Record<string, Any>>(
args: {
document: IdentifiedSanityDocumentStub<R>
publishedId?: string
releaseId?: string
},
options?: BaseActionOptions,
): Observable<SingleActionResult | MultipleActionResult>
replaceVersion<R extends Record<string, Any>>(
{
document,
publishedId,
releaseId,
}: {
document: SanityDocumentStub<R> | IdentifiedSanityDocumentStub<R>
publishedId?: string
releaseId?: string
},
options?: BaseActionOptions,
): Observable<SingleActionResult | MultipleActionResult> {
const documentVersionId = deriveDocumentVersionId('replaceVersion', {
document,
publishedId,
releaseId,
})
const documentVersion = {...document, _id: documentVersionId}
return dataMethods._replaceVersion<R>(this, this.#httpRequest, documentVersion, options)
}
/**
* @public
*
* Used to indicate when a document within a release should be unpublished when
* the release is run.
*
* @remarks
* * If the published document does not exist, an error will be thrown.
*
* @param params - Version action parameters:
* - `releaseId` - The ID of the release to unpublish the document from.
* - `publishedId` - The published ID of the document to unpublish.
* @param options - Additional action options.
* @returns an observable that resolves to the `transactionId`.
*
* @example Unpublishing a release version of a published document
* ```ts
* client.observable.unpublishVersion({publishedId: 'myDocument', releaseId: 'myRelease'})
* // The document with the ID `versions.myRelease.myDocument` will be unpublished. when `myRelease` is run.
* ```
*/
unpublishVersion(
{releaseId, publishedId}: {releaseId: string; publishedId: string},
options?: BaseActionOptions,
): Observable<SingleActionResult | MultipleActionResult> {
const versionId = getVersionId(publishedId, releaseId)
return dataMethods._unpublishVersion(this, this.#httpRequest, versionId, publishedId, options)
}
/**
* Perform mutation operations against the configured dataset
* Returns an observable that resolves to the first mutated document.
*
* @param operations - Mutation operations to execute
* @param options - Mutation options
*/
mutate<R extends Record<string, Any> = Record<string, Any>>(
operations: Mutation<R>[] | ObservablePatch | ObservableTransaction,
options: FirstDocumentMutationOptions,
): Observable<SanityDocument<R>>
/**
* Perform mutation operations against the configured dataset.
* Returns an observable that resolves to an array of the mutated documents.
*
* @param operations - Mutation operations to execute
* @param options - Mutation options
*/
mutate<R extends Record<string, Any> = Record<string, Any>>(
operations: Mutation<R>[] | ObservablePatch | ObservableTransaction,
options: AllDocumentsMutationOptions,
): Observable<SanityDocument<R>[]>
/**
* Perform mutation operations against the configured dataset
* Returns an observable that resolves to a mutation result object containing the document ID of the first mutated document.
*
* @param operations - Mutation operations to execute
* @param options - Mutation options
*/
mutate<R extends Record<string, Any> = Record<string, Any>>(
operations: Mutation<R>[] | ObservablePatch | ObservableTransaction,
options: FirstDocumentIdMutationOptions,
): Observable<SingleMutationResult>
/**
* Perform mutation operations against the configured dataset
* Returns an observable that resolves to a mutation result object containing the mutated document IDs.
*
* @param operations - Mutation operations to execute
* @param options - Mutation options
*/
mutate<R extends Record<string, Any> = Record<string, Any>>(
operations: Mutation<R>[] | ObservablePatch | ObservableTransaction,
options: AllDocumentIdsMutationOptions,
): Observable<MultipleMutationResult>
/**
* Perform mutation operations against the configured dataset
* Returns an observable that resolves to the first mutated document.
*
* @param operations - Mutation operations to execute
* @param options - Mutation options
*/
mutate<R extends Record<string, Any> = Record<string, Any>>(
operations: Mutation<R>[] | ObservablePatch | ObservableTransaction,
options?: BaseMutationOptions,
): Observable<SanityDocument<R>>
mutate<R extends Record<string, Any> = Record<string, Any>>(
operations: Mutation<R>[] | ObservablePatch | ObservableTransaction,
options?:
| FirstDocumentMutationOptions
| AllDocumentsMutationOptions
| FirstDocumentIdMutationOptions
| AllDocumentIdsMutationOptions
| BaseMutationOptions,
): Observable<
SanityDocument<R> | SanityDocument<R>[] | SingleMutationResult | MultipleMutationResult
> {
return dataMethods._mutate<R>(this, this.#httpRequest, operations, options)
}
/**
* Create a new buildable patch of operations to perform
*
* @param documentId - Document ID to patch
* @param operations - Optional object of patch operations to initialize the patch instance with
* @returns Patch instance - call `.commit()` to perform the operations defined
*/
patch(documentId: string, operations?: PatchOperations): ObservablePatch
/**
* Create a new buildable patch of operations to perform
*
* @param documentIds - Array of document IDs to patch
* @param operations - Optional object of patch operations to initialize the patch instance with
* @returns Patch instance - call `.commit()` to perform the operations defined
*/
patch(documentIds: string[], operations?: PatchOperations): ObservablePatch
/**
* Create a new buildable patch of operations to perform
*
* @param selection - An object with `query` and optional `params`, defining which document(s) to patch
* @param operations - Optional object of patch operations to initialize the patch instance with
* @returns Patch instance - call `.commit()` to perform the operations defined
*/
patch(selection: MutationSelection, operations?: PatchOperations): ObservablePatch
/**
* Create a new buildable patch of operations to perform
*
* @param selection - Document ID, an array of document IDs, or an object with `query` and optional `params`, defining which document(s) to patch
* @param operations - Optional object of patch operations to initialize the patch instance with
* @returns Patch instance - call `.commit()` to perform the operations defined
*/
patch(selection: PatchSelection, operations?: PatchOperations): ObservablePatch {
return new ObservablePatch(selection, operations, this)
}
/**
* Create a new transaction of mutations
*
* @param operations - Optional array of mutation operations to initialize the transaction instance with
*/
transaction<R extends Record<string, Any> = Record<string, Any>>(
operations?: Mutation<R>[],
): ObservableTransaction {
return new ObservableTransaction(operations, this)
}
/**
* Perform action operations against the configured dataset
*
* @param operations - Action operation(s) to execute
* @param options - Action options
*/
action(
operations: Action | Action[],
options?: BaseActionOptions,
): Observable<SingleActionResult | MultipleActionResult> {
return dataMethods._action(this, this.#httpRequest, operations, options)
}
/**
* Perform an HTTP request against the Sanity API
*
* @param options - Request options
*/
request<R = Any>(options: RawRequestOptions): Observable<R> {
return dataMethods._request(this, this.#httpRequest, options)
}
/**
* Get a Sanity API URL for the URI provided
*
* @param uri - URI/path to build URL for
* @param canUseCdn - Whether or not to allow using the API CDN for this route
*/
getUrl(uri: string, canUseCdn?: boolean): string {
return dataMethods._getUrl(this, uri, canUseCdn)
}
/**
* Get a Sanity API URL for the data operation and path provided
*
* @param operation - Data operation (eg `query`, `mutate`, `listen` or similar)
* @param path - Path to append after the operation
*/
getDataUrl(operation: string, path?: string): string {
return dataMethods._getDataUrl(this, operation, path)
}
}
/** @public */
export class SanityClient {
assets: AssetsClient
datasets: DatasetsClient
live: LiveClient
projects: ProjectsClient
users: UsersClient
agent: {
action: AgentActionsClient
}
releases: ReleasesClient
/**
* Observable version of the Sanity client, with the same configuration as the promise-based one
*/
observable: ObservableSanityClient
/**
* Private properties
*/
#clientConfig: InitializedClientConfig
#httpRequest: HttpRequest
/**
* Instance properties
*/
listen = _listen
constructor(httpRequest: HttpRequest, config: ClientConfig = defaultConfig) {
this.config(config)
this.#httpRequest = httpRequest
this.assets = new AssetsClient(this, this.#httpRequest)
this.datasets = new DatasetsClient(this, this.#httpRequest)
this.live = new LiveClient(this)
this.projects = new ProjectsClient(this, this.#httpRequest)
this.users = new UsersClient(this, this.#httpRequest)
this.agent = {
action: new AgentActionsClient(this, this.#httpRequest),
}
this.releases = new ReleasesClient(this, this.#httpRequest)
this.observable = new ObservableSanityClient(httpRequest, config)
}
/**
* Clone the client - returns a new instance
*/
clone(): SanityClient {
return new SanityClient(this.#httpRequest, this.config())
}
/**
* Returns the current client configuration
*/
config(): InitializedClientConfig
/**
* Reconfigure the client. Note that this _mutates_ the current client.
*/
config(newConfig?: Partial<ClientConfig>): this
config(newConfig?: Partial<ClientConfig>): ClientConfig | this {
if (newConfig === undefined) {
return {...this.#clientConfig}
}
if (this.#clientConfig && this.#clientConfig.allowReconfigure === false) {
throw new Error(
'Existing client instance cannot be reconfigured - use `withConfig(newConfig)` to return a new client',
)
}
if (this.observable) {
this.observable.config(newConfig)
}
this.#clientConfig = initConfig(newConfig, this.#clientConfig || {})
return this
}
/**
* Clone the client with a new (partial) configuration.
*
* @param newConfig - New client configuration properties, shallowly merged with existing configuration
*/
withConfig(newConfig?: Partial<ClientConfig>): SanityClient {
const thisConfig = this.config()
return new SanityClient(this.#httpRequest, {
...thisConfig,
...newConfig,
stega: {
...(thisConfig.stega || {}),
...(typeof newConfig?.stega === 'boolean'
? {enabled: newConfig.stega}
: newConfig?.stega || {}),
},
})
}
/**
* Perform a GROQ-query against the configured dataset.
*
* @param query - GROQ-query to perform
*/
fetch<
R = Any,
Q extends QueryWithoutParams = QueryWithoutParams,
const G extends string = string,
>(query: G, params?: Q | QueryWithoutParams): Promise<ClientReturn<G, R>>
/**
* Perform a GROQ-query against the configured dataset.
*
* @param query - GROQ-query to perform
* @param params - Optional query parameters
* @param options - Optional request options
*/
fetch<
R = Any,
Q extends QueryWithoutParams | QueryParams = QueryParams,
const G extends string = string,
>(
query: G,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options?: FilteredResponseQueryOptions,
): Promise<ClientReturn<G, R>>
/**
* Perform a GROQ-query against the configured dataset.
*
* @param query - GROQ-query to perform
* @param params - Optional query parameters
* @param options - Request options
*/
fetch<
R = Any,
Q extends QueryWithoutParams | QueryParams = QueryParams,
const G extends string = string,
>(
query: G,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options: UnfilteredResponseQueryOptions,
): Promise<RawQueryResponse<ClientReturn<G, R>>>
/**
* Perform a GROQ-query against the configured dataset.
*
* @param query - GROQ-query to perform
* @param params - Optional query parameters
* @param options - Request options
*/
fetch<
R = Any,
Q extends QueryWithoutParams | QueryParams = QueryParams,
const G extends string = string,
>(
query: G,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options: UnfilteredResponseWithoutQuery,
): Promise<RawQuerylessQueryResponse<ClientReturn<G, R>>>
fetch<R, Q, const G extends string>(
query: G,
params?: Q,
options?: QueryOptions,
): Promise<RawQueryResponse<ClientReturn<G, R>> | ClientReturn<G, R>> {
return lastValueFrom(
dataMethods._fetch<ClientReturn<G, R>, Q>(
this,
this.#httpRequest,
this.#clientConfig.stega,
query,
params,
options,
),
)
}
/**
* Fetch a single document with the given ID.
*
* @param id - Document ID to fetch
* @param options - Request options
*/
getDocument<R extends Record<string, Any> = Record<string, Any>>(
id: string,
options?: {signal?: AbortSignal; tag?: string; releaseId?: string},
): Promise<SanityDocument<R> | undefined> {
return lastValueFrom(dataMethods._getDocument<R>(this, this.#httpRequest, id, options))
}
/**
* Fetch multiple documents in one request.
* Should be used sparingly - performing a query is usually a better option.
* The order/position of documents is preserved based on the original array of IDs.
* If any of the documents are missing, they will be replaced by a `null` entry in the returned array
*
* @param ids - Document IDs to fetch
* @param options - Request options
*/
getDocuments<R extends Record<string, Any> = Record<string, Any>>(
ids: string[],
options?: {signal?: AbortSignal; tag?: string},
): Promise<(SanityDocument<R> | null)[]> {
return lastValueFrom(dataMethods._getDocuments<R>(this, this.#httpRequest, ids, options))
}
/**
* Create a document. Requires a `_type` property. If no `_id` is provided, it will be generated by the database.
* Returns a promise that resolves to the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
create<R extends Record<string, Any> = Record<string, Any>>(
document: SanityDocumentStub<R>,
options: FirstDocumentMutationOptions,
): Promise<SanityDocument<R>>
/**
* Create a document. Requires a `_type` property. If no `_id` is provided, it will be generated by the database.
* Returns a promise that resolves to an array containing the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
create<R extends Record<string, Any> = Record<string, Any>>(
document: SanityDocumentStub<R>,
options: AllDocumentsMutationOptions,
): Promise<SanityDocument<R>[]>
/**
* Create a document. Requires a `_type` property. If no `_id` is provided, it will be generated by the database.
* Returns a promise that resolves to a mutation result object containing the ID of the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
create<R extends Record<string, Any> = Record<string, Any>>(
document: SanityDocumentStub<R>,
options: FirstDocumentIdMutationOptions,
): Promise<SingleMutationResult>
/**
* Create a document. Requires a `_type` property. If no `_id` is provided, it will be generated by the database.
* Returns a promise that resolves to a mutation result object containing the ID of the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
create<R extends Record<string, Any> = Record<string, Any>>(
document: SanityDocumentStub<R>,
options: AllDocumentIdsMutationOptions,
): Promise<MultipleMutationResult>
/**
* Create a document. Requires a `_type` property. If no `_id` is provided, it will be generated by the database.
* Returns a promise that resolves to the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
create<R extends Record<string, Any> = Record<string, Any>>(
document: SanityDocumentStub<R>,
options?: BaseMutationOptions,
): Promise<SanityDocument<R>>
create<R extends Record<string, Any> = Record<string, Any>>(
document: SanityDocumentStub<R>,
options?:
| AllDocumentIdsMutationOptions
| AllDocumentsMutationOptions
| BaseMutationOptions
| FirstDocumentIdMutationOptions
| FirstDocumentMutationOptions,
): Promise<
SanityDocument<R> | SanityDocument<R>[] | SingleMutationResult | MultipleMutationResult
> {
return lastValueFrom(
dataMethods._create<R>(this, this.#httpRequest, document, 'create', options),
)
}
/**
* Create a document if no document with the same ID already exists.
* Returns a promise that resolves to the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
createIfNotExists<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options: FirstDocumentMutationOptions,
): Promise<SanityDocument<R>>
/**
* Create a document if no document with the same ID already exists.
* Returns a promise that resolves to an array containing the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
createIfNotExists<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options: AllDocumentsMutationOptions,
): Promise<SanityDocument<R>[]>
/**
* Create a document if no document with the same ID already exists.
* Returns a promise that resolves to a mutation result object containing the ID of the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
createIfNotExists<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options: FirstDocumentIdMutationOptions,
): Promise<SingleMutationResult>
/**
* Create a document if no document with the same ID already exists.
* Returns a promise that resolves to a mutation result object containing the ID of the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
createIfNotExists<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options: AllDocumentIdsMutationOptions,
): Promise<MultipleMutationResult>
/**
* Create a document if no document with the same ID already exists.
* Returns a promise that resolves to the created document.
*
* @param document - Document to create
* @param options - Mutation options
*/
createIfNotExists<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options?: BaseMutationOptions,
): Promise<SanityDocument<R>>
createIfNotExists<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options?:
| AllDocumentIdsMutationOptions
| AllDocumentsMutationOptions
| BaseMutationOptions
| FirstDocumentIdMutationOptions
| FirstDocumentMutationOptions,
): Promise<
SanityDocument<R> | SanityDocument<R>[] | SingleMutationResult | MultipleMutationResult
> {
return lastValueFrom(
dataMethods._createIfNotExists<R>(this, this.#httpRequest, document, options),
)
}
/**
* Create a document if it does not exist, or replace a document with the same document ID
* Returns a promise that resolves to the created document.
*
* @param document - Document to either create or replace
* @param options - Mutation options
*/
createOrReplace<R extends Record<string, Any> = Record<string, Any>>(
document: IdentifiedSanityDocumentStub<R>,
options: FirstDocumentMutationOptions,
): Promise<SanityDocument<R>>
/**
* Create a document if it does not exist, or replace a docu