@sanity/sdk 3.11.0-next.20261029162752 → 3.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@ import { J as isMessageBusEnvironment, M as getClientErrorApiBody, V as isStudio
5
5
  import { i as pickProperties, n as isObject, t as isDeepEqual } from "../object-CxXlSVg7.js";
6
6
  import { n as getClient } from "../clientStore-DtQjmYYe.js";
7
7
  import { a as getDashboardMessageBus, i as resolveTopic, o as isDashboardEnvironment, r as getTopicState, s as requireDashboardMessageBus } from "../topicStore-g-C28bpz.js";
8
- import { C as getProjectAccessErrorDetails, S as toFavoriteDocument, T as getSignInMethodLabel, d as getUsersKey, i as parseQueryKey, n as getQueryKey, p as parseUsersKey, t as CORE_SDK_VERSION } from "../version-jKLQyZ-r.js";
8
+ import { C as getProjectAccessErrorDetails, S as toFavoriteDocument, T as getSignInMethodLabel, d as getUsersKey, i as parseQueryKey, n as getQueryKey, p as parseUsersKey, t as CORE_SDK_VERSION } from "../version-fBDdKP8q.js";
9
9
  import "@sanity/client";
10
10
  import { EMPTY, catchError, defer, distinctUntilChanged, map, merge } from "rxjs";
11
11
  import "@sanity/types";
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { a as compareProjectOrganization, i as projects, n as threadComments, o
5
5
  import { r as omitProperty, t as isDeepEqual } from "./object-CxXlSVg7.js";
6
6
  import { n as getClient, r as getClientState } from "./clientStore-DtQjmYYe.js";
7
7
  import { n as getDashboardOrganizationId } from "./topicStore-g-C28bpz.js";
8
- import { _ as updateLastLoadMoreRequest, a as resolveQuery, b as favorites, c as getAllReleasesState, d as getUsersKey, f as initializeRequest, g as setUsersError, h as setUsersData, l as addSubscription, m as removeSubscription, o as getPerspectiveState, p as parseUsersKey, r as getQueryState, s as getActiveReleasesState, t as CORE_SDK_VERSION, u as cancelRequest, v as PROJECT_API_VERSION, w as getProjectAccessErrorProjectId, x as setFavorite, y as USERS_STATE_CLEAR_DELAY } from "./version-jKLQyZ-r.js";
8
+ import { _ as updateLastLoadMoreRequest, a as resolveQuery, b as favorites, c as getAllReleasesState, d as getUsersKey, f as initializeRequest, g as setUsersError, h as setUsersData, l as addSubscription, m as removeSubscription, o as getPerspectiveState, p as parseUsersKey, r as getQueryState, s as getActiveReleasesState, t as CORE_SDK_VERSION, u as cancelRequest, v as PROJECT_API_VERSION, w as getProjectAccessErrorProjectId, x as setFavorite, y as USERS_STATE_CLEAR_DELAY } from "./version-fBDdKP8q.js";
9
9
  import { ClientError, CorsOriginError } from "@sanity/client";
10
10
  import { EMPTY, NEVER, Observable, ReplaySubject, Subject, Subscription, auditTime, catchError, combineLatest, concat, concatMap, debounceTime, defer, distinctUntilChanged, filter, first, firstValueFrom, from, fromEvent, groupBy, map, merge, mergeMap, of, pairwise, partition, race, share, skip, startWith, switchMap, take, takeUntil, tap, throttle, throwError, timer, withLatestFrom } from "rxjs";
11
11
  import { isKeySegment, isKeyedObject } from "@sanity/types";
@@ -553,7 +553,7 @@ const _resolveQuery = bindActionByResource(queryStore, ({ state, instance }, { s
553
553
  }, QUERY_STATE_CLEAR_DELAY);
554
554
  };
555
555
  return promise.then(releaseSubscriber, releaseSubscriber), promise;
556
- }), CORE_SDK_VERSION = getEnv("PKG_VERSION") || "3.11.0-next.20261029162752-development";
556
+ }), CORE_SDK_VERSION = getEnv("PKG_VERSION") || "3.11.0-development";
557
557
  export { getProjectAccessErrorDetails as C, toFavoriteDocument as S, getSignInMethodLabel as T, updateLastLoadMoreRequest as _, resolveQuery as a, favorites as b, getAllReleasesState as c, getUsersKey as d, initializeRequest as f, setUsersError as g, setUsersData as h, parseQueryKey as i, addSubscription as l, removeSubscription as m, getQueryKey as n, getPerspectiveState as o, parseUsersKey as p, getQueryState as r, getActiveReleasesState as s, CORE_SDK_VERSION as t, cancelRequest as u, PROJECT_API_VERSION as v, getProjectAccessErrorProjectId as w, setFavorite as x, USERS_STATE_CLEAR_DELAY as y };
558
558
 
559
- //# sourceMappingURL=version-jKLQyZ-r.js.map
559
+ //# sourceMappingURL=version-fBDdKP8q.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version-jKLQyZ-r.js","names":["\"publishAt\"","\"intendedPublishAt\""],"sources":["../src/auth/projectAccessError.ts","../src/favorites/favorites.ts","../src/users/usersConstants.ts","../src/users/reducers.ts","../src/client/liveEvents.ts","../src/releases/observeReleases.ts","../src/releases/utils/sortReleases.ts","../src/releases/releasesStore.ts","../src/releases/getPerspectiveState.ts","../src/query/queryStoreConstants.ts","../src/query/reducers.ts","../src/query/queryStore.ts","../package.json","../src/version.ts"],"sourcesContent":["import {ClientError} from '@sanity/client'\n\nimport {type SanityInstance} from '../store/createSanityInstance'\nimport {getCurrentUserState} from './authStore'\nimport {getClientErrorApiBody, getClientErrorApiProjectId, getClientErrorApiType} from './utils'\n\n/**\n * Identifiers from a `projectUserNotFoundError` response. Each field is\n * optional because older API responses only carry a description.\n *\n * @internal\n */\nexport interface ProjectAccessErrorDetails {\n /** The project the failed request was made against. */\n projectId?: string\n /** The global ID of the signed-in user, which has no membership in the project. */\n userId?: string\n /** The trace ID of the failed request. Support uses it to find the request in logs. */\n traceId?: string\n}\n\nfunction findClientError(error: unknown): ClientError | null {\n if (error instanceof ClientError) return error\n if (error instanceof Error && error.cause instanceof ClientError) return error.cause\n return null\n}\n\nfunction stringOrUndefined(value: unknown): string | undefined {\n return typeof value === 'string' && value ? value : undefined\n}\n\n/**\n * Reads the identifiers from the 401 `projectUserNotFoundError` that the\n * Content Lake returns when the signed-in user is not a member of the project.\n * Accepts the `ClientError` itself or an error that wraps it as its `cause`,\n * such as the React package's `AuthError`.\n *\n * @returns The identifiers, or `null` when the error is not a\n * `projectUserNotFoundError`.\n * @internal\n */\nexport function getProjectAccessErrorDetails(error: unknown): ProjectAccessErrorDetails | null {\n const clientError = findClientError(error)\n if (\n !clientError ||\n clientError.statusCode !== 401 ||\n getClientErrorApiType(clientError) !== 'projectUserNotFoundError'\n ) {\n return null\n }\n\n const body = getClientErrorApiBody(clientError)?.error\n return {\n projectId: getClientErrorApiProjectId(clientError),\n userId: stringOrUndefined(body?.userID),\n traceId: stringOrUndefined(clientError.traceId),\n }\n}\n\n/**\n * Returns the ID of the project that rejected a request because the signed-in\n * user isn't a member of it. The Content Lake reports this as a 401\n * `projectUserNotFoundError`. It usually means the user signed in with a\n * different account than the one that has access, for example Google instead\n * of SSO with the same email address.\n *\n * When this error reaches the SDK's `AuthBoundary`, the boundary replaces the\n * whole app with a screen that explains the problem. An app-level error\n * boundary inside `AuthBoundary` catches the error first, so it decides where\n * the error goes. Rethrow it when the app can't work without the rejected\n * project. Handle it in place when only part of the app reads from that\n * project, so a user who can access the app's other projects can keep using\n * them.\n *\n * @param error - The value to inspect. A `ClientError`, or an error that wraps\n * one as its `cause`.\n * @returns The rejected project's ID, or `null` when the error isn't a\n * `projectUserNotFoundError` or the response doesn't name the project.\n *\n * @example Rethrowing only for the project the whole app needs\n * ```tsx\n * const MAIN_PROJECT_ID = 'abc123'\n *\n * function Fallback({error}: FallbackProps) {\n * const projectId = getProjectAccessErrorProjectId(error)\n * // The app can't work without its main project, so let AuthBoundary\n * // replace it with the project access screen.\n * if (projectId === MAIN_PROJECT_ID) throw error\n * if (projectId) return <p>You don't have access to project {projectId}.</p>\n * return <p>Something went wrong.</p>\n * }\n * ```\n *\n * @category Authentication\n * @public\n */\nexport function getProjectAccessErrorProjectId(error: unknown): string | null {\n return getProjectAccessErrorDetails(error)?.projectId ?? null\n}\n\n// Provider IDs come from the `provider` field of `/users/me`. SAML providers\n// are org-configured and arrive as `saml-<providerId>`.\nconst SIGN_IN_METHOD_LABELS: Record<string, string> = {\n google: 'Google',\n github: 'GitHub',\n sanity: 'email and password',\n vercel: 'Vercel',\n}\n\n/**\n * Returns a user-facing name for a `/users/me` `provider` value, such as\n * `Google` for `google` or `SSO` for any `saml-*` provider.\n *\n * @returns The label, or `undefined` for an unknown or missing provider.\n * @internal\n */\nexport function getSignInMethodLabel(provider: string | undefined): string | undefined {\n if (!provider) return undefined\n if (provider.startsWith('saml-')) return 'SSO'\n return SIGN_IN_METHOD_LABELS[provider]\n}\n\n// Names the sign-in method but never the email address, because error\n// messages end up in logs and error trackers.\nfunction getProjectAccessErrorMessage(\n details: ProjectAccessErrorDetails,\n provider: string | undefined,\n): string {\n const method = getSignInMethodLabel(provider)\n const account = method ? `Your Sanity account (signed in with ${method})` : 'Your Sanity account'\n const project = details.projectId ? `project ${details.projectId}` : 'this project'\n // Matches the trace ID suffix @sanity/client adds to ClientError messages.\n const traceId = details.traceId ? ` (traceId: ${details.traceId})` : ''\n return (\n `${account} isn't a member of ${project}. ` +\n 'Each sign-in method, such as Google or SSO, is a separate account. ' +\n `Sign out and sign in with the account that has access.${traceId}`\n )\n}\n\n// Keeps everything the original ClientError carries (status code, response\n// body, trace ID) so `instanceof ClientError` checks and\n// `getProjectAccessErrorDetails` keep working on it.\nclass ProjectAccessClientError extends ClientError {\n constructor(error: ClientError, message: string) {\n super(error.response)\n this.message = message\n }\n}\n\n/**\n * Replaces the API's `projectUserNotFoundError` message with one that tells\n * the user what to do. Hooks throw store errors to the nearest error boundary,\n * and most boundaries, including routers' default error screens, render\n * `error.message`. Any other error is returned unchanged.\n *\n * @internal\n */\nexport function withProjectAccessMessage(instance: SanityInstance, error: unknown): unknown {\n if (!(error instanceof ClientError) || error instanceof ProjectAccessClientError) return error\n const details = getProjectAccessErrorDetails(error)\n if (!details) return error\n\n const provider = getCurrentUserState(instance).getCurrent()?.provider\n return new ProjectAccessClientError(error, getProjectAccessErrorMessage(details, provider))\n}\n","import {\n type CanvasResource,\n type Events,\n type FrameMessages,\n type MediaResource,\n SDK_CHANNEL_NAME,\n SDK_NODE_NAME,\n type StudioResource,\n type WindowMessages,\n} from '@sanity/message-protocol'\nimport {catchError, first, from, map, type Observable, of, switchMap} from 'rxjs'\n\nimport {getNodeState} from '../comlink/node/getNodeState'\nimport {type DocumentHandle} from '../config/sanityConfig'\nimport {type SanityInstance} from '../store/createSanityInstance'\nimport {defineFetcher, defineMutation} from '../store/fetcherStore'\n\n/**\n * @public\n */\nexport interface FavoriteStatusResponse {\n isFavorited: boolean\n}\n\n/**\n * @public\n */\nexport interface FavoriteDocumentContext extends DocumentHandle {\n resourceId: string\n resourceType: StudioResource['type'] | MediaResource['type'] | CanvasResource['type']\n schemaName?: string\n}\n\n/**\n * The `document` a favorite write addresses over Comlink.\n *\n * @internal\n */\nexport function toFavoriteDocument(context: FavoriteDocumentContext): {\n id: string\n type: string\n resource: {id: string; type: FavoriteDocumentContext['resourceType']; schemaName?: string}\n} {\n return {\n id: context.documentId,\n type: context.documentType,\n resource: {\n id: context.resourceId,\n type: context.resourceType,\n ...(context.schemaName ? {schemaName: context.schemaName} : {}),\n },\n }\n}\n\n// Helper to create a stable key for the store\nfunction createFavoriteKey(context: FavoriteDocumentContext): string {\n return `${context.documentId}:${context.documentType}:${context.resourceId}:${context.resourceType}${\n context.schemaName ? `:${context.schemaName}` : ''\n }`\n}\n\n/**\n * Fetcher for a document's favorite status, read from the dashboard over\n * comlink, on the shared fetcher cache.\n *\n * @internal\n */\nexport const favorites = defineFetcher<[context: FavoriteDocumentContext], FavoriteStatusResponse>({\n name: 'favorites',\n getKey: (_instance: SanityInstance, context: FavoriteDocumentContext) =>\n createFavoriteKey(context),\n // Tag each entry with its key so `setFavorite` can invalidate exactly it.\n tags: (_data, context) => [{type: 'favorite', id: createFavoriteKey(context)}],\n fetch: (instance) => {\n return (context: FavoriteDocumentContext): Observable<FavoriteStatusResponse> => {\n const nodeStateSource = getNodeState<FrameMessages, WindowMessages>(instance, {\n name: SDK_NODE_NAME,\n connectTo: SDK_CHANNEL_NAME,\n })\n const payload = {document: toFavoriteDocument(context)}\n\n return nodeStateSource.observable.pipe(\n // Wait until connected, then complete after the single fetch settles.\n first((nodeState) => !!nodeState),\n switchMap((nodeState) => {\n const node = nodeState!.node\n return from(node.fetch('dashboard/v1/events/favorite/query', payload)).pipe(\n map((response) => ({isFavorited: response.isFavorited})),\n catchError((err) => {\n // eslint-disable-next-line no-console\n console.error('Favorites service connection error', err)\n return of({isFavorited: false})\n }),\n )\n }),\n )\n }\n },\n})\n\n/**\n * Input for {@link setFavorite}: the document context plus the desired state.\n *\n * @public\n */\nexport type SetFavoriteInput = FavoriteDocumentContext & {\n /** The favorite state to move to: `true` to favorite, `false` to unfavorite. */\n isFavorited: boolean\n}\n\n/**\n * Sets a document's favorite state over comlink. Writes the new state into the\n * cached {@link favorites} status before the request (rolled back on failure),\n * then invalidates it so active readers reconverge on server truth. The\n * write-side counterpart to {@link favorites}.\n *\n * @internal\n */\nexport const setFavorite = defineMutation<SetFavoriteInput, FavoriteStatusResponse>({\n name: 'setFavorite',\n mutationFn: (instance) => {\n return ({isFavorited, ...context}: SetFavoriteInput): Observable<FavoriteStatusResponse> => {\n const nodeStateSource = getNodeState<FrameMessages, WindowMessages>(instance, {\n name: SDK_NODE_NAME,\n connectTo: SDK_CHANNEL_NAME,\n })\n const payload: Events.FavoriteMutateMessage['data'] = {\n eventType: isFavorited ? 'added' : 'removed',\n document: toFavoriteDocument(context),\n }\n\n return nodeStateSource.observable.pipe(\n // Wait until connected, then complete after the single mutation settles.\n first((nodeState) => !!nodeState),\n switchMap((nodeState) => {\n const node = nodeState!.node\n return from(node.fetch('dashboard/v1/events/favorite/mutate', payload)).pipe(\n map((response) => {\n if (!response.success) throw new Error('Failed to update favorite status')\n return {isFavorited}\n }),\n )\n }),\n )\n }\n },\n onMutate: (write, {isFavorited, ...context}) => write(favorites, [context], {isFavorited}),\n invalidates: (_result, input) => [{type: 'favorite', id: createFavoriteKey(input)}],\n})\n","// NOTE: currently this API is only available on vX\nexport const API_VERSION = 'vX'\nexport const PROJECT_API_VERSION = '2025-07-18'\nexport const USERS_STATE_CLEAR_DELAY = 5000\nexport const DEFAULT_USERS_BATCH_SIZE = 100\n","import {type SanityInstance} from '../store/createSanityInstance'\nimport {omitProperty} from '../utils/object'\nimport {type GetUsersOptions, type SanityUserResponse, type UsersStoreState} from './types'\nimport {DEFAULT_USERS_BATCH_SIZE} from './usersConstants'\n\n/** @internal */\nexport const getUsersKey = (\n instance: SanityInstance,\n {\n resourceType,\n organizationId,\n batchSize = DEFAULT_USERS_BATCH_SIZE,\n projectId = instance.config.projectId,\n userId,\n }: GetUsersOptions = {},\n): string =>\n JSON.stringify({\n resourceType,\n organizationId,\n batchSize,\n projectId,\n userId,\n } satisfies ReturnType<typeof parseUsersKey>)\n\n/** @internal */\nexport const parseUsersKey = (\n key: string,\n): {\n batchSize: number\n resourceType?: 'organization' | 'project'\n projectId?: string\n organizationId?: string\n userId?: string\n} => JSON.parse(key)\n\nexport const addSubscription =\n (subscriptionId: string, key: string) =>\n (prev: UsersStoreState): UsersStoreState => {\n const group = prev.users[key]\n const subscriptions = [...(group?.subscriptions ?? []), subscriptionId]\n return {...prev, users: {...prev.users, [key]: {...group, subscriptions}}}\n }\n\nexport const removeSubscription =\n (subscriptionId: string, key: string) =>\n (prev: UsersStoreState): UsersStoreState => {\n const group = prev.users[key]\n if (!group) return prev\n const subscriptions = group.subscriptions.filter((id) => id !== subscriptionId)\n if (!subscriptions.length) return {...prev, users: omitProperty(prev.users, key)}\n return {...prev, users: {...prev.users, [key]: {...group, subscriptions}}}\n }\n\nexport const setUsersData =\n (key: string, {data, nextCursor, totalCount}: SanityUserResponse) =>\n (prev: UsersStoreState): UsersStoreState => {\n const group = prev.users[key]\n if (!group) return prev\n const users = [...(group.users ?? []), ...data]\n return {...prev, users: {...prev.users, [key]: {...group, users, totalCount, nextCursor}}}\n }\n\nexport const updateLastLoadMoreRequest =\n (timestamp: string, key: string) =>\n (prev: UsersStoreState): UsersStoreState => {\n const group = prev.users[key]\n if (!group) return prev\n return {...prev, users: {...prev.users, [key]: {...group, lastLoadMoreRequest: timestamp}}}\n }\n\nexport const setUsersError =\n (key: string, error: unknown) =>\n (prev: UsersStoreState): UsersStoreState => {\n const group = prev.users[key]\n if (!group) return prev\n return {...prev, users: {...prev.users, [key]: {...group, error}}}\n }\n\nexport const cancelRequest =\n (key: string) =>\n (prev: UsersStoreState): UsersStoreState => {\n const group = prev.users[key]\n if (!group) return prev\n if (group.subscriptions.length) return prev\n return {...prev, users: omitProperty(prev.users, key)}\n }\n\nexport const initializeRequest =\n (key: string) =>\n (prev: UsersStoreState): UsersStoreState => {\n if (prev.users[key]) return prev\n return {...prev, users: {...prev.users, [key]: {subscriptions: []}}}\n }\n","import {\n ConnectionFailedError,\n CorsOriginError,\n DisconnectError,\n type LiveEventMessage,\n} from '@sanity/client'\nimport {\n defer,\n distinctUntilChanged,\n EMPTY,\n filter,\n map,\n type Observable,\n of,\n switchMap,\n timer,\n} from 'rxjs'\n\nimport {getClientAuthState, getTokenState} from '../auth/authStore'\nimport {type DocumentResource} from '../config/sanityConfig'\nimport {type SanityInstance} from '../store/createSanityInstance'\nimport {getClientState} from './clientStore'\nimport {retryWithCredential} from './retry'\n\n/**\n * All live-events subscriptions must use identical connection options\n * (API version, request tag, `includeDrafts`): `@sanity/client` caches the\n * underlying EventSource per URL + options, so divergent options would\n * silently split what should be a single shared connection.\n */\nconst LIVE_EVENTS_API_VERSION = 'v2025-05-06'\n\n/**\n * Delay before re-establishing the live events connection after a\n * server-initiated error (e.g. ChannelError, MessageError). Live errors are\n * retried rather than surfaced because an errored live connection would\n * otherwise poison the consuming store. Plain connection drops never reach\n * this — they are reconnected inside `@sanity/client`.\n *\n * @internal\n */\nexport const LIVE_EVENTS_RETRY_DELAY = 1000\n\n/**\n * Options for {@link observeLiveEvents}.\n * @internal\n */\nexport interface ObserveLiveEventsOptions {\n /** Resource to scope the underlying client and live connection to. */\n resource?: DocumentResource\n /**\n * Called when the connection fails due to a CORS misconfiguration. The\n * error is swallowed (the stream never errors; it idles) so consumers can\n * surface it as store state instead of a stream error.\n */\n onCorsError: (error: unknown) => void\n}\n\n/**\n * Emits Live Content API messages for a dataset so consumers can invalidate\n * fetched data via sync tags.\n *\n * All consumers observe the same underlying EventSource connection:\n * `@sanity/client` caches the live-events stream per URL and connection\n * options, and every subscription made through this function uses the same\n * API version and request tag.\n *\n * @internal\n */\nexport function observeLiveEvents(\n instance: SanityInstance,\n {resource, onCorsError}: ObserveLiveEventsOptions,\n): Observable<LiveEventMessage> {\n // Drafts need a token. Other clients are rebuilt when their token changes,\n // but an OAuth app's client follows its token through `auth`, so reconnect it\n // only when a token appears or disappears, not on every refresh.\n const hasToken$ = getTokenState(instance).observable.pipe(map(Boolean), distinctUntilChanged())\n const connection$ = getClientState(instance, {\n apiVersion: LIVE_EVENTS_API_VERSION,\n resource,\n }).observable.pipe(\n switchMap((client) =>\n (client.config().auth ? hasToken$ : of(Boolean(client.config().token))).pipe(\n map((includeDrafts) => [client, includeDrafts] as const),\n ),\n ),\n )\n\n return connection$.pipe(\n switchMap(([client, includeDrafts]) =>\n retryWithCredential(\n defer(() => client.live.events({includeDrafts, tag: 'live-events'})),\n getClientAuthState(instance),\n (error, _, credentialChanged) => {\n if (error instanceof CorsOriginError) {\n // Swallow CORS errors without bubbling up so that they can be\n // handled by the consumer (e.g. shown via the Cors Error component)\n onCorsError(error)\n return EMPTY\n }\n if (error instanceof DisconnectError) {\n // The server explicitly told this client to stop reconnecting —\n // end live updates without erroring (consumers keep serving data,\n // they just stop receiving live invalidation)\n return EMPTY\n }\n if (\n error instanceof ConnectionFailedError &&\n typeof error.status === 'number' &&\n error.status >= 400 &&\n error.status < 500\n ) {\n // The server rejected the connection with a 4xx (e.g. a 401 from\n // an expired token) — it will keep rejecting the same credential,\n // so retrying on a timer would reconnect once per second forever.\n // Reconnect once the credential changes instead. A\n // ConnectionFailedError without a status stays retryable: it may\n // be a transient network failure.\n return credentialChanged\n }\n // Server-initiated live errors (e.g. ChannelError, MessageError) are\n // retried, not surfaced. Dropped connections are already reconnected\n // inside @sanity/client.\n return timer(LIVE_EVENTS_RETRY_DELAY)\n },\n ),\n ),\n filter((e): e is LiveEventMessage => e.type === 'message'),\n )\n}\n","import {type ReleaseDocument, type SyncTag} from '@sanity/client'\nimport {\n BehaviorSubject,\n combineLatest,\n distinctUntilChanged,\n filter,\n map,\n type Observable,\n startWith,\n switchMap,\n tap,\n} from 'rxjs'\n\nimport {getClientAuthState} from '../auth/authStore'\nimport {getClientState} from '../client/clientStore'\nimport {observeLiveEvents} from '../client/liveEvents'\nimport {retryRead} from '../client/retry'\nimport {type DocumentResource} from '../config/sanityConfig'\nimport {type SanityInstance} from '../store/createSanityInstance'\n\nconst RELEASES_QUERY = 'releases::all()'\nconst RELEASES_API_VERSION = 'v2025-05-06'\n\n/**\n * Options for {@link observeReleases}.\n * @internal\n */\nexport interface ObserveReleasesOptions {\n /** Resource to scope the underlying client and live connection to. */\n resource?: DocumentResource\n /**\n * Called when the live events connection fails due to a CORS\n * misconfiguration. See `observeLiveEvents`.\n */\n onCorsError: (error: unknown) => void\n /** Receives a failed fetch, and `undefined` once fetching recovers. */\n onError: (error: unknown) => void\n}\n\n/**\n * Emits every release document (including archived and published), refetching\n * whenever a Live Content API event matches the query's sync tags.\n *\n * This fetches directly through the client store — deliberately not via the\n * query store — because release data is itself an input to query perspective\n * resolution (`getPerspectiveState`); fetching through the query store would\n * make the two stores mutually dependent.\n *\n * @internal\n */\nexport function observeReleases(\n instance: SanityInstance,\n {resource, onCorsError, onError}: ObserveReleasesOptions,\n): Observable<ReleaseDocument[] | undefined> {\n const client$ = getClientState(instance, {\n apiVersion: RELEASES_API_VERSION,\n resource,\n }).observable\n\n return client$.pipe(\n switchMap((client) => {\n const syncTags$ = new BehaviorSubject<SyncTag[] | undefined>(undefined)\n\n // Pair the latest live message with the latest known sync tags so that\n // a message arriving while a fetch is still in flight is re-evaluated\n // (and refetched if it matches) once that fetch's tags land — instead\n // of being dropped and leaving the store stale until the next event.\n const refetchEventId$ = combineLatest([\n observeLiveEvents(instance, {resource, onCorsError}).pipe(startWith(undefined)),\n syncTags$,\n ]).pipe(\n filter(\n ([message, syncTags]) =>\n message === undefined || message.tags.some((tag) => syncTags?.includes(tag)),\n ),\n map(([message]) => message?.id),\n distinctUntilChanged(),\n )\n\n return refetchEventId$.pipe(\n switchMap((lastLiveEventId) =>\n client.observable.fetch<ReleaseDocument[]>(\n RELEASES_QUERY,\n {},\n {\n perspective: 'raw',\n filterResponse: false,\n returnQuery: false,\n lastLiveEventId,\n tag: 'releases',\n },\n ),\n ),\n tap((response) => {\n syncTags$.next(response.syncTags)\n }),\n map((response) => response.result),\n )\n }),\n retryRead(getClientAuthState(instance), onError),\n )\n}\n","import {type ReleaseDocument} from '@sanity/client'\n\n// mirrors the order of the releases in the releases list in Studio\n// https://github.com/sanity-io/sanity/blob/main/packages/sanity/src/core/releases/hooks/utils.ts\nexport function sortReleases(releases: ReleaseDocument[] = []): ReleaseDocument[] {\n // The order should always be:\n // [undecided (sortByCreatedAt), scheduled(sortBy publishAt || metadata.intendedPublishAt), asap(sortByCreatedAt)]\n return [...releases].sort((a, b) => {\n // metadata is optional on a release document; guard against releases that\n // have no metadata at all so sorting can't throw and wipe out the list.\n const aType = a.metadata?.releaseType\n const bType = b.metadata?.releaseType\n\n // undecided are always first, then by createdAt descending\n if (aType === 'undecided' && bType !== 'undecided') {\n return -1\n }\n if (aType !== 'undecided' && bType === 'undecided') {\n return 1\n }\n if (aType === 'undecided' && bType === 'undecided') {\n // Sort by createdAt\n return new Date(b._createdAt).getTime() - new Date(a._createdAt).getTime()\n }\n\n // Scheduled are always at the middle, then by publishAt descending\n if (aType === 'scheduled' && bType === 'scheduled') {\n const aPublishAt = a['publishAt'] || a.metadata?.['intendedPublishAt']\n if (!aPublishAt) {\n return 1\n }\n const bPublishAt = b['publishAt'] || b.metadata?.['intendedPublishAt']\n if (!bPublishAt) {\n return -1\n }\n return new Date(bPublishAt).getTime() - new Date(aPublishAt).getTime()\n }\n\n // ASAP are always last, then by createdAt descending\n if (aType === 'asap' && bType !== 'asap') {\n return 1\n }\n if (aType !== 'asap' && bType === 'asap') {\n return -1\n }\n if (aType === 'asap' && bType === 'asap') {\n // Sort by createdAt\n return new Date(b._createdAt).getTime() - new Date(a._createdAt).getTime()\n }\n\n return 0\n })\n}\n","import {type ReleaseDocument} from '@sanity/client'\nimport {map} from 'rxjs'\n\nimport {type DocumentResource} from '../config/sanityConfig'\nimport {bindActionByResource, type BoundResourceKey} from '../store/createActionBinder'\nimport {type SanityInstance} from '../store/createSanityInstance'\nimport {createStateSourceAction, type StateSource} from '../store/createStateSourceAction'\nimport {defineStore, type StoreContext} from '../store/defineStore'\nimport {observeReleases} from './observeReleases'\nimport {sortReleases} from './utils/sortReleases'\n\nconst ARCHIVED_RELEASE_STATES = ['archived', 'published']\nconst STABLE_EMPTY_RELEASES: ReleaseDocument[] = []\n\n/**\n * Lifecycle states a release document can be in. Mirrors the server's\n * `ReleaseState`.\n * @beta\n */\nexport type ReleaseState =\n | 'active'\n | 'archiving'\n | 'unarchiving'\n | 'archived'\n | 'published'\n | 'publishing'\n | 'scheduled'\n | 'scheduling'\n\nexport interface ReleasesStoreState {\n activeReleases?: ReleaseDocument[]\n allReleases?: ReleaseDocument[]\n error?: unknown\n fetchError?: unknown\n}\n\nexport const releasesStore = defineStore<ReleasesStoreState, BoundResourceKey>({\n name: 'Releases',\n // Empty rather than undefined, so the React hooks do not suspend on first load. A\n // reconnect keeps whatever was last known until the fetch returns.\n getInitialState: (): ReleasesStoreState => ({\n activeReleases: STABLE_EMPTY_RELEASES,\n allReleases: STABLE_EMPTY_RELEASES,\n }),\n upstream: (context) => subscribeToReleases(context),\n})\n\n/**\n * Get the active releases from the store.\n * @internal\n */\nconst _getActiveReleasesState = bindActionByResource(\n releasesStore,\n createStateSourceAction({\n selector: ({state}) => {\n if (state.error ?? state.fetchError) throw state.error ?? state.fetchError\n return state.activeReleases\n },\n }),\n)\n\n/**\n * Get the active releases from the store.\n * @internal\n */\nexport const getActiveReleasesState = (\n instance: SanityInstance,\n options?: {resource?: DocumentResource},\n): StateSource<ReleaseDocument[] | undefined> =>\n // bindActionByResource keyFn destructures { resource } from the first param, so pass {} when no options\n _getActiveReleasesState(instance, options ?? {})\n\n/**\n * Get every release in the store, including archived and published.\n * @internal\n */\nconst _getAllReleasesState = bindActionByResource(\n releasesStore,\n createStateSourceAction({\n selector: ({state}) => {\n if (state.error ?? state.fetchError) throw state.error ?? state.fetchError\n return state.allReleases\n },\n }),\n)\n\n/**\n * Get every release in the store, including archived and published.\n * @internal\n */\nexport const getAllReleasesState = (\n instance: SanityInstance,\n options?: {resource?: DocumentResource},\n): StateSource<ReleaseDocument[] | undefined> => _getAllReleasesState(instance, options ?? {})\n\nconst subscribeToReleases = ({\n instance,\n state,\n key: {resource},\n}: StoreContext<ReleasesStoreState, BoundResourceKey>) => {\n const releases$ = observeReleases(instance, {\n resource,\n // Surface CORS errors as store state instead of erroring the stream so\n // they can be handled by the Cors Error component\n onCorsError: (error) => state.set('setError', {error}),\n onError: (fetchError) => state.set('setFetchError', {fetchError}),\n })\n return releases$\n .pipe(\n map((releases) => {\n // logic here mirrors that of studio:\n // https://github.com/sanity-io/sanity/blob/156e8fa482703d99219f08da7bacb384517f1513/packages/sanity/src/core/releases/store/useActiveReleases.ts#L29\n const sorted = sortReleases(releases ?? STABLE_EMPTY_RELEASES).reverse()\n state.set('setReleases', {\n allReleases: sorted,\n activeReleases: sorted.filter(\n (release) => !ARCHIVED_RELEASE_STATES.includes(release.state),\n ),\n fetchError: undefined,\n })\n }),\n )\n .subscribe({error: (error) => state.set('setError', {error})})\n}\n","import {createSelector} from 'reselect'\n\nimport {type DocumentResource, type PerspectiveHandle} from '../config/sanityConfig'\nimport {bindActionByResource, type BoundStoreAction} from '../store/createActionBinder'\nimport {createStateSourceAction, type SelectorContext} from '../store/createStateSourceAction'\nimport {releasesStore, type ReleasesStoreState} from './releasesStore'\nimport {isReleasePerspective} from './utils/isReleasePerspective'\nimport {sortReleases} from './utils/sortReleases'\n\nconst DEFAULT_PERSPECTIVE = 'drafts'\n\n// Cache for options\nconst optionsCache = new Map<string, Map<string, PerspectiveHandle>>()\n\nconst selectInstancePerspective = (context: SelectorContext<ReleasesStoreState>, _?: unknown) =>\n context.instance.config.perspective\nconst selectActiveReleases = (context: SelectorContext<ReleasesStoreState>) =>\n context.state.activeReleases\nconst selectOptions = (\n _context: SelectorContext<ReleasesStoreState>,\n options: PerspectiveHandle & {projectId?: string; dataset?: string; resource?: DocumentResource},\n) => options\n\nconst memoizedOptionsSelector = createSelector(\n [selectActiveReleases, selectOptions],\n (activeReleases, options) => {\n if (!options || !activeReleases) return options\n\n // Use release document IDs as the cache key\n const releaseIds = activeReleases.map((release) => release._id).join(',')\n let nestedCache = optionsCache.get(releaseIds)\n if (!nestedCache) {\n nestedCache = new Map<string, PerspectiveHandle>()\n optionsCache.set(releaseIds, nestedCache)\n }\n\n const optionsKey = JSON.stringify(options)\n let cachedOptions = nestedCache.get(optionsKey)\n\n if (!cachedOptions) {\n cachedOptions = options\n nestedCache.set(optionsKey, cachedOptions)\n }\n return cachedOptions\n },\n)\n\nconst _getPerspectiveStateSelector = createStateSourceAction({\n selector: createSelector(\n [selectInstancePerspective, selectActiveReleases, memoizedOptionsSelector],\n (instancePerspective, activeReleases, memoizedOptions) => {\n const perspective = memoizedOptions?.perspective ?? instancePerspective ?? DEFAULT_PERSPECTIVE\n\n if (!isReleasePerspective(perspective)) return perspective\n\n // if there are no active releases we can't compute the release perspective\n if (!activeReleases || activeReleases.length === 0) return undefined\n\n const releaseNames = sortReleases(activeReleases).map((release) => release.name)\n const index = releaseNames.findIndex((name) => name === perspective.releaseName)\n\n if (index < 0) {\n throw new Error(`Release \"${perspective.releaseName}\" not found in active releases`)\n }\n\n const filteredReleases = releaseNames.slice(0, index + 1) // Include the release itself\n\n return ['drafts', ...filteredReleases]\n .filter((name) => !perspective.excludedPerspectives?.includes(name))\n .reverse()\n },\n ),\n})\n\ntype OmitFirst<T extends unknown[]> = T extends [unknown, ...infer R] ? R : never\ntype SelectorParams = OmitFirst<Parameters<typeof _getPerspectiveStateSelector>>\ntype BoundGetPerspectiveState = BoundStoreAction<\n ReleasesStoreState,\n SelectorParams,\n ReturnType<typeof _getPerspectiveStateSelector>\n>\n\nconst _boundGetPerspectiveState = bindActionByResource(\n releasesStore,\n _getPerspectiveStateSelector,\n) as BoundGetPerspectiveState\n\n/**\n * Provides a subscribable state source for a \"perspective\" for the Sanity client,\n * which is used to fetch documents as though certain Content Releases are active.\n *\n * @param instance - The Sanity instance to get the perspective for\n * @param options - The options for the perspective -- usually a release name\n *\n * @returns A subscribable perspective value, usually a list of applicable release names,\n * or a single release name / default perspective (such as 'drafts').\n *\n * @public\n */\nexport const getPerspectiveState: BoundGetPerspectiveState = (instance, ...rest) =>\n // bindActionByResource keyFn destructures { resource } from the first param, so pass {} when no options\n _boundGetPerspectiveState(instance, ...(rest.length ? rest : [{}]))\n","import {UPSTREAM_CLOSE_DELAY_MS} from '../store/createStoreInstance'\n\n/**\n * When a query has no more subscribers, its state is cleaned up and removed\n * from the store. A delay used to prevent re-creating resources when the last\n * subscriber is removed quickly before another one is added. This is helpful\n * when used in a frontend where components may suspend or transition to\n * different views quickly.\n *\n * Must not exceed the live connection's close delay: nothing refetches when the\n * connection reopens, so a result kept past the close would miss live events.\n */\nexport const QUERY_STATE_CLEAR_DELAY = UPSTREAM_CLOSE_DELAY_MS\nexport const QUERY_STORE_API_VERSION = 'v2025-05-06'\nexport const QUERY_STORE_DEFAULT_PERSPECTIVE = 'drafts'\n","import {omitProperty} from '../utils/object'\n\ninterface QueryState {\n syncTags?: string[]\n result?: unknown\n error?: unknown\n lastLiveEventId?: string\n subscribers: string[]\n}\n\nexport interface QueryStoreState {\n queries: {[key: string]: QueryState | undefined}\n error?: unknown\n}\n\nexport const setQueryError =\n (key: string, error: unknown) =>\n (prev: QueryStoreState): QueryStoreState => {\n const prevQuery = prev.queries[key]\n if (!prevQuery) return prev\n return {...prev, queries: {...prev.queries, [key]: {...prevQuery, error}}}\n }\n\nexport const setQueryData =\n (key: string, result: unknown, syncTags?: string[]) =>\n (prev: QueryStoreState): QueryStoreState => {\n const prevQuery = prev.queries[key]\n if (!prevQuery) return prev\n return {\n ...prev,\n queries: {...prev.queries, [key]: {...prevQuery, result: result ?? null, syncTags}},\n }\n }\n\nexport const setLastLiveEventId =\n (key: string, lastLiveEventId: string) =>\n (prev: QueryStoreState): QueryStoreState => {\n const prevQuery = prev.queries[key]\n if (!prevQuery) return prev\n return {...prev, queries: {...prev.queries, [key]: {...prevQuery, lastLiveEventId}}}\n }\n\nexport const addSubscriber =\n (key: string, subscriptionId: string) =>\n (prev: QueryStoreState): QueryStoreState => {\n const prevQuery = prev.queries[key]\n const subscribers = [...(prevQuery?.subscribers ?? []), subscriptionId]\n return {...prev, queries: {...prev.queries, [key]: {...prevQuery, subscribers}}}\n }\n\nexport const removeSubscriber =\n (key: string, subscriptionId: string) =>\n (prev: QueryStoreState): QueryStoreState => {\n const prevQuery = prev.queries[key]\n if (!prevQuery) return prev\n const subscribers = prevQuery.subscribers.filter((id) => id !== subscriptionId)\n if (!subscribers.length) return {...prev, queries: omitProperty(prev.queries, key)}\n return {...prev, queries: {...prev.queries, [key]: {...prevQuery, subscribers}}}\n }\n","import {type ResponseQueryOptions} from '@sanity/client'\nimport {\n catchError,\n combineLatest,\n distinctUntilChanged,\n EMPTY,\n filter,\n first,\n firstValueFrom,\n groupBy,\n map,\n mergeMap,\n NEVER,\n Observable,\n of,\n pairwise,\n race,\n share,\n startWith,\n switchMap,\n tap,\n} from 'rxjs'\n\nimport {getClientAuthState} from '../auth/authStore'\nimport {withProjectAccessMessage} from '../auth/projectAccessError'\nimport {getClientState} from '../client/clientStore'\nimport {observeLiveEvents} from '../client/liveEvents'\nimport {retryRead} from '../client/retry'\nimport {type DatasetHandle} from '../config/sanityConfig'\nimport {getPerspectiveState} from '../releases/getPerspectiveState'\nimport {isReleasePerspective} from '../releases/utils/isReleasePerspective'\nimport {bindActionByResource, type BoundResourceKey} from '../store/createActionBinder'\nimport {type SanityInstance} from '../store/createSanityInstance'\nimport {\n createStateSourceAction,\n type SelectorContext,\n type StateSource,\n} from '../store/createStateSourceAction'\nimport {type StoreState} from '../store/createStoreState'\nimport {defineStore, type StoreContext} from '../store/defineStore'\nimport {type ResolveQueryResult} from '../typegen/resolve'\nimport {randomId} from '../utils/ids'\nimport {setCleanupTimeout} from '../utils/setCleanupTimeout'\nimport {\n QUERY_STATE_CLEAR_DELAY,\n QUERY_STORE_API_VERSION,\n QUERY_STORE_DEFAULT_PERSPECTIVE,\n} from './queryStoreConstants'\nimport {\n addSubscriber,\n type QueryStoreState,\n removeSubscriber,\n setLastLiveEventId,\n setQueryData,\n setQueryError,\n} from './reducers'\n\n/**\n * @beta\n */\nexport interface QueryOptions<\n TQuery extends string = string,\n TDataset extends string = string,\n TProjectId extends string = string,\n>\n extends\n Pick<ResponseQueryOptions, 'useCdn' | 'cache' | 'next' | 'cacheMode' | 'tag'>,\n DatasetHandle<TDataset, TProjectId> {\n query: TQuery\n params?: Record<string, unknown>\n}\n\n/**\n * @beta\n */\nexport interface ResolveQueryOptions<\n TQuery extends string = string,\n TDataset extends string = string,\n TProjectId extends string = string,\n> extends QueryOptions<TQuery, TDataset, TProjectId> {\n signal?: AbortSignal\n}\n\nconst EMPTY_ARRAY: never[] = []\n\n/** @internal */\nexport const getQueryKey = (instance: SanityInstance, options: QueryOptions): string =>\n JSON.stringify(normalizeOptionsWithPerspective(instance, options))\n/** @internal */\nexport const parseQueryKey = (key: string): QueryOptions => JSON.parse(key)\n\n/**\n * Ensures the query key includes an effective perspective so that\n * implicit differences (e.g. different instance.config.perspective)\n * don't collide in the dataset-scoped store.\n *\n * Since perspectives are unique, we can depend on the release stacks\n * to be correct when we retrieve the results.\n *\n */\nfunction normalizeOptionsWithPerspective(\n instance: SanityInstance,\n options: QueryOptions,\n): QueryOptions {\n if (options.perspective !== undefined) return options\n const instancePerspective = instance.config.perspective\n return {\n ...options,\n perspective:\n instancePerspective !== undefined ? instancePerspective : QUERY_STORE_DEFAULT_PERSPECTIVE,\n }\n}\n\nconst queryStore = defineStore<QueryStoreState, BoundResourceKey>({\n name: 'QueryStore',\n getInitialState: () => ({queries: {}}),\n initialize(context) {\n const subscription = listenForNewSubscribersAndFetch(context)\n return () => subscription.unsubscribe()\n },\n upstream: (context) => listenToLiveClientAndSetLastLiveEventIds(context),\n})\n\nconst errorHandler = (state: StoreState<{error?: unknown}>) => {\n return (error: unknown): void => state.set('setError', {error})\n}\n\nconst listenForNewSubscribersAndFetch = ({state, instance}: StoreContext<QueryStoreState>) => {\n return state.observable\n .pipe(\n map((s) => new Set(Object.keys(s.queries))),\n distinctUntilChanged((curr, next) => {\n if (curr.size !== next.size) return false\n return Array.from(next).every((i) => curr.has(i))\n }),\n startWith(new Set<string>()),\n pairwise(),\n mergeMap(([curr, next]) => {\n const added = Array.from(next).filter((i) => !curr.has(i))\n const removed = Array.from(curr).filter((i) => !next.has(i))\n\n return [\n ...added.map((key) => ({key, added: true})),\n ...removed.map((key) => ({key, added: false})),\n ]\n }),\n groupBy((i) => i.key),\n mergeMap((group$) =>\n group$.pipe(\n switchMap((e) => {\n if (!e.added) return EMPTY\n\n const lastLiveEventId$ = state.observable.pipe(\n map((s) => s.queries[group$.key]?.lastLiveEventId),\n distinctUntilChanged(),\n )\n const {\n query,\n params,\n projectId,\n dataset,\n tag,\n resource,\n perspective: perspectiveFromOptions,\n ...restOptions\n } = parseQueryKey(group$.key)\n\n // Short-circuit perspective resolution for non-release perspectives to avoid\n // touching the releases store (and its initialization) unnecessarily.\n const perspective$ = isReleasePerspective(perspectiveFromOptions)\n ? getPerspectiveState(instance, {\n perspective: perspectiveFromOptions,\n resource,\n }).observable.pipe(filter(Boolean))\n : of(perspectiveFromOptions ?? QUERY_STORE_DEFAULT_PERSPECTIVE)\n\n const client$ = getClientState(instance, {\n apiVersion: QUERY_STORE_API_VERSION,\n projectId,\n dataset,\n resource,\n }).observable\n\n return combineLatest({\n lastLiveEventId: lastLiveEventId$,\n client: client$,\n perspective: perspective$,\n }).pipe(\n switchMap(({lastLiveEventId, client, perspective}) =>\n client.observable.fetch(query, params, {\n ...restOptions,\n perspective,\n filterResponse: false,\n returnQuery: false,\n lastLiveEventId,\n tag,\n }),\n ),\n tap(({result, syncTags}) => {\n state.set('setQueryData', setQueryData(group$.key, result, syncTags))\n }),\n // Retry inside the per-event stream: erroring the group pipe would\n // complete the group's subscription, and since `groupBy` above never\n // removes its group subjects, re-adding the key would emit into a\n // subject with no subscribers — the key could never be fetched again.\n retryRead(getClientAuthState(instance), (error) =>\n state.set(\n 'setQueryError',\n setQueryError(group$.key, withProjectAccessMessage(instance, error)),\n ),\n ),\n )\n }),\n ),\n ),\n )\n .subscribe({error: errorHandler(state)})\n}\n\nconst listenToLiveClientAndSetLastLiveEventIds = ({\n state,\n instance,\n key: {resource},\n}: StoreContext<QueryStoreState, BoundResourceKey>) => {\n const liveMessages$ = observeLiveEvents(instance, {\n resource,\n // Surface CORS errors as store state (handled by the Cors Error\n // component) instead of erroring the stream: a stream error here would\n // reach the outer subscription's errorHandler, set the store-wide\n // `state.error`, and permanently brick every query selector.\n onCorsError: (error) => state.set('setError', {error}),\n }).pipe(share())\n\n return state.observable\n .pipe(\n mergeMap((s) => Object.entries(s.queries)),\n groupBy(([key]) => key),\n mergeMap((group$) => {\n const syncTags$ = group$.pipe(\n map(([, queryState]) => queryState),\n map((i) => i?.syncTags ?? EMPTY_ARRAY),\n distinctUntilChanged(),\n )\n\n return combineLatest([liveMessages$, syncTags$]).pipe(\n filter(([message, syncTags]) => message.tags.some((tag) => syncTags.includes(tag))),\n tap(([message]) => {\n state.set('setLastLiveEventId', setLastLiveEventId(group$.key, message.id))\n }),\n )\n }),\n )\n .subscribe({error: errorHandler(state)})\n}\n\n/**\n * Returns the state source for a query.\n *\n * This function returns a state source that represents the current result of a GROQ query.\n * Subscribing to the state source will instruct the SDK to fetch the query (if not already fetched)\n * and will keep the query live using the Live content API (considering sync tags) to provide up-to-date results.\n * When the last subscriber is removed, the query state is automatically cleaned up from the store.\n *\n * Note: This functionality is for advanced users who want to build their own framework integrations.\n * Our SDK also provides a React integration (useQuery hook) for convenient usage.\n *\n * Note: Automatic cleanup can interfere with React Suspense because if a component suspends while being the only subscriber,\n * cleanup might occur unexpectedly. In such cases, consider using `resolveQuery` instead.\n *\n * @beta\n */\nexport function getQueryState<\n TQuery extends string = string,\n TDataset extends string = string,\n TProjectId extends string = string,\n>(\n instance: SanityInstance,\n queryOptions: QueryOptions<TQuery, TDataset, TProjectId>,\n): StateSource<ResolveQueryResult<TQuery, `${TProjectId}.${TDataset}`> | undefined>\n\n/** @beta */\nexport function getQueryState<TData>(\n instance: SanityInstance,\n queryOptions: QueryOptions,\n): StateSource<TData | undefined>\n\n/** @beta */\nexport function getQueryState(\n instance: SanityInstance,\n queryOptions: QueryOptions,\n): StateSource<unknown>\n\n/** @beta */\nexport function getQueryState(\n ...args: Parameters<typeof _getQueryState>\n): ReturnType<typeof _getQueryState> {\n return _getQueryState(...args)\n}\nconst _getQueryState = bindActionByResource(\n queryStore,\n createStateSourceAction({\n selector: ({state, instance}: SelectorContext<QueryStoreState>, options: QueryOptions) => {\n if (state.error) throw state.error\n const key = getQueryKey(instance, options)\n const queryState = state.queries[key]\n if (queryState?.error) throw queryState.error\n return queryState?.result\n },\n onSubscribe: ({state, instance}, options: QueryOptions) => {\n const subscriptionId = randomId(16)\n const key = getQueryKey(instance, options)\n\n state.set('addSubscriber', addSubscriber(key, subscriptionId))\n\n return () => {\n // this runs on unsubscribe\n setCleanupTimeout(\n () => state.set('removeSubscriber', removeSubscriber(key, subscriptionId)),\n QUERY_STATE_CLEAR_DELAY,\n )\n }\n },\n }),\n)\n\n/**\n * Resolves the result of a query without registering a lasting subscriber.\n *\n * This function fetches the result of a GROQ query and returns a promise that resolves with the query result.\n * It registers a temporary subscriber for the lifetime of the resolution (released shortly after the promise\n * settles), so the query state participates in normal cleanup even when no lasting subscriber ever attaches —\n * e.g. when a suspended component errors before committing. This makes it ideal for use with React Suspense,\n * where the returned promise is thrown to delay rendering until the query result becomes available.\n * Once the promise resolves, it is expected that a real subscriber will be added via `getQueryState` to manage ongoing updates.\n *\n * Additionally, an optional AbortSignal can be provided to cancel the query and immediately clear the associated state\n * if there are no other active subscribers.\n *\n * @beta\n */\nexport function resolveQuery<\n TQuery extends string = string,\n TDataset extends string = string,\n TProjectId extends string = string,\n>(\n instance: SanityInstance,\n queryOptions: ResolveQueryOptions<TQuery, TDataset, TProjectId>,\n): Promise<ResolveQueryResult<TQuery, `${TProjectId}.${TDataset}`>>\n\n/** @beta */\nexport function resolveQuery<TData>(\n instance: SanityInstance,\n queryOptions: ResolveQueryOptions,\n): Promise<TData>\n/** @beta */\nexport function resolveQuery(...args: Parameters<typeof _resolveQuery>): Promise<unknown> {\n return _resolveQuery(...args)\n}\nconst _resolveQuery = bindActionByResource(\n queryStore,\n ({state, instance}, {signal, ...options}: ResolveQueryOptions) => {\n const normalized = normalizeOptionsWithPerspective(instance, options)\n const {getCurrent} = getQueryState(instance, normalized)\n const key = getQueryKey(instance, normalized)\n\n // Hold a temporary subscription for the lifetime of this resolution so the\n // key participates in normal cleanup. Without one, a fetch that errors\n // while a component is suspended leaves a subscriber-less key behind — the\n // component never commits, so no other subscriber exists — and its stored\n // error would be rethrown on every future mount without ever refetching.\n const subscriptionId = randomId(16)\n state.set('addSubscriber', addSubscriber(key, subscriptionId))\n\n const aborted$ = signal\n ? new Observable<void>((observer) => {\n const cleanup = () => {\n signal.removeEventListener('abort', listener)\n }\n\n const listener = () => {\n observer.error(new DOMException('The operation was aborted.', 'AbortError'))\n observer.complete()\n cleanup()\n }\n signal.addEventListener('abort', listener)\n\n return cleanup\n }).pipe(\n catchError((error) => {\n if (error instanceof Error && error.name === 'AbortError') {\n // Release immediately (not after the clear delay) so that when\n // this was the only subscriber, the key removal tears down the\n // in-flight request right away — e.g. when useQuery switches\n // to a different query\n state.set('removeSubscriber', removeSubscriber(key, subscriptionId))\n }\n throw error\n }),\n )\n : NEVER\n\n const resolved$ = state.observable.pipe(\n map(getCurrent),\n first((i) => i !== undefined),\n )\n\n const promise = firstValueFrom(race([resolved$, aborted$]))\n const releaseSubscriber = () => {\n setCleanupTimeout(() => {\n state.set('removeSubscriber', removeSubscriber(key, subscriptionId))\n }, QUERY_STATE_CLEAR_DELAY)\n }\n promise.then(releaseSubscriber, releaseSubscriber)\n return promise\n },\n)\n","","import {version} from '../package.json'\nimport {getEnv} from './utils/getEnv'\n\n/**\n * This version is provided by pkg-utils at build time\n * @internal\n */\nexport const CORE_SDK_VERSION = getEnv('PKG_VERSION') || `${version}-development`\n"],"mappings":"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"}
1
+ {"version":3,"file":"version-fBDdKP8q.js","names":["\"publishAt\"","\"intendedPublishAt\""],"sources":["../src/auth/projectAccessError.ts","../src/favorites/favorites.ts","../src/users/usersConstants.ts","../src/users/reducers.ts","../src/client/liveEvents.ts","../src/releases/observeReleases.ts","../src/releases/utils/sortReleases.ts","../src/releases/releasesStore.ts","../src/releases/getPerspectiveState.ts","../src/query/queryStoreConstants.ts","../src/query/reducers.ts","../src/query/queryStore.ts","../package.json","../src/version.ts"],"sourcesContent":["import {ClientError} from '@sanity/client'\n\nimport {type SanityInstance} from '../store/createSanityInstance'\nimport {getCurrentUserState} from './authStore'\nimport {getClientErrorApiBody, getClientErrorApiProjectId, getClientErrorApiType} from './utils'\n\n/**\n * Identifiers from a `projectUserNotFoundError` response. Each field is\n * optional because older API responses only carry a description.\n *\n * @internal\n */\nexport interface ProjectAccessErrorDetails {\n /** The project the failed request was made against. */\n projectId?: string\n /** The global ID of the signed-in user, which has no membership in the project. */\n userId?: string\n /** The trace ID of the failed request. Support uses it to find the request in logs. */\n traceId?: string\n}\n\nfunction findClientError(error: unknown): ClientError | null {\n if (error instanceof ClientError) return error\n if (error instanceof Error && error.cause instanceof ClientError) return error.cause\n return null\n}\n\nfunction stringOrUndefined(value: unknown): string | undefined {\n return typeof value === 'string' && value ? value : undefined\n}\n\n/**\n * Reads the identifiers from the 401 `projectUserNotFoundError` that the\n * Content Lake returns when the signed-in user is not a member of the project.\n * Accepts the `ClientError` itself or an error that wraps it as its `cause`,\n * such as the React package's `AuthError`.\n *\n * @returns The identifiers, or `null` when the error is not a\n * `projectUserNotFoundError`.\n * @internal\n */\nexport function getProjectAccessErrorDetails(error: unknown): ProjectAccessErrorDetails | null {\n const clientError = findClientError(error)\n if (\n !clientError ||\n clientError.statusCode !== 401 ||\n getClientErrorApiType(clientError) !== 'projectUserNotFoundError'\n ) {\n return null\n }\n\n const body = getClientErrorApiBody(clientError)?.error\n return {\n projectId: getClientErrorApiProjectId(clientError),\n userId: stringOrUndefined(body?.userID),\n traceId: stringOrUndefined(clientError.traceId),\n }\n}\n\n/**\n * Returns the ID of the project that rejected a request because the signed-in\n * user isn't a member of it. The Content Lake reports this as a 401\n * `projectUserNotFoundError`. It usually means the user signed in with a\n * different account than the one that has access, for example Google instead\n * of SSO with the same email address.\n *\n * When this error reaches the SDK's `AuthBoundary`, the boundary replaces the\n * whole app with a screen that explains the problem. An app-level error\n * boundary inside `AuthBoundary` catches the error first, so it decides where\n * the error goes. Rethrow it when the app can't work without the rejected\n * project. Handle it in place when only part of the app reads from that\n * project, so a user who can access the app's other projects can keep using\n * them.\n *\n * @param error - The value to inspect. A `ClientError`, or an error that wraps\n * one as its `cause`.\n * @returns The rejected project's ID, or `null` when the error isn't a\n * `projectUserNotFoundError` or the response doesn't name the project.\n *\n * @example Rethrowing only for the project the whole app needs\n * ```tsx\n * const MAIN_PROJECT_ID = 'abc123'\n *\n * function Fallback({error}: FallbackProps) {\n * const projectId = getProjectAccessErrorProjectId(error)\n * // The app can't work without its main project, so let AuthBoundary\n * // replace it with the project access screen.\n * if (projectId === MAIN_PROJECT_ID) throw error\n * if (projectId) return <p>You don't have access to project {projectId}.</p>\n * return <p>Something went wrong.</p>\n * }\n * ```\n *\n * @category Authentication\n * @public\n */\nexport function getProjectAccessErrorProjectId(error: unknown): string | null {\n return getProjectAccessErrorDetails(error)?.projectId ?? null\n}\n\n// Provider IDs come from the `provider` field of `/users/me`. SAML providers\n// are org-configured and arrive as `saml-<providerId>`.\nconst SIGN_IN_METHOD_LABELS: Record<string, string> = {\n google: 'Google',\n github: 'GitHub',\n sanity: 'email and password',\n vercel: 'Vercel',\n}\n\n/**\n * Returns a user-facing name for a `/users/me` `provider` value, such as\n * `Google` for `google` or `SSO` for any `saml-*` provider.\n *\n * @returns The label, or `undefined` for an unknown or missing provider.\n * @internal\n */\nexport function getSignInMethodLabel(provider: string | undefined): string | undefined {\n if (!provider) return undefined\n if (provider.startsWith('saml-')) return 'SSO'\n return SIGN_IN_METHOD_LABELS[provider]\n}\n\n// Names the sign-in method but never the email address, because error\n// messages end up in logs and error trackers.\nfunction getProjectAccessErrorMessage(\n details: ProjectAccessErrorDetails,\n provider: string | undefined,\n): string {\n const method = getSignInMethodLabel(provider)\n const account = method ? `Your Sanity account (signed in with ${method})` : 'Your Sanity account'\n const project = details.projectId ? `project ${details.projectId}` : 'this project'\n // Matches the trace ID suffix @sanity/client adds to ClientError messages.\n const traceId = details.traceId ? ` (traceId: ${details.traceId})` : ''\n return (\n `${account} isn't a member of ${project}. ` +\n 'Each sign-in method, such as Google or SSO, is a separate account. ' +\n `Sign out and sign in with the account that has access.${traceId}`\n )\n}\n\n// Keeps everything the original ClientError carries (status code, response\n// body, trace ID) so `instanceof ClientError` checks and\n// `getProjectAccessErrorDetails` keep working on it.\nclass ProjectAccessClientError extends ClientError {\n constructor(error: ClientError, message: string) {\n super(error.response)\n this.message = message\n }\n}\n\n/**\n * Replaces the API's `projectUserNotFoundError` message with one that tells\n * the user what to do. Hooks throw store errors to the nearest error boundary,\n * and most boundaries, including routers' default error screens, render\n * `error.message`. Any other error is returned unchanged.\n *\n * @internal\n */\nexport function withProjectAccessMessage(instance: SanityInstance, error: unknown): unknown {\n if (!(error instanceof ClientError) || error instanceof ProjectAccessClientError) return error\n const details = getProjectAccessErrorDetails(error)\n if (!details) return error\n\n const provider = getCurrentUserState(instance).getCurrent()?.provider\n return new ProjectAccessClientError(error, getProjectAccessErrorMessage(details, provider))\n}\n","import {\n type CanvasResource,\n type Events,\n type FrameMessages,\n type MediaResource,\n SDK_CHANNEL_NAME,\n SDK_NODE_NAME,\n type StudioResource,\n type WindowMessages,\n} from '@sanity/message-protocol'\nimport {catchError, first, from, map, type Observable, of, switchMap} from 'rxjs'\n\nimport {getNodeState} from '../comlink/node/getNodeState'\nimport {type DocumentHandle} from '../config/sanityConfig'\nimport {type SanityInstance} from '../store/createSanityInstance'\nimport {defineFetcher, defineMutation} from '../store/fetcherStore'\n\n/**\n * @public\n */\nexport interface FavoriteStatusResponse {\n isFavorited: boolean\n}\n\n/**\n * @public\n */\nexport interface FavoriteDocumentContext extends DocumentHandle {\n resourceId: string\n resourceType: StudioResource['type'] | MediaResource['type'] | CanvasResource['type']\n schemaName?: string\n}\n\n/**\n * The `document` a favorite write addresses over Comlink.\n *\n * @internal\n */\nexport function toFavoriteDocument(context: FavoriteDocumentContext): {\n id: string\n type: string\n resource: {id: string; type: FavoriteDocumentContext['resourceType']; schemaName?: string}\n} {\n return {\n id: context.documentId,\n type: context.documentType,\n resource: {\n id: context.resourceId,\n type: context.resourceType,\n ...(context.schemaName ? {schemaName: context.schemaName} : {}),\n },\n }\n}\n\n// Helper to create a stable key for the store\nfunction createFavoriteKey(context: FavoriteDocumentContext): string {\n return `${context.documentId}:${context.documentType}:${context.resourceId}:${context.resourceType}${\n context.schemaName ? `:${context.schemaName}` : ''\n }`\n}\n\n/**\n * Fetcher for a document's favorite status, read from the dashboard over\n * comlink, on the shared fetcher cache.\n *\n * @internal\n */\nexport const favorites = defineFetcher<[context: FavoriteDocumentContext], FavoriteStatusResponse>({\n name: 'favorites',\n getKey: (_instance: SanityInstance, context: FavoriteDocumentContext) =>\n createFavoriteKey(context),\n // Tag each entry with its key so `setFavorite` can invalidate exactly it.\n tags: (_data, context) => [{type: 'favorite', id: createFavoriteKey(context)}],\n fetch: (instance) => {\n return (context: FavoriteDocumentContext): Observable<FavoriteStatusResponse> => {\n const nodeStateSource = getNodeState<FrameMessages, WindowMessages>(instance, {\n name: SDK_NODE_NAME,\n connectTo: SDK_CHANNEL_NAME,\n })\n const payload = {document: toFavoriteDocument(context)}\n\n return nodeStateSource.observable.pipe(\n // Wait until connected, then complete after the single fetch settles.\n first((nodeState) => !!nodeState),\n switchMap((nodeState) => {\n const node = nodeState!.node\n return from(node.fetch('dashboard/v1/events/favorite/query', payload)).pipe(\n map((response) => ({isFavorited: response.isFavorited})),\n catchError((err) => {\n // eslint-disable-next-line no-console\n console.error('Favorites service connection error', err)\n return of({isFavorited: false})\n }),\n )\n }),\n )\n }\n },\n})\n\n/**\n * Input for {@link setFavorite}: the document context plus the desired state.\n *\n * @public\n */\nexport type SetFavoriteInput = FavoriteDocumentContext & {\n /** The favorite state to move to: `true` to favorite, `false` to unfavorite. */\n isFavorited: boolean\n}\n\n/**\n * Sets a document's favorite state over comlink. Writes the new state into the\n * cached {@link favorites} status before the request (rolled back on failure),\n * then invalidates it so active readers reconverge on server truth. The\n * write-side counterpart to {@link favorites}.\n *\n * @internal\n */\nexport const setFavorite = defineMutation<SetFavoriteInput, FavoriteStatusResponse>({\n name: 'setFavorite',\n mutationFn: (instance) => {\n return ({isFavorited, ...context}: SetFavoriteInput): Observable<FavoriteStatusResponse> => {\n const nodeStateSource = getNodeState<FrameMessages, WindowMessages>(instance, {\n name: SDK_NODE_NAME,\n connectTo: SDK_CHANNEL_NAME,\n })\n const payload: Events.FavoriteMutateMessage['data'] = {\n eventType: isFavorited ? 'added' : 'removed',\n document: toFavoriteDocument(context),\n }\n\n return nodeStateSource.observable.pipe(\n // Wait until connected, then complete after the single mutation settles.\n first((nodeState) => !!nodeState),\n switchMap((nodeState) => {\n const node = nodeState!.node\n return from(node.fetch('dashboard/v1/events/favorite/mutate', payload)).pipe(\n map((response) => {\n if (!response.success) throw new Error('Failed to update favorite status')\n return {isFavorited}\n }),\n )\n }),\n )\n }\n },\n onMutate: (write, {isFavorited, ...context}) => write(favorites, [context], {isFavorited}),\n invalidates: (_result, input) => [{type: 'favorite', id: createFavoriteKey(input)}],\n})\n","// NOTE: currently this API is only available on vX\nexport const API_VERSION = 'vX'\nexport const PROJECT_API_VERSION = '2025-07-18'\nexport const USERS_STATE_CLEAR_DELAY = 5000\nexport const DEFAULT_USERS_BATCH_SIZE = 100\n","import {type SanityInstance} from '../store/createSanityInstance'\nimport {omitProperty} from '../utils/object'\nimport {type GetUsersOptions, type SanityUserResponse, type UsersStoreState} from './types'\nimport {DEFAULT_USERS_BATCH_SIZE} from './usersConstants'\n\n/** @internal */\nexport const getUsersKey = (\n instance: SanityInstance,\n {\n resourceType,\n organizationId,\n batchSize = DEFAULT_USERS_BATCH_SIZE,\n projectId = instance.config.projectId,\n userId,\n }: GetUsersOptions = {},\n): string =>\n JSON.stringify({\n resourceType,\n organizationId,\n batchSize,\n projectId,\n userId,\n } satisfies ReturnType<typeof parseUsersKey>)\n\n/** @internal */\nexport const parseUsersKey = (\n key: string,\n): {\n batchSize: number\n resourceType?: 'organization' | 'project'\n projectId?: string\n organizationId?: string\n userId?: string\n} => JSON.parse(key)\n\nexport const addSubscription =\n (subscriptionId: string, key: string) =>\n (prev: UsersStoreState): UsersStoreState => {\n const group = prev.users[key]\n const subscriptions = [...(group?.subscriptions ?? []), subscriptionId]\n return {...prev, users: {...prev.users, [key]: {...group, subscriptions}}}\n }\n\nexport const removeSubscription =\n (subscriptionId: string, key: string) =>\n (prev: UsersStoreState): UsersStoreState => {\n const group = prev.users[key]\n if (!group) return prev\n const subscriptions = group.subscriptions.filter((id) => id !== subscriptionId)\n if (!subscriptions.length) return {...prev, users: omitProperty(prev.users, key)}\n return {...prev, users: {...prev.users, [key]: {...group, subscriptions}}}\n }\n\nexport const setUsersData =\n (key: string, {data, nextCursor, totalCount}: SanityUserResponse) =>\n (prev: UsersStoreState): UsersStoreState => {\n const group = prev.users[key]\n if (!group) return prev\n const users = [...(group.users ?? []), ...data]\n return {...prev, users: {...prev.users, [key]: {...group, users, totalCount, nextCursor}}}\n }\n\nexport const updateLastLoadMoreRequest =\n (timestamp: string, key: string) =>\n (prev: UsersStoreState): UsersStoreState => {\n const group = prev.users[key]\n if (!group) return prev\n return {...prev, users: {...prev.users, [key]: {...group, lastLoadMoreRequest: timestamp}}}\n }\n\nexport const setUsersError =\n (key: string, error: unknown) =>\n (prev: UsersStoreState): UsersStoreState => {\n const group = prev.users[key]\n if (!group) return prev\n return {...prev, users: {...prev.users, [key]: {...group, error}}}\n }\n\nexport const cancelRequest =\n (key: string) =>\n (prev: UsersStoreState): UsersStoreState => {\n const group = prev.users[key]\n if (!group) return prev\n if (group.subscriptions.length) return prev\n return {...prev, users: omitProperty(prev.users, key)}\n }\n\nexport const initializeRequest =\n (key: string) =>\n (prev: UsersStoreState): UsersStoreState => {\n if (prev.users[key]) return prev\n return {...prev, users: {...prev.users, [key]: {subscriptions: []}}}\n }\n","import {\n ConnectionFailedError,\n CorsOriginError,\n DisconnectError,\n type LiveEventMessage,\n} from '@sanity/client'\nimport {\n defer,\n distinctUntilChanged,\n EMPTY,\n filter,\n map,\n type Observable,\n of,\n switchMap,\n timer,\n} from 'rxjs'\n\nimport {getClientAuthState, getTokenState} from '../auth/authStore'\nimport {type DocumentResource} from '../config/sanityConfig'\nimport {type SanityInstance} from '../store/createSanityInstance'\nimport {getClientState} from './clientStore'\nimport {retryWithCredential} from './retry'\n\n/**\n * All live-events subscriptions must use identical connection options\n * (API version, request tag, `includeDrafts`): `@sanity/client` caches the\n * underlying EventSource per URL + options, so divergent options would\n * silently split what should be a single shared connection.\n */\nconst LIVE_EVENTS_API_VERSION = 'v2025-05-06'\n\n/**\n * Delay before re-establishing the live events connection after a\n * server-initiated error (e.g. ChannelError, MessageError). Live errors are\n * retried rather than surfaced because an errored live connection would\n * otherwise poison the consuming store. Plain connection drops never reach\n * this — they are reconnected inside `@sanity/client`.\n *\n * @internal\n */\nexport const LIVE_EVENTS_RETRY_DELAY = 1000\n\n/**\n * Options for {@link observeLiveEvents}.\n * @internal\n */\nexport interface ObserveLiveEventsOptions {\n /** Resource to scope the underlying client and live connection to. */\n resource?: DocumentResource\n /**\n * Called when the connection fails due to a CORS misconfiguration. The\n * error is swallowed (the stream never errors; it idles) so consumers can\n * surface it as store state instead of a stream error.\n */\n onCorsError: (error: unknown) => void\n}\n\n/**\n * Emits Live Content API messages for a dataset so consumers can invalidate\n * fetched data via sync tags.\n *\n * All consumers observe the same underlying EventSource connection:\n * `@sanity/client` caches the live-events stream per URL and connection\n * options, and every subscription made through this function uses the same\n * API version and request tag.\n *\n * @internal\n */\nexport function observeLiveEvents(\n instance: SanityInstance,\n {resource, onCorsError}: ObserveLiveEventsOptions,\n): Observable<LiveEventMessage> {\n // Drafts need a token. Other clients are rebuilt when their token changes,\n // but an OAuth app's client follows its token through `auth`, so reconnect it\n // only when a token appears or disappears, not on every refresh.\n const hasToken$ = getTokenState(instance).observable.pipe(map(Boolean), distinctUntilChanged())\n const connection$ = getClientState(instance, {\n apiVersion: LIVE_EVENTS_API_VERSION,\n resource,\n }).observable.pipe(\n switchMap((client) =>\n (client.config().auth ? hasToken$ : of(Boolean(client.config().token))).pipe(\n map((includeDrafts) => [client, includeDrafts] as const),\n ),\n ),\n )\n\n return connection$.pipe(\n switchMap(([client, includeDrafts]) =>\n retryWithCredential(\n defer(() => client.live.events({includeDrafts, tag: 'live-events'})),\n getClientAuthState(instance),\n (error, _, credentialChanged) => {\n if (error instanceof CorsOriginError) {\n // Swallow CORS errors without bubbling up so that they can be\n // handled by the consumer (e.g. shown via the Cors Error component)\n onCorsError(error)\n return EMPTY\n }\n if (error instanceof DisconnectError) {\n // The server explicitly told this client to stop reconnecting —\n // end live updates without erroring (consumers keep serving data,\n // they just stop receiving live invalidation)\n return EMPTY\n }\n if (\n error instanceof ConnectionFailedError &&\n typeof error.status === 'number' &&\n error.status >= 400 &&\n error.status < 500\n ) {\n // The server rejected the connection with a 4xx (e.g. a 401 from\n // an expired token) — it will keep rejecting the same credential,\n // so retrying on a timer would reconnect once per second forever.\n // Reconnect once the credential changes instead. A\n // ConnectionFailedError without a status stays retryable: it may\n // be a transient network failure.\n return credentialChanged\n }\n // Server-initiated live errors (e.g. ChannelError, MessageError) are\n // retried, not surfaced. Dropped connections are already reconnected\n // inside @sanity/client.\n return timer(LIVE_EVENTS_RETRY_DELAY)\n },\n ),\n ),\n filter((e): e is LiveEventMessage => e.type === 'message'),\n )\n}\n","import {type ReleaseDocument, type SyncTag} from '@sanity/client'\nimport {\n BehaviorSubject,\n combineLatest,\n distinctUntilChanged,\n filter,\n map,\n type Observable,\n startWith,\n switchMap,\n tap,\n} from 'rxjs'\n\nimport {getClientAuthState} from '../auth/authStore'\nimport {getClientState} from '../client/clientStore'\nimport {observeLiveEvents} from '../client/liveEvents'\nimport {retryRead} from '../client/retry'\nimport {type DocumentResource} from '../config/sanityConfig'\nimport {type SanityInstance} from '../store/createSanityInstance'\n\nconst RELEASES_QUERY = 'releases::all()'\nconst RELEASES_API_VERSION = 'v2025-05-06'\n\n/**\n * Options for {@link observeReleases}.\n * @internal\n */\nexport interface ObserveReleasesOptions {\n /** Resource to scope the underlying client and live connection to. */\n resource?: DocumentResource\n /**\n * Called when the live events connection fails due to a CORS\n * misconfiguration. See `observeLiveEvents`.\n */\n onCorsError: (error: unknown) => void\n /** Receives a failed fetch, and `undefined` once fetching recovers. */\n onError: (error: unknown) => void\n}\n\n/**\n * Emits every release document (including archived and published), refetching\n * whenever a Live Content API event matches the query's sync tags.\n *\n * This fetches directly through the client store — deliberately not via the\n * query store — because release data is itself an input to query perspective\n * resolution (`getPerspectiveState`); fetching through the query store would\n * make the two stores mutually dependent.\n *\n * @internal\n */\nexport function observeReleases(\n instance: SanityInstance,\n {resource, onCorsError, onError}: ObserveReleasesOptions,\n): Observable<ReleaseDocument[] | undefined> {\n const client$ = getClientState(instance, {\n apiVersion: RELEASES_API_VERSION,\n resource,\n }).observable\n\n return client$.pipe(\n switchMap((client) => {\n const syncTags$ = new BehaviorSubject<SyncTag[] | undefined>(undefined)\n\n // Pair the latest live message with the latest known sync tags so that\n // a message arriving while a fetch is still in flight is re-evaluated\n // (and refetched if it matches) once that fetch's tags land — instead\n // of being dropped and leaving the store stale until the next event.\n const refetchEventId$ = combineLatest([\n observeLiveEvents(instance, {resource, onCorsError}).pipe(startWith(undefined)),\n syncTags$,\n ]).pipe(\n filter(\n ([message, syncTags]) =>\n message === undefined || message.tags.some((tag) => syncTags?.includes(tag)),\n ),\n map(([message]) => message?.id),\n distinctUntilChanged(),\n )\n\n return refetchEventId$.pipe(\n switchMap((lastLiveEventId) =>\n client.observable.fetch<ReleaseDocument[]>(\n RELEASES_QUERY,\n {},\n {\n perspective: 'raw',\n filterResponse: false,\n returnQuery: false,\n lastLiveEventId,\n tag: 'releases',\n },\n ),\n ),\n tap((response) => {\n syncTags$.next(response.syncTags)\n }),\n map((response) => response.result),\n )\n }),\n retryRead(getClientAuthState(instance), onError),\n )\n}\n","import {type ReleaseDocument} from '@sanity/client'\n\n// mirrors the order of the releases in the releases list in Studio\n// https://github.com/sanity-io/sanity/blob/main/packages/sanity/src/core/releases/hooks/utils.ts\nexport function sortReleases(releases: ReleaseDocument[] = []): ReleaseDocument[] {\n // The order should always be:\n // [undecided (sortByCreatedAt), scheduled(sortBy publishAt || metadata.intendedPublishAt), asap(sortByCreatedAt)]\n return [...releases].sort((a, b) => {\n // metadata is optional on a release document; guard against releases that\n // have no metadata at all so sorting can't throw and wipe out the list.\n const aType = a.metadata?.releaseType\n const bType = b.metadata?.releaseType\n\n // undecided are always first, then by createdAt descending\n if (aType === 'undecided' && bType !== 'undecided') {\n return -1\n }\n if (aType !== 'undecided' && bType === 'undecided') {\n return 1\n }\n if (aType === 'undecided' && bType === 'undecided') {\n // Sort by createdAt\n return new Date(b._createdAt).getTime() - new Date(a._createdAt).getTime()\n }\n\n // Scheduled are always at the middle, then by publishAt descending\n if (aType === 'scheduled' && bType === 'scheduled') {\n const aPublishAt = a['publishAt'] || a.metadata?.['intendedPublishAt']\n if (!aPublishAt) {\n return 1\n }\n const bPublishAt = b['publishAt'] || b.metadata?.['intendedPublishAt']\n if (!bPublishAt) {\n return -1\n }\n return new Date(bPublishAt).getTime() - new Date(aPublishAt).getTime()\n }\n\n // ASAP are always last, then by createdAt descending\n if (aType === 'asap' && bType !== 'asap') {\n return 1\n }\n if (aType !== 'asap' && bType === 'asap') {\n return -1\n }\n if (aType === 'asap' && bType === 'asap') {\n // Sort by createdAt\n return new Date(b._createdAt).getTime() - new Date(a._createdAt).getTime()\n }\n\n return 0\n })\n}\n","import {type ReleaseDocument} from '@sanity/client'\nimport {map} from 'rxjs'\n\nimport {type DocumentResource} from '../config/sanityConfig'\nimport {bindActionByResource, type BoundResourceKey} from '../store/createActionBinder'\nimport {type SanityInstance} from '../store/createSanityInstance'\nimport {createStateSourceAction, type StateSource} from '../store/createStateSourceAction'\nimport {defineStore, type StoreContext} from '../store/defineStore'\nimport {observeReleases} from './observeReleases'\nimport {sortReleases} from './utils/sortReleases'\n\nconst ARCHIVED_RELEASE_STATES = ['archived', 'published']\nconst STABLE_EMPTY_RELEASES: ReleaseDocument[] = []\n\n/**\n * Lifecycle states a release document can be in. Mirrors the server's\n * `ReleaseState`.\n * @beta\n */\nexport type ReleaseState =\n | 'active'\n | 'archiving'\n | 'unarchiving'\n | 'archived'\n | 'published'\n | 'publishing'\n | 'scheduled'\n | 'scheduling'\n\nexport interface ReleasesStoreState {\n activeReleases?: ReleaseDocument[]\n allReleases?: ReleaseDocument[]\n error?: unknown\n fetchError?: unknown\n}\n\nexport const releasesStore = defineStore<ReleasesStoreState, BoundResourceKey>({\n name: 'Releases',\n // Empty rather than undefined, so the React hooks do not suspend on first load. A\n // reconnect keeps whatever was last known until the fetch returns.\n getInitialState: (): ReleasesStoreState => ({\n activeReleases: STABLE_EMPTY_RELEASES,\n allReleases: STABLE_EMPTY_RELEASES,\n }),\n upstream: (context) => subscribeToReleases(context),\n})\n\n/**\n * Get the active releases from the store.\n * @internal\n */\nconst _getActiveReleasesState = bindActionByResource(\n releasesStore,\n createStateSourceAction({\n selector: ({state}) => {\n if (state.error ?? state.fetchError) throw state.error ?? state.fetchError\n return state.activeReleases\n },\n }),\n)\n\n/**\n * Get the active releases from the store.\n * @internal\n */\nexport const getActiveReleasesState = (\n instance: SanityInstance,\n options?: {resource?: DocumentResource},\n): StateSource<ReleaseDocument[] | undefined> =>\n // bindActionByResource keyFn destructures { resource } from the first param, so pass {} when no options\n _getActiveReleasesState(instance, options ?? {})\n\n/**\n * Get every release in the store, including archived and published.\n * @internal\n */\nconst _getAllReleasesState = bindActionByResource(\n releasesStore,\n createStateSourceAction({\n selector: ({state}) => {\n if (state.error ?? state.fetchError) throw state.error ?? state.fetchError\n return state.allReleases\n },\n }),\n)\n\n/**\n * Get every release in the store, including archived and published.\n * @internal\n */\nexport const getAllReleasesState = (\n instance: SanityInstance,\n options?: {resource?: DocumentResource},\n): StateSource<ReleaseDocument[] | undefined> => _getAllReleasesState(instance, options ?? {})\n\nconst subscribeToReleases = ({\n instance,\n state,\n key: {resource},\n}: StoreContext<ReleasesStoreState, BoundResourceKey>) => {\n const releases$ = observeReleases(instance, {\n resource,\n // Surface CORS errors as store state instead of erroring the stream so\n // they can be handled by the Cors Error component\n onCorsError: (error) => state.set('setError', {error}),\n onError: (fetchError) => state.set('setFetchError', {fetchError}),\n })\n return releases$\n .pipe(\n map((releases) => {\n // logic here mirrors that of studio:\n // https://github.com/sanity-io/sanity/blob/156e8fa482703d99219f08da7bacb384517f1513/packages/sanity/src/core/releases/store/useActiveReleases.ts#L29\n const sorted = sortReleases(releases ?? STABLE_EMPTY_RELEASES).reverse()\n state.set('setReleases', {\n allReleases: sorted,\n activeReleases: sorted.filter(\n (release) => !ARCHIVED_RELEASE_STATES.includes(release.state),\n ),\n fetchError: undefined,\n })\n }),\n )\n .subscribe({error: (error) => state.set('setError', {error})})\n}\n","import {createSelector} from 'reselect'\n\nimport {type DocumentResource, type PerspectiveHandle} from '../config/sanityConfig'\nimport {bindActionByResource, type BoundStoreAction} from '../store/createActionBinder'\nimport {createStateSourceAction, type SelectorContext} from '../store/createStateSourceAction'\nimport {releasesStore, type ReleasesStoreState} from './releasesStore'\nimport {isReleasePerspective} from './utils/isReleasePerspective'\nimport {sortReleases} from './utils/sortReleases'\n\nconst DEFAULT_PERSPECTIVE = 'drafts'\n\n// Cache for options\nconst optionsCache = new Map<string, Map<string, PerspectiveHandle>>()\n\nconst selectInstancePerspective = (context: SelectorContext<ReleasesStoreState>, _?: unknown) =>\n context.instance.config.perspective\nconst selectActiveReleases = (context: SelectorContext<ReleasesStoreState>) =>\n context.state.activeReleases\nconst selectOptions = (\n _context: SelectorContext<ReleasesStoreState>,\n options: PerspectiveHandle & {projectId?: string; dataset?: string; resource?: DocumentResource},\n) => options\n\nconst memoizedOptionsSelector = createSelector(\n [selectActiveReleases, selectOptions],\n (activeReleases, options) => {\n if (!options || !activeReleases) return options\n\n // Use release document IDs as the cache key\n const releaseIds = activeReleases.map((release) => release._id).join(',')\n let nestedCache = optionsCache.get(releaseIds)\n if (!nestedCache) {\n nestedCache = new Map<string, PerspectiveHandle>()\n optionsCache.set(releaseIds, nestedCache)\n }\n\n const optionsKey = JSON.stringify(options)\n let cachedOptions = nestedCache.get(optionsKey)\n\n if (!cachedOptions) {\n cachedOptions = options\n nestedCache.set(optionsKey, cachedOptions)\n }\n return cachedOptions\n },\n)\n\nconst _getPerspectiveStateSelector = createStateSourceAction({\n selector: createSelector(\n [selectInstancePerspective, selectActiveReleases, memoizedOptionsSelector],\n (instancePerspective, activeReleases, memoizedOptions) => {\n const perspective = memoizedOptions?.perspective ?? instancePerspective ?? DEFAULT_PERSPECTIVE\n\n if (!isReleasePerspective(perspective)) return perspective\n\n // if there are no active releases we can't compute the release perspective\n if (!activeReleases || activeReleases.length === 0) return undefined\n\n const releaseNames = sortReleases(activeReleases).map((release) => release.name)\n const index = releaseNames.findIndex((name) => name === perspective.releaseName)\n\n if (index < 0) {\n throw new Error(`Release \"${perspective.releaseName}\" not found in active releases`)\n }\n\n const filteredReleases = releaseNames.slice(0, index + 1) // Include the release itself\n\n return ['drafts', ...filteredReleases]\n .filter((name) => !perspective.excludedPerspectives?.includes(name))\n .reverse()\n },\n ),\n})\n\ntype OmitFirst<T extends unknown[]> = T extends [unknown, ...infer R] ? R : never\ntype SelectorParams = OmitFirst<Parameters<typeof _getPerspectiveStateSelector>>\ntype BoundGetPerspectiveState = BoundStoreAction<\n ReleasesStoreState,\n SelectorParams,\n ReturnType<typeof _getPerspectiveStateSelector>\n>\n\nconst _boundGetPerspectiveState = bindActionByResource(\n releasesStore,\n _getPerspectiveStateSelector,\n) as BoundGetPerspectiveState\n\n/**\n * Provides a subscribable state source for a \"perspective\" for the Sanity client,\n * which is used to fetch documents as though certain Content Releases are active.\n *\n * @param instance - The Sanity instance to get the perspective for\n * @param options - The options for the perspective -- usually a release name\n *\n * @returns A subscribable perspective value, usually a list of applicable release names,\n * or a single release name / default perspective (such as 'drafts').\n *\n * @public\n */\nexport const getPerspectiveState: BoundGetPerspectiveState = (instance, ...rest) =>\n // bindActionByResource keyFn destructures { resource } from the first param, so pass {} when no options\n _boundGetPerspectiveState(instance, ...(rest.length ? rest : [{}]))\n","import {UPSTREAM_CLOSE_DELAY_MS} from '../store/createStoreInstance'\n\n/**\n * When a query has no more subscribers, its state is cleaned up and removed\n * from the store. A delay used to prevent re-creating resources when the last\n * subscriber is removed quickly before another one is added. This is helpful\n * when used in a frontend where components may suspend or transition to\n * different views quickly.\n *\n * Must not exceed the live connection's close delay: nothing refetches when the\n * connection reopens, so a result kept past the close would miss live events.\n */\nexport const QUERY_STATE_CLEAR_DELAY = UPSTREAM_CLOSE_DELAY_MS\nexport const QUERY_STORE_API_VERSION = 'v2025-05-06'\nexport const QUERY_STORE_DEFAULT_PERSPECTIVE = 'drafts'\n","import {omitProperty} from '../utils/object'\n\ninterface QueryState {\n syncTags?: string[]\n result?: unknown\n error?: unknown\n lastLiveEventId?: string\n subscribers: string[]\n}\n\nexport interface QueryStoreState {\n queries: {[key: string]: QueryState | undefined}\n error?: unknown\n}\n\nexport const setQueryError =\n (key: string, error: unknown) =>\n (prev: QueryStoreState): QueryStoreState => {\n const prevQuery = prev.queries[key]\n if (!prevQuery) return prev\n return {...prev, queries: {...prev.queries, [key]: {...prevQuery, error}}}\n }\n\nexport const setQueryData =\n (key: string, result: unknown, syncTags?: string[]) =>\n (prev: QueryStoreState): QueryStoreState => {\n const prevQuery = prev.queries[key]\n if (!prevQuery) return prev\n return {\n ...prev,\n queries: {...prev.queries, [key]: {...prevQuery, result: result ?? null, syncTags}},\n }\n }\n\nexport const setLastLiveEventId =\n (key: string, lastLiveEventId: string) =>\n (prev: QueryStoreState): QueryStoreState => {\n const prevQuery = prev.queries[key]\n if (!prevQuery) return prev\n return {...prev, queries: {...prev.queries, [key]: {...prevQuery, lastLiveEventId}}}\n }\n\nexport const addSubscriber =\n (key: string, subscriptionId: string) =>\n (prev: QueryStoreState): QueryStoreState => {\n const prevQuery = prev.queries[key]\n const subscribers = [...(prevQuery?.subscribers ?? []), subscriptionId]\n return {...prev, queries: {...prev.queries, [key]: {...prevQuery, subscribers}}}\n }\n\nexport const removeSubscriber =\n (key: string, subscriptionId: string) =>\n (prev: QueryStoreState): QueryStoreState => {\n const prevQuery = prev.queries[key]\n if (!prevQuery) return prev\n const subscribers = prevQuery.subscribers.filter((id) => id !== subscriptionId)\n if (!subscribers.length) return {...prev, queries: omitProperty(prev.queries, key)}\n return {...prev, queries: {...prev.queries, [key]: {...prevQuery, subscribers}}}\n }\n","import {type ResponseQueryOptions} from '@sanity/client'\nimport {\n catchError,\n combineLatest,\n distinctUntilChanged,\n EMPTY,\n filter,\n first,\n firstValueFrom,\n groupBy,\n map,\n mergeMap,\n NEVER,\n Observable,\n of,\n pairwise,\n race,\n share,\n startWith,\n switchMap,\n tap,\n} from 'rxjs'\n\nimport {getClientAuthState} from '../auth/authStore'\nimport {withProjectAccessMessage} from '../auth/projectAccessError'\nimport {getClientState} from '../client/clientStore'\nimport {observeLiveEvents} from '../client/liveEvents'\nimport {retryRead} from '../client/retry'\nimport {type DatasetHandle} from '../config/sanityConfig'\nimport {getPerspectiveState} from '../releases/getPerspectiveState'\nimport {isReleasePerspective} from '../releases/utils/isReleasePerspective'\nimport {bindActionByResource, type BoundResourceKey} from '../store/createActionBinder'\nimport {type SanityInstance} from '../store/createSanityInstance'\nimport {\n createStateSourceAction,\n type SelectorContext,\n type StateSource,\n} from '../store/createStateSourceAction'\nimport {type StoreState} from '../store/createStoreState'\nimport {defineStore, type StoreContext} from '../store/defineStore'\nimport {type ResolveQueryResult} from '../typegen/resolve'\nimport {randomId} from '../utils/ids'\nimport {setCleanupTimeout} from '../utils/setCleanupTimeout'\nimport {\n QUERY_STATE_CLEAR_DELAY,\n QUERY_STORE_API_VERSION,\n QUERY_STORE_DEFAULT_PERSPECTIVE,\n} from './queryStoreConstants'\nimport {\n addSubscriber,\n type QueryStoreState,\n removeSubscriber,\n setLastLiveEventId,\n setQueryData,\n setQueryError,\n} from './reducers'\n\n/**\n * @beta\n */\nexport interface QueryOptions<\n TQuery extends string = string,\n TDataset extends string = string,\n TProjectId extends string = string,\n>\n extends\n Pick<ResponseQueryOptions, 'useCdn' | 'cache' | 'next' | 'cacheMode' | 'tag'>,\n DatasetHandle<TDataset, TProjectId> {\n query: TQuery\n params?: Record<string, unknown>\n}\n\n/**\n * @beta\n */\nexport interface ResolveQueryOptions<\n TQuery extends string = string,\n TDataset extends string = string,\n TProjectId extends string = string,\n> extends QueryOptions<TQuery, TDataset, TProjectId> {\n signal?: AbortSignal\n}\n\nconst EMPTY_ARRAY: never[] = []\n\n/** @internal */\nexport const getQueryKey = (instance: SanityInstance, options: QueryOptions): string =>\n JSON.stringify(normalizeOptionsWithPerspective(instance, options))\n/** @internal */\nexport const parseQueryKey = (key: string): QueryOptions => JSON.parse(key)\n\n/**\n * Ensures the query key includes an effective perspective so that\n * implicit differences (e.g. different instance.config.perspective)\n * don't collide in the dataset-scoped store.\n *\n * Since perspectives are unique, we can depend on the release stacks\n * to be correct when we retrieve the results.\n *\n */\nfunction normalizeOptionsWithPerspective(\n instance: SanityInstance,\n options: QueryOptions,\n): QueryOptions {\n if (options.perspective !== undefined) return options\n const instancePerspective = instance.config.perspective\n return {\n ...options,\n perspective:\n instancePerspective !== undefined ? instancePerspective : QUERY_STORE_DEFAULT_PERSPECTIVE,\n }\n}\n\nconst queryStore = defineStore<QueryStoreState, BoundResourceKey>({\n name: 'QueryStore',\n getInitialState: () => ({queries: {}}),\n initialize(context) {\n const subscription = listenForNewSubscribersAndFetch(context)\n return () => subscription.unsubscribe()\n },\n upstream: (context) => listenToLiveClientAndSetLastLiveEventIds(context),\n})\n\nconst errorHandler = (state: StoreState<{error?: unknown}>) => {\n return (error: unknown): void => state.set('setError', {error})\n}\n\nconst listenForNewSubscribersAndFetch = ({state, instance}: StoreContext<QueryStoreState>) => {\n return state.observable\n .pipe(\n map((s) => new Set(Object.keys(s.queries))),\n distinctUntilChanged((curr, next) => {\n if (curr.size !== next.size) return false\n return Array.from(next).every((i) => curr.has(i))\n }),\n startWith(new Set<string>()),\n pairwise(),\n mergeMap(([curr, next]) => {\n const added = Array.from(next).filter((i) => !curr.has(i))\n const removed = Array.from(curr).filter((i) => !next.has(i))\n\n return [\n ...added.map((key) => ({key, added: true})),\n ...removed.map((key) => ({key, added: false})),\n ]\n }),\n groupBy((i) => i.key),\n mergeMap((group$) =>\n group$.pipe(\n switchMap((e) => {\n if (!e.added) return EMPTY\n\n const lastLiveEventId$ = state.observable.pipe(\n map((s) => s.queries[group$.key]?.lastLiveEventId),\n distinctUntilChanged(),\n )\n const {\n query,\n params,\n projectId,\n dataset,\n tag,\n resource,\n perspective: perspectiveFromOptions,\n ...restOptions\n } = parseQueryKey(group$.key)\n\n // Short-circuit perspective resolution for non-release perspectives to avoid\n // touching the releases store (and its initialization) unnecessarily.\n const perspective$ = isReleasePerspective(perspectiveFromOptions)\n ? getPerspectiveState(instance, {\n perspective: perspectiveFromOptions,\n resource,\n }).observable.pipe(filter(Boolean))\n : of(perspectiveFromOptions ?? QUERY_STORE_DEFAULT_PERSPECTIVE)\n\n const client$ = getClientState(instance, {\n apiVersion: QUERY_STORE_API_VERSION,\n projectId,\n dataset,\n resource,\n }).observable\n\n return combineLatest({\n lastLiveEventId: lastLiveEventId$,\n client: client$,\n perspective: perspective$,\n }).pipe(\n switchMap(({lastLiveEventId, client, perspective}) =>\n client.observable.fetch(query, params, {\n ...restOptions,\n perspective,\n filterResponse: false,\n returnQuery: false,\n lastLiveEventId,\n tag,\n }),\n ),\n tap(({result, syncTags}) => {\n state.set('setQueryData', setQueryData(group$.key, result, syncTags))\n }),\n // Retry inside the per-event stream: erroring the group pipe would\n // complete the group's subscription, and since `groupBy` above never\n // removes its group subjects, re-adding the key would emit into a\n // subject with no subscribers — the key could never be fetched again.\n retryRead(getClientAuthState(instance), (error) =>\n state.set(\n 'setQueryError',\n setQueryError(group$.key, withProjectAccessMessage(instance, error)),\n ),\n ),\n )\n }),\n ),\n ),\n )\n .subscribe({error: errorHandler(state)})\n}\n\nconst listenToLiveClientAndSetLastLiveEventIds = ({\n state,\n instance,\n key: {resource},\n}: StoreContext<QueryStoreState, BoundResourceKey>) => {\n const liveMessages$ = observeLiveEvents(instance, {\n resource,\n // Surface CORS errors as store state (handled by the Cors Error\n // component) instead of erroring the stream: a stream error here would\n // reach the outer subscription's errorHandler, set the store-wide\n // `state.error`, and permanently brick every query selector.\n onCorsError: (error) => state.set('setError', {error}),\n }).pipe(share())\n\n return state.observable\n .pipe(\n mergeMap((s) => Object.entries(s.queries)),\n groupBy(([key]) => key),\n mergeMap((group$) => {\n const syncTags$ = group$.pipe(\n map(([, queryState]) => queryState),\n map((i) => i?.syncTags ?? EMPTY_ARRAY),\n distinctUntilChanged(),\n )\n\n return combineLatest([liveMessages$, syncTags$]).pipe(\n filter(([message, syncTags]) => message.tags.some((tag) => syncTags.includes(tag))),\n tap(([message]) => {\n state.set('setLastLiveEventId', setLastLiveEventId(group$.key, message.id))\n }),\n )\n }),\n )\n .subscribe({error: errorHandler(state)})\n}\n\n/**\n * Returns the state source for a query.\n *\n * This function returns a state source that represents the current result of a GROQ query.\n * Subscribing to the state source will instruct the SDK to fetch the query (if not already fetched)\n * and will keep the query live using the Live content API (considering sync tags) to provide up-to-date results.\n * When the last subscriber is removed, the query state is automatically cleaned up from the store.\n *\n * Note: This functionality is for advanced users who want to build their own framework integrations.\n * Our SDK also provides a React integration (useQuery hook) for convenient usage.\n *\n * Note: Automatic cleanup can interfere with React Suspense because if a component suspends while being the only subscriber,\n * cleanup might occur unexpectedly. In such cases, consider using `resolveQuery` instead.\n *\n * @beta\n */\nexport function getQueryState<\n TQuery extends string = string,\n TDataset extends string = string,\n TProjectId extends string = string,\n>(\n instance: SanityInstance,\n queryOptions: QueryOptions<TQuery, TDataset, TProjectId>,\n): StateSource<ResolveQueryResult<TQuery, `${TProjectId}.${TDataset}`> | undefined>\n\n/** @beta */\nexport function getQueryState<TData>(\n instance: SanityInstance,\n queryOptions: QueryOptions,\n): StateSource<TData | undefined>\n\n/** @beta */\nexport function getQueryState(\n instance: SanityInstance,\n queryOptions: QueryOptions,\n): StateSource<unknown>\n\n/** @beta */\nexport function getQueryState(\n ...args: Parameters<typeof _getQueryState>\n): ReturnType<typeof _getQueryState> {\n return _getQueryState(...args)\n}\nconst _getQueryState = bindActionByResource(\n queryStore,\n createStateSourceAction({\n selector: ({state, instance}: SelectorContext<QueryStoreState>, options: QueryOptions) => {\n if (state.error) throw state.error\n const key = getQueryKey(instance, options)\n const queryState = state.queries[key]\n if (queryState?.error) throw queryState.error\n return queryState?.result\n },\n onSubscribe: ({state, instance}, options: QueryOptions) => {\n const subscriptionId = randomId(16)\n const key = getQueryKey(instance, options)\n\n state.set('addSubscriber', addSubscriber(key, subscriptionId))\n\n return () => {\n // this runs on unsubscribe\n setCleanupTimeout(\n () => state.set('removeSubscriber', removeSubscriber(key, subscriptionId)),\n QUERY_STATE_CLEAR_DELAY,\n )\n }\n },\n }),\n)\n\n/**\n * Resolves the result of a query without registering a lasting subscriber.\n *\n * This function fetches the result of a GROQ query and returns a promise that resolves with the query result.\n * It registers a temporary subscriber for the lifetime of the resolution (released shortly after the promise\n * settles), so the query state participates in normal cleanup even when no lasting subscriber ever attaches —\n * e.g. when a suspended component errors before committing. This makes it ideal for use with React Suspense,\n * where the returned promise is thrown to delay rendering until the query result becomes available.\n * Once the promise resolves, it is expected that a real subscriber will be added via `getQueryState` to manage ongoing updates.\n *\n * Additionally, an optional AbortSignal can be provided to cancel the query and immediately clear the associated state\n * if there are no other active subscribers.\n *\n * @beta\n */\nexport function resolveQuery<\n TQuery extends string = string,\n TDataset extends string = string,\n TProjectId extends string = string,\n>(\n instance: SanityInstance,\n queryOptions: ResolveQueryOptions<TQuery, TDataset, TProjectId>,\n): Promise<ResolveQueryResult<TQuery, `${TProjectId}.${TDataset}`>>\n\n/** @beta */\nexport function resolveQuery<TData>(\n instance: SanityInstance,\n queryOptions: ResolveQueryOptions,\n): Promise<TData>\n/** @beta */\nexport function resolveQuery(...args: Parameters<typeof _resolveQuery>): Promise<unknown> {\n return _resolveQuery(...args)\n}\nconst _resolveQuery = bindActionByResource(\n queryStore,\n ({state, instance}, {signal, ...options}: ResolveQueryOptions) => {\n const normalized = normalizeOptionsWithPerspective(instance, options)\n const {getCurrent} = getQueryState(instance, normalized)\n const key = getQueryKey(instance, normalized)\n\n // Hold a temporary subscription for the lifetime of this resolution so the\n // key participates in normal cleanup. Without one, a fetch that errors\n // while a component is suspended leaves a subscriber-less key behind — the\n // component never commits, so no other subscriber exists — and its stored\n // error would be rethrown on every future mount without ever refetching.\n const subscriptionId = randomId(16)\n state.set('addSubscriber', addSubscriber(key, subscriptionId))\n\n const aborted$ = signal\n ? new Observable<void>((observer) => {\n const cleanup = () => {\n signal.removeEventListener('abort', listener)\n }\n\n const listener = () => {\n observer.error(new DOMException('The operation was aborted.', 'AbortError'))\n observer.complete()\n cleanup()\n }\n signal.addEventListener('abort', listener)\n\n return cleanup\n }).pipe(\n catchError((error) => {\n if (error instanceof Error && error.name === 'AbortError') {\n // Release immediately (not after the clear delay) so that when\n // this was the only subscriber, the key removal tears down the\n // in-flight request right away — e.g. when useQuery switches\n // to a different query\n state.set('removeSubscriber', removeSubscriber(key, subscriptionId))\n }\n throw error\n }),\n )\n : NEVER\n\n const resolved$ = state.observable.pipe(\n map(getCurrent),\n first((i) => i !== undefined),\n )\n\n const promise = firstValueFrom(race([resolved$, aborted$]))\n const releaseSubscriber = () => {\n setCleanupTimeout(() => {\n state.set('removeSubscriber', removeSubscriber(key, subscriptionId))\n }, QUERY_STATE_CLEAR_DELAY)\n }\n promise.then(releaseSubscriber, releaseSubscriber)\n return promise\n },\n)\n","","import {version} from '../package.json'\nimport {getEnv} from './utils/getEnv'\n\n/**\n * This version is provided by pkg-utils at build time\n * @internal\n */\nexport const CORE_SDK_VERSION = getEnv('PKG_VERSION') || `${version}-development`\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/sdk",
3
- "version": "3.11.0-next.20261029162752",
3
+ "version": "3.11.0",
4
4
  "private": false,
5
5
  "description": "Sanity SDK",
6
6
  "keywords": [