@sanity/sdk 2.8.0 → 2.9.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.
Files changed (92) hide show
  1. package/dist/_chunks-dts/utils.d.ts +2396 -0
  2. package/dist/_chunks-es/_internal.js +129 -0
  3. package/dist/_chunks-es/_internal.js.map +1 -0
  4. package/dist/_chunks-es/createGroqSearchFilter.js +1460 -0
  5. package/dist/_chunks-es/createGroqSearchFilter.js.map +1 -0
  6. package/dist/_chunks-es/telemetryManager.js +87 -0
  7. package/dist/_chunks-es/telemetryManager.js.map +1 -0
  8. package/dist/_chunks-es/version.js +7 -0
  9. package/dist/_chunks-es/version.js.map +1 -0
  10. package/dist/_exports/_internal.d.ts +64 -0
  11. package/dist/_exports/_internal.js +20 -0
  12. package/dist/_exports/_internal.js.map +1 -0
  13. package/dist/index.d.ts +2 -2343
  14. package/dist/index.js +383 -1777
  15. package/dist/index.js.map +1 -1
  16. package/package.json +11 -4
  17. package/src/_exports/_internal.ts +14 -0
  18. package/src/_exports/index.ts +10 -1
  19. package/src/auth/authStore.test.ts +150 -1
  20. package/src/auth/authStore.ts +11 -11
  21. package/src/auth/dashboardAuth.ts +2 -2
  22. package/src/auth/handleAuthCallback.ts +9 -3
  23. package/src/auth/logout.test.ts +1 -1
  24. package/src/auth/logout.ts +1 -1
  25. package/src/auth/refreshStampedToken.test.ts +118 -1
  26. package/src/auth/refreshStampedToken.ts +3 -2
  27. package/src/auth/standaloneAuth.ts +9 -3
  28. package/src/auth/studioAuth.ts +34 -7
  29. package/src/auth/studioModeAuth.ts +2 -1
  30. package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +10 -2
  31. package/src/auth/subscribeToStateAndFetchCurrentUser.ts +5 -1
  32. package/src/auth/subscribeToStorageEventsAndSetToken.ts +2 -2
  33. package/src/auth/utils.ts +33 -0
  34. package/src/client/clientStore.test.ts +14 -0
  35. package/src/client/clientStore.ts +2 -1
  36. package/src/comlink/node/getNodeState.ts +2 -1
  37. package/src/config/sanityConfig.ts +6 -0
  38. package/src/document/actions.ts +18 -11
  39. package/src/document/applyDocumentActions.test.ts +7 -6
  40. package/src/document/applyDocumentActions.ts +10 -4
  41. package/src/document/documentStore.test.ts +536 -188
  42. package/src/document/documentStore.ts +142 -76
  43. package/src/document/events.ts +7 -2
  44. package/src/document/permissions.test.ts +18 -16
  45. package/src/document/permissions.ts +35 -11
  46. package/src/document/processActions.test.ts +359 -32
  47. package/src/document/processActions.ts +104 -76
  48. package/src/document/reducers.test.ts +117 -29
  49. package/src/document/reducers.ts +43 -36
  50. package/src/document/sharedListener.ts +16 -6
  51. package/src/document/util.ts +14 -0
  52. package/src/favorites/favorites.test.ts +9 -2
  53. package/src/presence/bifurTransport.ts +6 -1
  54. package/src/preview/getPreviewState.test.ts +115 -98
  55. package/src/preview/getPreviewState.ts +38 -60
  56. package/src/preview/previewProjectionUtils.test.ts +179 -0
  57. package/src/preview/previewProjectionUtils.ts +93 -0
  58. package/src/preview/resolvePreview.test.ts +42 -25
  59. package/src/preview/resolvePreview.ts +29 -10
  60. package/src/preview/{previewStore.ts → types.ts} +8 -17
  61. package/src/projection/getProjectionState.test.ts +16 -16
  62. package/src/projection/getProjectionState.ts +2 -1
  63. package/src/projection/projectionQuery.ts +2 -3
  64. package/src/projection/types.ts +1 -1
  65. package/src/query/queryStore.ts +2 -1
  66. package/src/releases/getPerspectiveState.ts +7 -6
  67. package/src/releases/releasesStore.test.ts +20 -5
  68. package/src/releases/releasesStore.ts +20 -8
  69. package/src/store/createStateSourceAction.test.ts +62 -0
  70. package/src/store/createStateSourceAction.ts +34 -39
  71. package/src/telemetry/__telemetry__/sdk.telemetry.ts +42 -0
  72. package/src/telemetry/devMode.test.ts +52 -0
  73. package/src/telemetry/devMode.ts +40 -0
  74. package/src/telemetry/initTelemetry.test.ts +225 -0
  75. package/src/telemetry/initTelemetry.ts +205 -0
  76. package/src/telemetry/telemetryManager.test.ts +263 -0
  77. package/src/telemetry/telemetryManager.ts +187 -0
  78. package/src/users/usersStore.test.ts +1 -0
  79. package/src/users/usersStore.ts +5 -1
  80. package/src/utils/createFetcherStore.test.ts +6 -4
  81. package/src/utils/createFetcherStore.ts +2 -1
  82. package/src/utils/getStagingApiHost.test.ts +21 -0
  83. package/src/utils/getStagingApiHost.ts +14 -0
  84. package/src/utils/ids.test.ts +1 -29
  85. package/src/utils/ids.ts +0 -10
  86. package/src/utils/setCleanupTimeout.ts +24 -0
  87. package/src/preview/previewQuery.test.ts +0 -236
  88. package/src/preview/previewQuery.ts +0 -153
  89. package/src/preview/previewStore.test.ts +0 -36
  90. package/src/preview/subscribeToStateAndFetchBatches.test.ts +0 -221
  91. package/src/preview/subscribeToStateAndFetchBatches.ts +0 -112
  92. package/src/preview/util.ts +0 -13
package/dist/index.js CHANGED
@@ -1,13 +1,12 @@
1
- import { Observable, share, map, distinctUntilChanged, skip, filter, exhaustMap, from, timer, switchMap, takeWhile, firstValueFrom, fromEvent, EMPTY, defer, asapScheduler, combineLatest, of, concatMap, withLatestFrom, concat, throwError, first as first$1, Subject, takeUntil, partition, merge, shareReplay, tap as tap$1, catchError as catchError$1, startWith as startWith$1, pairwise as pairwise$1, groupBy as groupBy$1, mergeMap as mergeMap$1, throttle, race, NEVER, Subscription, debounceTime } from "rxjs";
2
- import { createClient, CorsOriginError } from "@sanity/client";
3
- import { pick, omit, isEqual, isObject } from "lodash-es";
4
- import { devtools } from "zustand/middleware";
5
- import { createStore } from "zustand/vanilla";
6
- import { first, switchMap as switchMap$1, groupBy, mergeMap, startWith, pairwise, filter as filter$1, map as map$1, delay, tap, catchError, scan, share as share$1 } from "rxjs/operators";
1
+ import { switchMap, from, firstValueFrom, EMPTY, asapScheduler, distinctUntilChanged, map as map$1, combineLatest, of, concatMap, withLatestFrom, filter as filter$1, concat, timer, throwError, first as first$1, Subject, takeUntil, share, partition, merge, shareReplay, tap as tap$1, catchError as catchError$1, startWith as startWith$1, pairwise as pairwise$1, groupBy as groupBy$1, mergeMap as mergeMap$1, throttle, race, skip, Observable, NEVER, fromEvent, Subscription, debounceTime, defer } from "rxjs";
2
+ import { createLogger, insecureRandomId, getClientState, bindActionGlobally, defineStore, createStateSourceAction, setCleanupTimeout, authStore, getDefaultLocation, AuthStateType, getCleanedUrl, getTokenFromLocation, createLoggedInAuthState, getAuthCode, REQUEST_TAG_PREFIX, DEFAULT_API_VERSION, configureLogging as configureLogging$1, isReleasePerspective, isDatasetSource, bindActionBySource, isMediaLibrarySource, isCanvasSource, getUsersKey, addSubscription, parseUsersKey, getClient, PROJECT_API_VERSION, setUsersError, setUsersData, API_VERSION as API_VERSION$6, getDashboardOrganizationId as getDashboardOrganizationId$1, USERS_STATE_CLEAR_DELAY, removeSubscription, updateLastLoadMoreRequest, cancelRequest, initializeRequest, bindActionByDataset, getTokenState, getQueryState, resolveQuery, bindActionBySourceAndPerspective, transformProjectionToPreview, PREVIEW_PROJECTION } from "./_chunks-es/createGroqSearchFilter.js";
3
+ import { createGroqSearchFilter, getActiveReleasesState, getAuthState, getClientErrorApiBody, getClientErrorApiDescription, getClientErrorApiType, getCurrentUserState, getIsInDashboardState, getLoginUrlState, getPerspectiveState, getQueryKey, isProjectUserNotFoundClientError, isStudioConfig, parseQueryKey, setAuthToken } from "./_chunks-es/createGroqSearchFilter.js";
4
+ import { pick, omit, isEqual } from "lodash-es";
5
+ import { first, switchMap as switchMap$1, groupBy, mergeMap, startWith, pairwise, filter, map, delay, tap, catchError, scan, share as share$1 } from "rxjs/operators";
7
6
  import { createController, createNode } from "@sanity/comlink";
8
7
  import { createSelector } from "reselect";
9
8
  import { SanityEncoder } from "@sanity/mutate";
10
- import { getPublishedId as getPublishedId$1 } from "@sanity/client/csm";
9
+ import { getVersionId, getPublishedId, DocumentId, getDraftId, isDraftId, isVersionId, isPublishedId } from "@sanity/id-utils";
11
10
  import { jsonMatch, stringifyPath, slicePath, getIndexForKey } from "@sanity/json-match";
12
11
  import { getIndexForKey as getIndexForKey2, getPathDepth, joinPaths, jsonMatch as jsonMatch2, slicePath as slicePath2, stringifyPath as stringifyPath2 } from "@sanity/json-match";
13
12
  import { evaluateSync, parse } from "groq-js";
@@ -17,142 +16,8 @@ import { isKeySegment, isKeyedObject } from "@sanity/types";
17
16
  import { createDocumentLoaderFromClient } from "@sanity/mutate/_unstable_store";
18
17
  import { SDK_CHANNEL_NAME, SDK_NODE_NAME } from "@sanity/message-protocol";
19
18
  import { fromUrl } from "@sanity/bifur-client";
20
- import { DocumentId, getPublishedId as getPublishedId$2, getDraftId as getDraftId$1, getVersionId, isDraftId, isVersionId, isPublishedId } from "@sanity/id-utils";
21
- function isDatasetSource(source) {
22
- return "projectId" in source && "dataset" in source;
23
- }
24
- function isMediaLibrarySource(source) {
25
- return "mediaLibraryId" in source;
26
- }
27
- function isCanvasSource(source) {
28
- return "canvasId" in source;
29
- }
30
- const isReleasePerspective = (perspective) => typeof perspective == "object" && perspective !== null && "releaseName" in perspective;
31
- function getPublishedId(id) {
32
- const draftsPrefix = "drafts.";
33
- return id.startsWith(draftsPrefix) ? id.slice(draftsPrefix.length) : id;
34
- }
35
- function getDraftId(id) {
36
- const draftsPrefix = "drafts.";
37
- return id.startsWith(draftsPrefix) ? id : `${draftsPrefix}${id}`;
38
- }
39
- function insecureRandomId() {
40
- return Array.from({ length: 16 }, () => Math.floor(Math.random() * 16).toString(16)).join("");
41
- }
42
- const LOG_LEVEL_PRIORITY = {
43
- error: 0,
44
- warn: 1,
45
- info: 2,
46
- debug: 3,
47
- trace: 4
48
- }, DEFAULT_CONFIG = {
49
- level: "warn",
50
- namespaces: [],
51
- internal: !1,
52
- timestamps: !0,
53
- enableInProduction: !1,
54
- handler: {
55
- // eslint-disable-next-line no-console
56
- error: console.error.bind(console),
57
- // eslint-disable-next-line no-console
58
- warn: console.warn.bind(console),
59
- // eslint-disable-next-line no-console
60
- info: console.info.bind(console),
61
- // eslint-disable-next-line no-console
62
- debug: console.debug.bind(console),
63
- // eslint-disable-next-line no-console
64
- trace: console.debug.bind(console)
65
- // trace uses console.debug
66
- }
67
- };
68
- function parseDebugEnvVar() {
69
- if (typeof process > "u" || !process.env?.DEBUG)
70
- return null;
71
- const debug = process.env.DEBUG;
72
- if (!debug.includes("sanity"))
73
- return null;
74
- const config = {}, levelMatch = debug.match(/sanity:(trace|debug|info|warn|error):/), hasLevelSpecifier = !!levelMatch;
75
- if (levelMatch ? config.level = levelMatch[1] : config.level = "debug", debug === "sanity")
76
- config.namespaces = ["*"];
77
- else if (hasLevelSpecifier && debug.match(/sanity:(trace|debug|info|warn|error):\*/))
78
- config.namespaces = ["*"];
79
- else if (!hasLevelSpecifier && debug.includes("sanity:*"))
80
- config.namespaces = ["*"];
81
- else {
82
- const namespaces = debug.split(",").filter((s) => s.includes("sanity:")).map((s) => {
83
- const cleaned = s.replace(/^sanity:/, "");
84
- return hasLevelSpecifier && cleaned.match(/^(trace|debug|info|warn|error):/) ? cleaned.split(":").slice(1).join(":") : cleaned.split(":")[0];
85
- }).filter(Boolean).filter((ns) => ns !== "*");
86
- namespaces.length > 0 && (config.namespaces = namespaces);
87
- }
88
- return debug.includes(":internal") && (config.internal = !0), config;
89
- }
90
- const envConfig = parseDebugEnvVar();
91
- let globalConfig = {
92
- ...DEFAULT_CONFIG,
93
- ...envConfig ?? {}
94
- };
95
- envConfig && (["info", "debug", "trace"].includes(globalConfig.level) || globalConfig.level === "warn") && console.info(
96
- `[${(/* @__PURE__ */ new Date()).toISOString()}] [INFO] [sdk] Logging auto-configured from DEBUG environment variable`,
97
- {
98
- level: globalConfig.level,
99
- namespaces: globalConfig.namespaces,
100
- internal: globalConfig.internal,
101
- source: "env:DEBUG",
102
- value: typeof process < "u" ? process.env?.DEBUG : void 0
103
- }
104
- );
105
- function configureLogging$1(config) {
106
- globalConfig = {
107
- ...globalConfig,
108
- ...config,
109
- handler: config.handler ?? globalConfig.handler
110
- };
111
- }
112
- function isLoggingEnabled() {
113
- return typeof process < "u" && process.env?.NODE_ENV === "production" ? globalConfig.enableInProduction : !0;
114
- }
115
- function isNamespaceEnabled(namespace) {
116
- return isLoggingEnabled() ? globalConfig.namespaces.includes("*") ? !0 : globalConfig.namespaces.includes(namespace) : !1;
117
- }
118
- function isLevelEnabled(level) {
119
- return isLoggingEnabled() ? LOG_LEVEL_PRIORITY[level] <= LOG_LEVEL_PRIORITY[globalConfig.level] : !1;
120
- }
121
- function formatMessage(namespace, level, message, context) {
122
- const parts = [];
123
- if (globalConfig.timestamps) {
124
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
125
- parts.push(`[${timestamp}]`);
126
- }
127
- parts.push(`[${level.toUpperCase()}]`), parts.push(`[${namespace}]`);
128
- const instanceContext = context?.instanceContext;
129
- return instanceContext && (instanceContext.projectId && parts.push(`[project:${instanceContext.projectId}]`), instanceContext.dataset && parts.push(`[dataset:${instanceContext.dataset}]`), instanceContext.instanceId && parts.push(`[instance:${instanceContext.instanceId.slice(0, 8)}]`)), parts.push(message), [parts.join(" "), context];
130
- }
131
- function sanitizeContext(context) {
132
- if (!context || Object.keys(context).length === 0) return;
133
- const sanitized = { ...context }, sensitiveKeys = ["token", "password", "secret", "apiKey", "authorization"];
134
- for (const key of Object.keys(sanitized))
135
- sensitiveKeys.some((sensitive) => key.toLowerCase().includes(sensitive)) && (sanitized[key] = "[REDACTED]");
136
- return sanitized;
137
- }
138
- function createLogger(namespace, baseContext) {
139
- const logAtLevel = (level, message, context) => {
140
- if (!isNamespaceEnabled(namespace) || !isLevelEnabled(level) || context?.internal && !globalConfig.internal) return;
141
- const mergedContext = { ...baseContext, ...context }, sanitized = sanitizeContext(mergedContext), [formatted, finalContext] = formatMessage(namespace, level, message, sanitized);
142
- globalConfig.handler[level](formatted, finalContext);
143
- };
144
- return {
145
- namespace,
146
- error: (message, context) => logAtLevel("error", message, context),
147
- warn: (message, context) => logAtLevel("warn", message, context),
148
- info: (message, context) => logAtLevel("info", message, context),
149
- debug: (message, context) => logAtLevel("debug", message, context),
150
- trace: (message, context) => logAtLevel("trace", message, { ...context, internal: !0 }),
151
- isLevelEnabled: (level) => isNamespaceEnabled(namespace) && isLevelEnabled(level),
152
- child: (childContext) => createLogger(namespace, { ...baseContext, ...childContext }),
153
- getInstanceContext: () => baseContext?.instanceContext
154
- };
155
- }
19
+ import { CorsOriginError } from "@sanity/client";
20
+ import { CORE_SDK_VERSION } from "./_chunks-es/version.js";
156
21
  function createSanityInstance(config = {}) {
157
22
  const instanceId = crypto.randomUUID(), disposeListeners = /* @__PURE__ */ new Map(), disposed = { current: !1 }, instanceContext = {
158
23
  instanceId,
@@ -227,870 +92,38 @@ function createSanityInstance(config = {}) {
227
92
  };
228
93
  return instance;
229
94
  }
230
- function getEnv(key) {
231
- if (typeof import.meta < "u" && import.meta.env)
232
- return import.meta.env[key];
233
- if (typeof process < "u" && process.env)
234
- return process.env[key];
235
- if (typeof window < "u" && window.ENV)
236
- return window.ENV?.[key];
237
- }
238
- function createStoreState(initialState, devToolsOptions) {
239
- const store = createStore()(devtools(() => initialState, devToolsOptions));
240
- return {
241
- get: store.getState,
242
- set: (actionKey, updatedState) => {
243
- const currentState = store.getState(), nextState = typeof updatedState == "function" ? updatedState(currentState) : updatedState;
244
- currentState !== nextState && store.setState(nextState, !1, actionKey);
245
- },
246
- observable: new Observable((observer) => {
247
- const emit = () => observer.next(store.getState());
248
- emit();
249
- const unsubscribe = store.subscribe(emit);
250
- return () => unsubscribe();
251
- })
252
- };
253
- }
254
- function createStoreInstance(instance, key, { name, getInitialState: getInitialState2, initialize }) {
255
- const state = createStoreState(getInitialState2(instance, key), {
256
- enabled: !!getEnv("DEV"),
257
- name: `${name}-${key.name}`
258
- }), dispose = initialize?.({ state, instance, key }), disposed = { current: !1 };
259
- return {
260
- state,
261
- dispose: () => {
262
- disposed.current || (disposed.current = !0, dispose?.());
263
- },
264
- isDisposed: () => disposed.current
265
- };
266
- }
267
- function createActionBinder(keyFn) {
268
- const instanceRegistry = /* @__PURE__ */ new Map(), storeRegistry = /* @__PURE__ */ new Map();
269
- return function(storeDefinition, action) {
270
- return function(instance, ...params) {
271
- const key = keyFn(instance, ...params), compositeKey = storeDefinition.name + (key.name ? `:${key.name}` : "");
272
- let instances = instanceRegistry.get(compositeKey);
273
- instances || (instances = /* @__PURE__ */ new Set(), instanceRegistry.set(compositeKey, instances)), instances.has(instance.instanceId) || (instances.add(instance.instanceId), instance.onDispose(() => {
274
- instances.delete(instance.instanceId), instances.size === 0 && (storeRegistry.get(compositeKey)?.dispose(), storeRegistry.delete(compositeKey), instanceRegistry.delete(compositeKey));
275
- }));
276
- let storeInstance = storeRegistry.get(compositeKey);
277
- return storeInstance || (storeInstance = createStoreInstance(instance, key, storeDefinition), storeRegistry.set(compositeKey, storeInstance)), action({ instance, state: storeInstance.state, key }, ...params);
278
- };
279
- };
280
- }
281
- const bindActionByDataset = createActionBinder((instance, options) => {
282
- const projectId = options?.projectId ?? instance.config.projectId, dataset = options?.dataset ?? instance.config.dataset;
283
- if (!projectId || !dataset)
284
- throw new Error("This API requires a project ID and dataset configured.");
285
- return { name: `${projectId}.${dataset}`, projectId, dataset };
286
- }), createSourceKey = (instance, source) => {
287
- let name, sourceForKey;
288
- if (source) {
289
- if (sourceForKey = source, isDatasetSource(source))
290
- name = `${source.projectId}.${source.dataset}`;
291
- else if (isMediaLibrarySource(source))
292
- name = `media-library:${source.mediaLibraryId}`;
293
- else if (isCanvasSource(source))
294
- name = `canvas:${source.canvasId}`;
295
- else
296
- throw new Error(`Received invalid source: ${JSON.stringify(source)}`);
297
- return { name, source: sourceForKey };
298
- }
299
- const { projectId, dataset } = instance.config;
300
- if (!projectId || !dataset)
301
- throw new Error("This API requires a project ID and dataset configured.");
302
- return { name: `${projectId}.${dataset}`, source: { projectId, dataset } };
303
- }, bindActionBySource = createActionBinder((instance, { source }) => createSourceKey(instance, source)), bindActionBySourceAndPerspective = createActionBinder((instance, options) => {
304
- const { source, perspective } = options, utilizedPerspective = perspective ?? instance.config.perspective ?? "drafts";
305
- let perspectiveKey;
306
- isReleasePerspective(utilizedPerspective) ? perspectiveKey = utilizedPerspective.releaseName : typeof utilizedPerspective == "string" ? perspectiveKey = utilizedPerspective : perspectiveKey = JSON.stringify(utilizedPerspective);
307
- const sourceKey = createSourceKey(instance, source);
308
- return {
309
- name: `${sourceKey.name}:${perspectiveKey}`,
310
- source: sourceKey.source,
311
- perspective: utilizedPerspective
312
- };
313
- }), bindActionGlobally = createActionBinder((..._rest) => ({ name: "global" }));
314
- function createStateSourceAction(options) {
315
- const selector = typeof options == "function" ? options : options.selector, subscribeHandler = options && "onSubscribe" in options ? options.onSubscribe : void 0, isEqual2 = options && "isEqual" in options ? options.isEqual ?? Object.is : Object.is, selectorContextCache = /* @__PURE__ */ new WeakMap();
316
- function stateSourceAction(context, ...params) {
317
- const { state, instance } = context, getCurrent = () => {
318
- const currentState = state.get();
319
- if (typeof currentState != "object" || currentState === null)
320
- throw new Error(
321
- `Expected store state to be an object but got "${typeof currentState}" instead`
322
- );
323
- let instanceCache = selectorContextCache.get(currentState);
324
- instanceCache || (instanceCache = /* @__PURE__ */ new WeakMap(), selectorContextCache.set(currentState, instanceCache));
325
- let selectorContext = instanceCache.get(instance);
326
- return selectorContext || (selectorContext = { state: currentState, instance }, instanceCache.set(instance, selectorContext)), selector(selectorContext, ...params);
327
- }, subscribe = (onStoreChanged) => {
328
- const cleanup = subscribeHandler?.(context, ...params), subscription = state.observable.pipe(
329
- // Derive value from current state
330
- map(getCurrent),
331
- // Filter unchanged values using custom equality check
332
- distinctUntilChanged(isEqual2),
333
- // Skip initial emission since we only want changes
334
- skip(1)
335
- ).subscribe({
336
- next: () => onStoreChanged?.(),
337
- // Propagate selector errors to both subscription types
338
- error: () => onStoreChanged?.()
339
- });
340
- return () => {
341
- subscription.unsubscribe(), cleanup?.();
342
- };
343
- }, observable = new Observable((observer) => {
344
- const emitCurrent = () => {
345
- try {
346
- observer.next(getCurrent());
347
- } catch (error) {
348
- observer.error(error);
349
- }
350
- };
351
- return emitCurrent(), subscribe(emitCurrent);
352
- }).pipe(share());
353
- return {
354
- getCurrent,
355
- subscribe,
356
- observable
357
- };
358
- }
359
- return stateSourceAction;
360
- }
361
- const DEFAULT_BASE = "http://localhost", AUTH_CODE_PARAM = "sid", DEFAULT_API_VERSION$1 = "2021-06-07", REQUEST_TAG_PREFIX = "sanity.sdk.auth";
362
- function resolveAuthMode(config, locationHref) {
363
- return isStudioConfig(config) ? "studio" : detectDashboardContext(locationHref) ? "dashboard" : "standalone";
364
- }
365
- function isStudioConfig(config) {
366
- return !!config.studio || !!config.studioMode?.enabled;
367
- }
368
- function detectDashboardContext(locationHref) {
369
- try {
370
- const contextParam = new URL(locationHref, DEFAULT_BASE).searchParams.get("_context");
371
- if (!contextParam) return !1;
372
- const parsed = JSON.parse(contextParam);
373
- return typeof parsed == "object" && parsed !== null && !Array.isArray(parsed) && Object.keys(parsed).length > 0;
374
- } catch (err) {
375
- return console.error("Failed to parse dashboard context from initial location:", err), !1;
376
- }
377
- }
378
- var AuthStateType = /* @__PURE__ */ ((AuthStateType2) => (AuthStateType2.LOGGED_IN = "logged-in", AuthStateType2.LOGGING_IN = "logging-in", AuthStateType2.ERROR = "error", AuthStateType2.LOGGED_OUT = "logged-out", AuthStateType2))(AuthStateType || {});
379
- const REFRESH_INTERVAL = 720 * 60 * 1e3, LOCK_NAME = "sanity-token-refresh-lock";
380
- function getLastRefreshTime(storageArea, storageKey) {
381
- try {
382
- const data = storageArea?.getItem(`${storageKey}_last_refresh`), parsed = data ? parseInt(data, 10) : 0;
383
- return isNaN(parsed) ? 0 : parsed;
384
- } catch {
385
- return 0;
386
- }
387
- }
388
- function setLastRefreshTime(storageArea, storageKey) {
389
- try {
390
- storageArea?.setItem(`${storageKey}_last_refresh`, Date.now().toString());
391
- } catch {
392
- }
393
- }
394
- function getNextRefreshDelay(storageArea, storageKey) {
395
- const lastRefresh = getLastRefreshTime(storageArea, storageKey);
396
- if (!lastRefresh) return 0;
397
- const now = Date.now(), nextRefreshTime = lastRefresh + REFRESH_INTERVAL;
398
- return Math.max(0, nextRefreshTime - now);
399
- }
400
- function createTokenRefreshStream(token, clientFactory, apiHost) {
401
- return new Observable((subscriber) => {
402
- const subscription = clientFactory({
403
- apiVersion: DEFAULT_API_VERSION$1,
404
- requestTagPrefix: "token-refresh",
405
- useProjectHostname: !1,
406
- useCdn: !1,
407
- token,
408
- ignoreBrowserTokenWarning: !0,
409
- ...apiHost && { apiHost }
410
- }).observable.request({
411
- uri: "auth/refresh-token",
412
- method: "POST",
413
- body: {
414
- token
415
- }
416
- }).subscribe(subscriber);
417
- return () => subscription.unsubscribe();
418
- });
419
- }
420
- async function acquireTokenRefreshLock(refreshFn, storageArea, storageKey) {
421
- if (!navigator.locks)
422
- return console.warn("Web Locks API not supported. Proceeding with uncoordinated refresh."), await refreshFn(), setLastRefreshTime(storageArea, storageKey), !0;
423
- try {
424
- return await navigator.locks.request(LOCK_NAME, { mode: "exclusive" }, async (lock) => {
425
- if (!lock) return !1;
426
- for (; ; ) {
427
- const delay2 = getNextRefreshDelay(storageArea, storageKey);
428
- delay2 > 0 && await new Promise((resolve) => setTimeout(resolve, delay2));
429
- try {
430
- await refreshFn(), setLastRefreshTime(storageArea, storageKey);
431
- } catch (error) {
432
- console.error("Token refresh failed within lock:", error);
433
- }
434
- await new Promise((resolve) => setTimeout(resolve, REFRESH_INTERVAL));
435
- }
436
- }) === !0;
437
- } catch (error) {
438
- return console.error("Failed to request token refresh lock:", error), !1;
439
- }
440
- }
441
- function shouldRefreshToken(lastRefresh) {
442
- return lastRefresh ? Date.now() - lastRefresh >= REFRESH_INTERVAL : !0;
443
- }
444
- const refreshStampedToken = ({ state }) => {
445
- const { clientFactory, apiHost, storageArea, storageKey } = state.get().options;
446
- return state.observable.pipe(
447
- map((storeState) => ({
448
- authState: storeState.authState,
449
- dashboardContext: storeState.dashboardContext
450
- })),
451
- filter(
452
- (storeState) => storeState.authState.type === AuthStateType.LOGGED_IN
453
- ),
454
- distinctUntilChanged(
455
- (prev, curr) => prev.authState.type === curr.authState.type && prev.authState.token === curr.authState.token && // Only care about token for distinctness here
456
- prev.dashboardContext === curr.dashboardContext
457
- ),
458
- // Make distinctness check explicit
459
- filter((storeState) => storeState.authState.token.includes("-st")),
460
- // Ensure we only try to refresh stamped tokens
461
- exhaustMap((storeState) => {
462
- const performRefresh = async () => {
463
- const currentState = state.get();
464
- if (currentState.authState.type !== AuthStateType.LOGGED_IN)
465
- throw new Error("User logged out before refresh could complete");
466
- const currentToken = currentState.authState.token, response = await firstValueFrom(
467
- createTokenRefreshStream(currentToken, clientFactory, apiHost)
468
- );
469
- state.set("setRefreshStampedToken", (prev) => ({
470
- authState: prev.authState.type === AuthStateType.LOGGED_IN ? { ...prev.authState, token: response.token } : prev.authState
471
- })), storageArea?.setItem(storageKey, JSON.stringify({ token: response.token }));
472
- };
473
- return storeState.dashboardContext ? new Observable((subscriber) => {
474
- const visibilityHandler = () => {
475
- const currentState = state.get();
476
- document.visibilityState === "visible" && currentState.authState.type === AuthStateType.LOGGED_IN && shouldRefreshToken(currentState.authState.lastTokenRefresh) && createTokenRefreshStream(
477
- currentState.authState.token,
478
- clientFactory,
479
- apiHost
480
- ).subscribe({
481
- next: (response) => {
482
- state.set("setRefreshStampedToken", (prev) => ({
483
- authState: prev.authState.type === AuthStateType.LOGGED_IN ? {
484
- ...prev.authState,
485
- token: response.token,
486
- lastTokenRefresh: Date.now()
487
- } : prev.authState
488
- })), subscriber.next(response);
489
- },
490
- error: (error) => subscriber.error(error)
491
- });
492
- }, timerSubscription = timer(REFRESH_INTERVAL, REFRESH_INTERVAL).pipe(
493
- filter(() => document.visibilityState === "visible"),
494
- switchMap(() => {
495
- const currentState = state.get().authState;
496
- if (currentState.type !== AuthStateType.LOGGED_IN)
497
- throw new Error("User logged out before refresh could complete");
498
- return createTokenRefreshStream(currentState.token, clientFactory, apiHost);
499
- })
500
- ).subscribe({
501
- next: (response) => {
502
- state.set("setRefreshStampedToken", (prev) => ({
503
- authState: prev.authState.type === AuthStateType.LOGGED_IN ? {
504
- ...prev.authState,
505
- token: response.token,
506
- lastTokenRefresh: Date.now()
507
- } : prev.authState
508
- })), subscriber.next(response);
509
- },
510
- error: (error) => subscriber.error(error)
511
- });
512
- return document.addEventListener("visibilitychange", visibilityHandler), () => {
513
- document.removeEventListener("visibilitychange", visibilityHandler), timerSubscription.unsubscribe();
514
- };
515
- }).pipe(
516
- takeWhile(() => state.get().authState.type === AuthStateType.LOGGED_IN),
517
- map((response) => ({ token: response.token }))
518
- ) : from(acquireTokenRefreshLock(performRefresh, storageArea, storageKey)).pipe(
519
- filter((hasLock) => hasLock),
520
- map(() => {
521
- const currentState = state.get().authState;
522
- if (currentState.type !== AuthStateType.LOGGED_IN)
523
- throw new Error("User logged out before refresh could complete");
524
- return { token: currentState.token };
525
- })
526
- );
527
- })
528
- ).subscribe({
529
- next: (response) => {
530
- state.set("setRefreshStampedToken", (prev) => ({
531
- authState: prev.authState.type === AuthStateType.LOGGED_IN ? {
532
- ...prev.authState,
533
- token: response.token,
534
- lastTokenRefresh: Date.now()
535
- } : prev.authState
536
- })), storageArea?.setItem(storageKey, JSON.stringify({ token: response.token }));
537
- },
538
- error: (error) => {
539
- state.set("setRefreshStampedTokenError", { authState: { type: AuthStateType.ERROR, error } });
540
- }
541
- });
542
- }, subscribeToStateAndFetchCurrentUser = ({ state, instance }, fetchOptions) => {
543
- const { clientFactory, apiHost } = state.get().options, useProjectHostname = fetchOptions?.useProjectHostname ?? isStudioConfig(instance.config), projectId = instance.config.projectId;
544
- return state.observable.pipe(
545
- map(({ authState, options: storeOptions }) => ({
546
- authState,
547
- authMethod: storeOptions.authMethod
548
- })),
549
- filter(
550
- (value) => value.authState.type === AuthStateType.LOGGED_IN && !value.authState.currentUser
551
- ),
552
- map((value) => ({ token: value.authState.token, authMethod: value.authMethod })),
553
- distinctUntilChanged(
554
- (prev, curr) => prev.token === curr.token && prev.authMethod === curr.authMethod
555
- )
556
- ).pipe(
557
- map(
558
- ({ token, authMethod }) => clientFactory({
559
- apiVersion: DEFAULT_API_VERSION$1,
560
- requestTagPrefix: REQUEST_TAG_PREFIX,
561
- token: authMethod === "cookie" ? void 0 : token,
562
- ignoreBrowserTokenWarning: !0,
563
- useProjectHostname,
564
- useCdn: !1,
565
- ...authMethod === "cookie" ? { withCredentials: !0 } : {},
566
- ...useProjectHostname && projectId ? { projectId } : {},
567
- ...apiHost && { apiHost }
568
- })
569
- ),
570
- switchMap(
571
- (client) => client.observable.request({ uri: "/users/me", method: "GET" })
572
- )
573
- ).subscribe({
574
- next: (currentUser) => {
575
- state.set("setCurrentUser", (prev) => ({
576
- authState: prev.authState.type === AuthStateType.LOGGED_IN ? { ...prev.authState, currentUser } : prev.authState
577
- }));
578
- },
579
- error: (error) => {
580
- state.set("setError", { authState: { type: AuthStateType.ERROR, error } });
581
- }
582
- });
583
- };
584
- function getAuthCode(callbackUrl, locationHref) {
585
- const loc = new URL(locationHref, DEFAULT_BASE), callbackLocation = callbackUrl ? new URL(callbackUrl, DEFAULT_BASE) : void 0, callbackLocationMatches = callbackLocation ? loc.pathname.toLowerCase().startsWith(callbackLocation.pathname.toLowerCase()) : !0;
586
- let authCode = new URLSearchParams(loc.hash.slice(1)).get(AUTH_CODE_PARAM) || new URLSearchParams(loc.search).get(AUTH_CODE_PARAM);
587
- if (!authCode) {
588
- const contextParam = new URLSearchParams(loc.search).get("_context");
589
- if (contextParam)
590
- try {
591
- const parsedContext = JSON.parse(contextParam);
592
- parsedContext && typeof parsedContext == "object" && typeof parsedContext.sid == "string" && parsedContext.sid && (authCode = parsedContext.sid);
593
- } catch {
594
- }
595
- }
596
- return authCode && callbackLocationMatches ? authCode : null;
597
- }
598
- function getTokenFromLocation(locationHref) {
599
- const loc = new URL(locationHref);
600
- return new URLSearchParams(loc.hash.slice(1)).get("token") || null;
601
- }
602
- function getTokenFromStorage(storageArea, storageKey) {
603
- if (!storageArea) return null;
604
- const item = storageArea.getItem(storageKey);
605
- if (item === null) return null;
606
- try {
607
- const parsed = JSON.parse(item);
608
- if (typeof parsed != "object" || parsed === null || !("token" in parsed) || typeof parsed.token != "string")
609
- throw new Error("Invalid stored auth data structure");
610
- return parsed.token;
611
- } catch {
612
- return storageArea.removeItem(storageKey), null;
613
- }
614
- }
615
- function getStorageEvents() {
616
- return typeof window < "u" && typeof window.addEventListener == "function" ? fromEvent(window, "storage") : EMPTY;
617
- }
618
- function getDefaultStorage() {
619
- try {
620
- return typeof localStorage < "u" && typeof localStorage.getItem == "function" ? localStorage : void 0;
621
- } catch {
622
- return;
623
- }
624
- }
625
- function getDefaultLocation() {
626
- try {
627
- return typeof location > "u" ? DEFAULT_BASE : typeof location.href == "string" ? location.href : DEFAULT_BASE;
628
- } catch {
629
- return DEFAULT_BASE;
630
- }
631
- }
632
- function getCleanedUrl(locationUrl) {
633
- const loc = new URL(locationUrl), rawHash = loc.hash.startsWith("#") ? loc.hash.slice(1) : loc.hash;
634
- if (rawHash && rawHash.includes("=")) {
635
- const hashParams = new URLSearchParams(rawHash);
636
- hashParams.delete("token"), hashParams.delete("withSid");
637
- const nextHash = hashParams.toString();
638
- loc.hash = nextHash ? `#${nextHash}` : "";
639
- }
640
- return loc.searchParams.delete("sid"), loc.searchParams.delete("url"), loc.toString();
641
- }
642
- function getClientErrorApiBody(error) {
643
- const body = error.response?.body;
644
- return body && typeof body == "object" ? body : void 0;
645
- }
646
- function getClientErrorApiType(error) {
647
- const body = getClientErrorApiBody(error);
648
- return body?.error?.type ?? body?.type;
649
- }
650
- function getClientErrorApiDescription(error) {
651
- const body = getClientErrorApiBody(error);
652
- return body?.error?.description ?? body?.description;
653
- }
654
- function isProjectUserNotFoundClientError(error) {
655
- return getClientErrorApiType(error) === "projectUserNotFoundError";
656
- }
657
- function parseDashboardContext(locationHref) {
658
- try {
659
- const contextParam = new URL(locationHref, DEFAULT_BASE).searchParams.get("_context");
660
- if (contextParam) {
661
- const parsedContext = JSON.parse(contextParam);
662
- if (parsedContext && typeof parsedContext == "object" && !Array.isArray(parsedContext) && Object.keys(parsedContext).length > 0)
663
- return delete parsedContext.sid, parsedContext;
664
- }
665
- } catch (err) {
666
- console.error("Failed to parse dashboard context from initial location:", err);
667
- }
668
- return {};
669
- }
670
- function getDashboardInitialState(options) {
671
- const { authConfig, initialLocationHref } = options, providedToken = authConfig.token, callbackUrl = authConfig.callbackUrl, storageKey = "__sanity_auth_token", dashboardContext = parseDashboardContext(initialLocationHref), storageArea = void 0;
672
- return providedToken ? {
673
- authState: { type: AuthStateType.LOGGED_IN, token: providedToken, currentUser: null },
674
- storageKey,
675
- storageArea,
676
- authMethod: void 0,
677
- dashboardContext
678
- } : getAuthCode(callbackUrl, initialLocationHref) || getTokenFromLocation(initialLocationHref) ? {
679
- authState: { type: AuthStateType.LOGGING_IN, isExchangingToken: !1 },
680
- storageKey,
681
- storageArea,
682
- authMethod: void 0,
683
- dashboardContext
684
- } : {
685
- authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 },
686
- storageKey,
687
- storageArea,
688
- authMethod: void 0,
689
- dashboardContext
690
- };
691
- }
692
- function initializeDashboardAuth(context, tokenRefresherRunning2) {
693
- const subscriptions = [];
694
- let startedRefresher = !1;
695
- return subscriptions.push(subscribeToStateAndFetchCurrentUser(context, { useProjectHostname: !1 })), tokenRefresherRunning2 || (startedRefresher = !0, subscriptions.push(refreshStampedToken(context))), {
696
- dispose: () => {
697
- for (const subscription of subscriptions)
698
- subscription.unsubscribe();
699
- },
700
- tokenRefresherStarted: startedRefresher
701
- };
702
- }
703
- const subscribeToStorageEventsAndSetToken = ({
704
- state
705
- }) => {
706
- const { storageArea, storageKey } = state.get().options;
707
- return defer(getStorageEvents).pipe(
708
- filter(
709
- (e) => e.storageArea === storageArea && e.key === storageKey
710
- ),
711
- map(() => getTokenFromStorage(storageArea, storageKey)),
712
- distinctUntilChanged()
713
- ).subscribe((token) => {
714
- state.set("updateTokenFromStorageEvent", {
715
- authState: token ? { type: AuthStateType.LOGGED_IN, token, currentUser: null } : { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }
716
- });
717
- });
718
- };
719
- function getStandaloneInitialState(options) {
720
- const { authConfig, initialLocationHref } = options, providedToken = authConfig.token, callbackUrl = authConfig.callbackUrl, storageKey = "__sanity_auth_token", storageArea = authConfig.storageArea ?? getDefaultStorage();
721
- if (providedToken)
722
- return {
723
- authState: { type: AuthStateType.LOGGED_IN, token: providedToken, currentUser: null },
724
- storageKey,
725
- storageArea,
726
- authMethod: void 0,
727
- dashboardContext: {}
728
- };
729
- if (getAuthCode(callbackUrl, initialLocationHref) || getTokenFromLocation(initialLocationHref))
730
- return {
731
- authState: { type: AuthStateType.LOGGING_IN, isExchangingToken: !1 },
732
- storageKey,
733
- storageArea,
734
- authMethod: void 0,
735
- dashboardContext: {}
736
- };
737
- const token = getTokenFromStorage(storageArea, storageKey);
738
- return token ? {
739
- authState: { type: AuthStateType.LOGGED_IN, token, currentUser: null },
740
- storageKey,
741
- storageArea,
742
- authMethod: "localstorage",
743
- dashboardContext: {}
744
- } : {
745
- authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 },
746
- storageKey,
747
- storageArea,
748
- authMethod: void 0,
749
- dashboardContext: {}
750
- };
751
- }
752
- function initializeStandaloneAuth(context, tokenRefresherRunning2) {
753
- const subscriptions = [];
754
- let startedRefresher = !1;
755
- return subscriptions.push(subscribeToStateAndFetchCurrentUser(context, { useProjectHostname: !1 })), context.state.get().options?.storageArea && subscriptions.push(subscribeToStorageEventsAndSetToken(context)), tokenRefresherRunning2 || (startedRefresher = !0, subscriptions.push(refreshStampedToken(context))), {
756
- dispose: () => {
757
- for (const subscription of subscriptions)
758
- subscription.unsubscribe();
759
- },
760
- tokenRefresherStarted: startedRefresher
761
- };
762
- }
763
- const COOKIE_AUTH_TIMEOUT_MS = 1e4;
764
- async function checkForCookieAuth(projectId, clientFactory) {
765
- if (!projectId) return !1;
766
- try {
767
- const user = await clientFactory({
768
- projectId,
769
- useCdn: !1,
770
- requestTagPrefix: "sdk",
771
- timeout: COOKIE_AUTH_TIMEOUT_MS
772
- }).request({
773
- uri: "/users/me",
774
- withCredentials: !0,
775
- tag: "users.get-current"
776
- });
777
- return user != null && typeof user == "object" && typeof user.id == "string";
778
- } catch {
779
- return !1;
780
- }
781
- }
782
- function getStudioTokenFromLocalStorage(storageArea, storageKey) {
783
- return !storageArea || !storageKey ? null : getTokenFromStorage(storageArea, storageKey) || null;
784
- }
785
- function getStudioInitialState(options) {
786
- const { authConfig, projectId, tokenSource } = options, storageArea = authConfig.storageArea ?? getDefaultStorage(), studioStorageKey = `__studio_auth_token_${projectId ?? ""}`;
787
- if (tokenSource)
788
- return {
789
- authState: { type: AuthStateType.LOGGING_IN, isExchangingToken: !1 },
790
- storageKey: studioStorageKey,
791
- storageArea,
792
- authMethod: void 0,
793
- dashboardContext: {}
794
- };
795
- const providedToken = authConfig.token;
796
- let authMethod;
797
- const token = getStudioTokenFromLocalStorage(storageArea, studioStorageKey);
798
- return token && (authMethod = "localstorage"), providedToken ? {
799
- authState: { type: AuthStateType.LOGGED_IN, token: providedToken, currentUser: null },
800
- storageKey: studioStorageKey,
801
- storageArea,
802
- authMethod,
803
- dashboardContext: {}
804
- } : token ? {
805
- authState: { type: AuthStateType.LOGGED_IN, token, currentUser: null },
806
- storageKey: studioStorageKey,
807
- storageArea,
808
- authMethod: "localstorage",
809
- dashboardContext: {}
810
- } : {
811
- authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 },
812
- storageKey: studioStorageKey,
813
- storageArea,
814
- authMethod: void 0,
815
- dashboardContext: {}
816
- };
817
- }
818
- function initializeStudioAuth(context, tokenRefresherRunning2) {
819
- const tokenSource = context.instance.config.studio?.auth?.token;
820
- return tokenSource ? initializeWithTokenSource(context, tokenSource) : initializeWithFallback(context, tokenRefresherRunning2);
821
- }
822
- function initializeWithTokenSource(context, tokenSource) {
823
- const subscriptions = [];
824
- subscriptions.push(subscribeToStateAndFetchCurrentUser(context, { useProjectHostname: !0 }));
825
- const tokenSub = tokenSource.subscribe({
826
- next: (token) => {
827
- const { state } = context;
828
- token ? state.set("studioTokenSource", (prev) => ({
829
- options: { ...prev.options, authMethod: void 0 },
830
- authState: { type: AuthStateType.LOGGED_IN, token, currentUser: null }
831
- })) : state.set("studioTokenSourceLoggedOut", (prev) => ({
832
- options: { ...prev.options, authMethod: void 0 },
833
- authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }
834
- }));
835
- }
836
- });
837
- return {
838
- dispose: () => {
839
- tokenSub.unsubscribe();
840
- for (const subscription of subscriptions)
841
- subscription.unsubscribe();
842
- },
843
- // Studio handles token refresh — do not start the SDK's refresher
844
- tokenRefresherStarted: !1
845
- };
846
- }
847
- function initializeWithFallback(context, tokenRefresherRunning2) {
848
- const subscriptions = [];
849
- let startedRefresher = !1;
850
- subscriptions.push(subscribeToStateAndFetchCurrentUser(context, { useProjectHostname: !0 })), context.state.get().options?.storageArea && subscriptions.push(subscribeToStorageEventsAndSetToken(context));
851
- try {
852
- const { instance, state } = context;
853
- if (!(state.get().authState?.type === AuthStateType.LOGGED_IN && state.get().authState.token)) {
854
- const projectIdValue = instance.config.projectId, clientFactory = state.get().options.clientFactory;
855
- checkForCookieAuth(projectIdValue, clientFactory).then((isCookieAuthEnabled) => {
856
- isCookieAuthEnabled && state.set("enableCookieAuth", (prev) => ({
857
- options: { ...prev.options, authMethod: "cookie" },
858
- authState: prev.authState.type === AuthStateType.LOGGED_IN ? prev.authState : { type: AuthStateType.LOGGED_IN, token: "", currentUser: null }
859
- }));
860
- });
861
- }
862
- } catch {
863
- }
864
- return tokenRefresherRunning2 || (startedRefresher = !0, subscriptions.push(refreshStampedToken(context))), {
865
- dispose: () => {
866
- for (const subscription of subscriptions)
867
- subscription.unsubscribe();
868
- },
869
- tokenRefresherStarted: startedRefresher
870
- };
871
- }
872
- let tokenRefresherRunning = !1;
873
- const authStore = {
874
- name: "Auth",
875
- getInitialState(instance) {
876
- const {
877
- apiHost,
878
- callbackUrl,
879
- providers: customProviders,
880
- token: providedToken,
881
- clientFactory = createClient,
882
- initialLocationHref = getDefaultLocation()
883
- } = instance.config.auth ?? {}, authConfig = instance.config.auth ?? {};
884
- let loginDomain = "https://www.sanity.io";
885
- try {
886
- apiHost && new URL(apiHost).hostname.endsWith(".sanity.work") && (loginDomain = "https://www.sanity.work");
887
- } catch {
888
- }
889
- const loginUrl = new URL("/login", loginDomain);
890
- loginUrl.searchParams.set("origin", getCleanedUrl(initialLocationHref)), loginUrl.searchParams.set("type", "stampedToken"), loginUrl.searchParams.set("withSid", "true");
891
- const mode = resolveAuthMode(instance.config, initialLocationHref), strategyOptions = {
892
- authConfig,
893
- projectId: instance.config.projectId,
894
- initialLocationHref,
895
- tokenSource: instance.config.studio?.auth?.token
896
- };
897
- let result;
898
- switch (mode) {
899
- case "studio":
900
- result = getStudioInitialState(strategyOptions);
901
- break;
902
- case "dashboard":
903
- result = getDashboardInitialState(strategyOptions);
904
- break;
905
- case "standalone":
906
- result = getStandaloneInitialState(strategyOptions);
907
- break;
908
- }
909
- return {
910
- authState: result.authState,
911
- dashboardContext: result.dashboardContext,
912
- options: {
913
- apiHost,
914
- loginUrl: loginUrl.toString(),
915
- callbackUrl,
916
- customProviders,
917
- providedToken,
918
- clientFactory,
919
- initialLocationHref,
920
- storageKey: result.storageKey,
921
- storageArea: result.storageArea,
922
- authMethod: result.authMethod
923
- }
924
- };
925
- },
926
- initialize(context) {
927
- const initialLocationHref = context.state.get().options?.initialLocationHref ?? getDefaultLocation(), mode = resolveAuthMode(context.instance.config, initialLocationHref);
928
- let initResult;
929
- switch (mode) {
930
- case "studio":
931
- initResult = initializeStudioAuth(context, tokenRefresherRunning);
932
- break;
933
- case "dashboard":
934
- initResult = initializeDashboardAuth(context, tokenRefresherRunning);
935
- break;
936
- case "standalone":
937
- initResult = initializeStandaloneAuth(context, tokenRefresherRunning);
938
- break;
939
- }
940
- return initResult.tokenRefresherStarted && (tokenRefresherRunning = !0), initResult.dispose;
941
- }
942
- }, getCurrentUserState = bindActionGlobally(
943
- authStore,
944
- createStateSourceAction(
945
- ({ state: { authState } }) => authState.type === AuthStateType.LOGGED_IN ? authState.currentUser : null
946
- )
947
- ), getTokenState = bindActionGlobally(
948
- authStore,
949
- createStateSourceAction(
950
- ({ state: { authState } }) => authState.type === AuthStateType.LOGGED_IN ? authState.token : null
951
- )
952
- ), getAuthMethodState = bindActionGlobally(
953
- authStore,
954
- createStateSourceAction(({ state: { options } }) => options.authMethod)
955
- ), getLoginUrlState = bindActionGlobally(
956
- authStore,
957
- createStateSourceAction(({ state: { options } }) => options.loginUrl)
958
- ), getAuthState = bindActionGlobally(
959
- authStore,
960
- createStateSourceAction(({ state: { authState } }) => authState)
961
- ), getDashboardOrganizationId$1 = bindActionGlobally(
962
- authStore,
963
- createStateSourceAction(({ state: { dashboardContext } }) => dashboardContext?.orgId)
964
- ), getIsInDashboardState = bindActionGlobally(
965
- authStore,
966
- createStateSourceAction(
967
- ({ state: { dashboardContext } }) => (
968
- // Check if dashboardContext exists and is not empty
969
- !!dashboardContext && Object.keys(dashboardContext).length > 0
970
- )
971
- )
972
- ), setAuthToken = bindActionGlobally(authStore, ({ state }, token) => {
973
- const currentAuthState = state.get().authState;
974
- token ? (currentAuthState.type !== AuthStateType.LOGGED_IN || currentAuthState.token !== token) && state.set("setToken", {
975
- authState: {
976
- type: AuthStateType.LOGGED_IN,
977
- token,
978
- // Keep existing user or set to null? Setting to null forces refetch.
979
- // Keep existing user to avoid unnecessary refetches if user data is still valid.
980
- currentUser: currentAuthState.type === AuthStateType.LOGGED_IN ? currentAuthState.currentUser : null
981
- }
982
- }) : currentAuthState.type !== AuthStateType.LOGGED_OUT && state.set("setToken", {
983
- authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }
984
- });
985
- }), DEFAULT_API_VERSION = "2024-11-12", DEFAULT_REQUEST_TAG_PREFIX = "sanity.sdk", allowedKeys = Object.keys({
986
- apiHost: null,
987
- useCdn: null,
988
- token: null,
989
- perspective: null,
990
- proxy: null,
991
- withCredentials: null,
992
- timeout: null,
993
- maxRetries: null,
994
- dataset: null,
995
- projectId: null,
996
- scope: null,
997
- apiVersion: null,
998
- requestTagPrefix: null,
999
- useProjectHostname: null,
1000
- "~experimental_resource": null,
1001
- source: null
1002
- }), DEFAULT_CLIENT_CONFIG = {
1003
- apiVersion: DEFAULT_API_VERSION,
1004
- useCdn: !1,
1005
- ignoreBrowserTokenWarning: !0,
1006
- allowReconfigure: !1,
1007
- requestTagPrefix: DEFAULT_REQUEST_TAG_PREFIX
1008
- }, clientStore = {
1009
- name: "clientStore",
1010
- getInitialState: (instance) => ({
1011
- clients: {},
1012
- token: getTokenState(instance).getCurrent()
1013
- }),
1014
- initialize(context) {
1015
- const subscription = listenToToken(context), authMethodSubscription = listenToAuthMethod(context);
1016
- return () => {
1017
- subscription.unsubscribe(), authMethodSubscription.unsubscribe();
1018
- };
1019
- }
1020
- }, listenToToken = ({ instance, state }) => getTokenState(instance).observable.subscribe((token) => {
1021
- state.set("setTokenAndResetClients", { token, clients: {} });
1022
- }), listenToAuthMethod = ({ instance, state }) => getAuthMethodState(instance).observable.subscribe((authMethod) => {
1023
- state.set("setAuthMethod", { authMethod });
1024
- }), getClientConfigKey = (options) => JSON.stringify(pick(options, ...allowedKeys)), getClient = bindActionGlobally(
1025
- clientStore,
1026
- ({ state, instance }, options) => {
1027
- if (!options || typeof options != "object")
1028
- throw new Error(
1029
- 'getClient() requires a configuration object with at least an "apiVersion" property. Example: getClient(instance, { apiVersion: "2024-11-12" })'
1030
- );
1031
- const disallowedKeys = Object.keys(options).filter((key2) => !allowedKeys.includes(key2));
1032
- if (disallowedKeys.length > 0) {
1033
- const listFormatter = new Intl.ListFormat("en", { style: "long", type: "conjunction" });
1034
- throw new Error(
1035
- `The client options provided contains unsupported properties: ${listFormatter.format(disallowedKeys)}. Allowed keys are: ${listFormatter.format(allowedKeys)}.`
1036
- );
1037
- }
1038
- const tokenFromState = state.get().token, { clients, authMethod } = state.get();
1039
- let resource;
1040
- options.source && (isDatasetSource(options.source) ? resource = { type: "dataset", id: `${options.source.projectId}.${options.source.dataset}` } : isMediaLibrarySource(options.source) ? resource = { type: "media-library", id: options.source.mediaLibraryId } : isCanvasSource(options.source) && (resource = { type: "canvas", id: options.source.canvasId }));
1041
- const projectId = options.projectId ?? instance.config.projectId, dataset = options.dataset ?? instance.config.dataset, apiHost = options.apiHost ?? instance.config.auth?.apiHost, effectiveOptions = {
1042
- ...DEFAULT_CLIENT_CONFIG,
1043
- ...(options.scope === "global" || !projectId || resource) && { useProjectHostname: !1 },
1044
- token: authMethod === "cookie" ? void 0 : tokenFromState ?? void 0,
1045
- ...options,
1046
- ...projectId && { projectId },
1047
- ...dataset && { dataset },
1048
- ...apiHost && { apiHost },
1049
- ...resource && { "~experimental_resource": resource }
1050
- };
1051
- resource && ((options.projectId || options.dataset) && console.warn(
1052
- "Both source and explicit projectId/dataset are provided. The source will be used and projectId/dataset will be ignored."
1053
- ), delete effectiveOptions.projectId, delete effectiveOptions.dataset), effectiveOptions.token === null || typeof effectiveOptions.token > "u" ? (delete effectiveOptions.token, authMethod === "cookie" && (effectiveOptions.withCredentials = !0)) : delete effectiveOptions.withCredentials;
1054
- const key = getClientConfigKey(effectiveOptions);
1055
- if (clients[key]) return clients[key];
1056
- const client = createClient(effectiveOptions);
1057
- return state.set("addClient", (prev) => ({ clients: { ...prev.clients, [key]: client } })), client;
1058
- }
1059
- ), getClientState = bindActionGlobally(
1060
- clientStore,
1061
- createStateSourceAction(({ instance }, options) => getClient(instance, options))
1062
- ), API_VERSION$6 = "vX";
95
+ const API_VERSION$5 = "vX";
1063
96
  function agentGenerate(instance, options) {
1064
97
  return getClientState(instance, {
1065
- apiVersion: API_VERSION$6,
98
+ apiVersion: API_VERSION$5,
1066
99
  projectId: instance.config.projectId,
1067
100
  dataset: instance.config.dataset
1068
101
  }).observable.pipe(switchMap((client) => client.observable.agent.action.generate(options)));
1069
102
  }
1070
103
  function agentTransform(instance, options) {
1071
104
  return getClientState(instance, {
1072
- apiVersion: API_VERSION$6,
105
+ apiVersion: API_VERSION$5,
1073
106
  projectId: instance.config.projectId,
1074
107
  dataset: instance.config.dataset
1075
108
  }).observable.pipe(switchMap((client) => client.observable.agent.action.transform(options)));
1076
109
  }
1077
110
  function agentTranslate(instance, options) {
1078
111
  return getClientState(instance, {
1079
- apiVersion: API_VERSION$6,
112
+ apiVersion: API_VERSION$5,
1080
113
  projectId: instance.config.projectId,
1081
114
  dataset: instance.config.dataset
1082
115
  }).observable.pipe(switchMap((client) => client.observable.agent.action.translate(options)));
1083
116
  }
1084
117
  function agentPrompt(instance, options) {
1085
118
  return getClientState(instance, {
1086
- apiVersion: API_VERSION$6,
119
+ apiVersion: API_VERSION$5,
1087
120
  projectId: instance.config.projectId,
1088
121
  dataset: instance.config.dataset
1089
122
  }).observable.pipe(switchMap((client) => from(client.agent.action.prompt(options))));
1090
123
  }
1091
124
  function agentPatch(instance, options) {
1092
125
  return getClientState(instance, {
1093
- apiVersion: API_VERSION$6,
126
+ apiVersion: API_VERSION$5,
1094
127
  projectId: instance.config.projectId,
1095
128
  dataset: instance.config.dataset
1096
129
  }).observable.pipe(switchMap((client) => from(client.agent.action.patch(options))));
@@ -1107,7 +140,7 @@ function createFetcherStore({
1107
140
  fetchThrottleInternal = 1e3,
1108
141
  stateExpirationDelay = 5e3
1109
142
  }) {
1110
- const store = {
143
+ const store = defineStore({
1111
144
  name,
1112
145
  getInitialState: () => ({
1113
146
  stateByParams: {}
@@ -1116,7 +149,7 @@ function createFetcherStore({
1116
149
  const subscription = subscribeToSubscriptionsAndFetch(context);
1117
150
  return () => subscription.unsubscribe();
1118
151
  }
1119
- }, subscribeToSubscriptionsAndFetch = ({
152
+ }), subscribeToSubscriptionsAndFetch = ({
1120
153
  state
1121
154
  }) => state.observable.pipe(
1122
155
  // Map the state to an array of [serialized, entry] pairs.
@@ -1132,13 +165,13 @@ function createFetcherStore({
1132
165
  startWith([group$.key, void 0]),
1133
166
  pairwise(),
1134
167
  // Trigger only when the subscriptions array grows.
1135
- filter$1(([[, prevEntry], [, currEntry]]) => {
168
+ filter(([[, prevEntry], [, currEntry]]) => {
1136
169
  const prevSubs = prevEntry?.subscriptions ?? [];
1137
170
  return (currEntry?.subscriptions ?? []).length > prevSubs.length;
1138
171
  }),
1139
- map$1(([, [, currEntry]]) => currEntry),
172
+ map(([, [, currEntry]]) => currEntry),
1140
173
  // Only trigger if we haven't fetched recently.
1141
- filter$1((entry) => {
174
+ filter((entry) => {
1142
175
  const lastFetch = entry?.lastFetchInitiatedAt;
1143
176
  return lastFetch ? Date.now() - new Date(lastFetch).getTime() >= fetchThrottleInternal : !0;
1144
177
  }),
@@ -1208,7 +241,7 @@ function createFetcherStore({
1208
241
  }
1209
242
  }
1210
243
  })), () => {
1211
- setTimeout(() => {
244
+ setCleanupTimeout(() => {
1212
245
  state.set("removeSubscription", (prev) => {
1213
246
  const entry = prev.stateByParams[key];
1214
247
  if (!entry) return prev;
@@ -1233,7 +266,7 @@ function createFetcherStore({
1233
266
  );
1234
267
  return { getState, resolveState };
1235
268
  }
1236
- const API_VERSION$5 = "v2025-02-19", project = createFetcherStore({
269
+ const API_VERSION$4 = "v2025-02-19", project = createFetcherStore({
1237
270
  name: "Project",
1238
271
  getKey: (instance, options) => {
1239
272
  const projectId = options?.projectId ?? instance.config.projectId;
@@ -1244,7 +277,7 @@ const API_VERSION$5 = "v2025-02-19", project = createFetcherStore({
1244
277
  fetcher: (instance) => (options = {}) => {
1245
278
  const projectId = options.projectId ?? instance.config.projectId;
1246
279
  return getClientState(instance, {
1247
- apiVersion: API_VERSION$5,
280
+ apiVersion: API_VERSION$4,
1248
281
  scope: "global",
1249
282
  projectId
1250
283
  }).observable.pipe(
@@ -1263,7 +296,7 @@ const API_VERSION$5 = "v2025-02-19", project = createFetcherStore({
1263
296
  function observeOrganizationVerificationState(instance, projectIds) {
1264
297
  const dashboardOrgId$ = getDashboardOrganizationId(instance).observable.pipe(distinctUntilChanged()), projectOrgIdObservables = projectIds.map(
1265
298
  (id) => getProjectState(instance, { projectId: id }).observable.pipe(
1266
- map((project2) => ({ projectId: id, orgId: project2?.organizationId ?? null })),
299
+ map$1((project2) => ({ projectId: id, orgId: project2?.organizationId ?? null })),
1267
300
  // Ensure we only proceed if the orgId is loaded, distinct prevents unnecessary checks
1268
301
  distinctUntilChanged((prev, curr) => prev.orgId === curr.orgId)
1269
302
  )
@@ -1299,7 +332,7 @@ const handleAuthCallback = bindActionGlobally(
1299
332
  const cleanedUrl = getCleanedUrl(locationHref), tokenFromUrl = getTokenFromLocation(locationHref);
1300
333
  if (tokenFromUrl)
1301
334
  return state.set("setTokenFromUrl", {
1302
- authState: { type: AuthStateType.LOGGED_IN, token: tokenFromUrl, currentUser: null }
335
+ authState: createLoggedInAuthState(tokenFromUrl, null)
1303
336
  }), cleanedUrl;
1304
337
  const authCode = getAuthCode(callbackUrl, locationHref);
1305
338
  if (!authCode) return !1;
@@ -1320,7 +353,7 @@ const handleAuthCallback = bindActionGlobally(
1320
353
  });
1321
354
  try {
1322
355
  const client = clientFactory({
1323
- apiVersion: DEFAULT_API_VERSION$1,
356
+ apiVersion: DEFAULT_API_VERSION,
1324
357
  requestTagPrefix: REQUEST_TAG_PREFIX,
1325
358
  useProjectHostname: !1,
1326
359
  useCdn: !1,
@@ -1331,7 +364,7 @@ const handleAuthCallback = bindActionGlobally(
1331
364
  query: { sid: authCode },
1332
365
  tag: "fetch-token"
1333
366
  });
1334
- return storageArea?.setItem(storageKey, JSON.stringify({ token })), state.set("setToken", { authState: { type: AuthStateType.LOGGED_IN, token, currentUser: null } }), cleanedUrl;
367
+ return storageArea?.setItem(storageKey, JSON.stringify({ token })), state.set("setToken", { authState: createLoggedInAuthState(token, null) }), cleanedUrl;
1335
368
  } catch (error) {
1336
369
  return state.set("exchangeSessionForTokenError", { authState: { type: AuthStateType.ERROR, error } }), cleanedUrl;
1337
370
  }
@@ -1348,11 +381,11 @@ const handleAuthCallback = bindActionGlobally(
1348
381
  }), await clientFactory({
1349
382
  token,
1350
383
  requestTagPrefix: REQUEST_TAG_PREFIX,
1351
- apiVersion: DEFAULT_API_VERSION$1,
384
+ apiVersion: DEFAULT_API_VERSION,
1352
385
  ...apiHost && { apiHost },
1353
386
  useProjectHostname: !1,
1354
387
  useCdn: !1
1355
- }).request({ uri: "/auth/logout", method: "POST" }));
388
+ }).request({ uri: "/auth/logout", method: "POST", tag: "logout" }));
1356
389
  } finally {
1357
390
  state.set("logoutSuccess", {
1358
391
  authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }
@@ -1408,7 +441,7 @@ const handleAuthCallback = bindActionGlobally(
1408
441
  })
1409
442
  });
1410
443
  }
1411
- }, comlinkControllerStore = {
444
+ }, comlinkControllerStore = defineStore({
1412
445
  name: "connectionStore",
1413
446
  getInitialState: () => ({
1414
447
  controller: null,
@@ -1420,7 +453,7 @@ const handleAuthCallback = bindActionGlobally(
1420
453
  destroyController(instance);
1421
454
  };
1422
455
  }
1423
- }, destroyController = bindActionGlobally(
456
+ }), destroyController = bindActionGlobally(
1424
457
  comlinkControllerStore,
1425
458
  destroyController$1
1426
459
  ), getOrCreateChannel = bindActionGlobally(
@@ -1461,7 +494,7 @@ const handleAuthCallback = bindActionGlobally(
1461
494
  existing.statusUnsub && existing.statusUnsub(), existing.node.stop(), nodes.delete(name), state.set("removeNode", { nodes });
1462
495
  return;
1463
496
  }
1464
- }, comlinkNodeStore = {
497
+ }, comlinkNodeStore = defineStore({
1465
498
  name: "nodeStore",
1466
499
  getInitialState: () => ({
1467
500
  nodes: /* @__PURE__ */ new Map(),
@@ -1474,7 +507,7 @@ const handleAuthCallback = bindActionGlobally(
1474
507
  });
1475
508
  };
1476
509
  }
1477
- }, releaseNode = bindActionGlobally(comlinkNodeStore, releaseNode$1), getOrCreateNode = bindActionGlobally(comlinkNodeStore, getOrCreateNode$1), NODE_RELEASE_TIME = 5e3, selectNode = (context, nodeInput) => context.state.nodes.get(nodeInput.name), getNodeState = bindActionGlobally(
510
+ }), releaseNode = bindActionGlobally(comlinkNodeStore, releaseNode$1), getOrCreateNode = bindActionGlobally(comlinkNodeStore, getOrCreateNode$1), NODE_RELEASE_TIME = 5e3, selectNode = (context, nodeInput) => context.state.nodes.get(nodeInput.name), getNodeState = bindActionGlobally(
1478
511
  comlinkNodeStore,
1479
512
  createStateSourceAction({
1480
513
  selector: createSelector([selectNode], (nodeEntry) => nodeEntry?.status === "connected" ? {
@@ -1486,7 +519,7 @@ const handleAuthCallback = bindActionGlobally(
1486
519
  getOrCreateNode(instance, nodeInput);
1487
520
  let subs = state.get().subscriptions.get(nodeName);
1488
521
  return subs || (subs = /* @__PURE__ */ new Set(), state.get().subscriptions.set(nodeName, subs)), subs.add(subscriberId), () => {
1489
- setTimeout(() => {
522
+ setCleanupTimeout(() => {
1490
523
  const activeSubs = state.get().subscriptions.get(nodeName);
1491
524
  activeSubs && (activeSubs.delete(subscriberId), activeSubs.size === 0 && (state.get().subscriptions.delete(nodeName), releaseNode(instance, nodeName)));
1492
525
  }, NODE_RELEASE_TIME);
@@ -1521,7 +554,7 @@ function configureLogging(config) {
1521
554
  source: "programmatic"
1522
555
  });
1523
556
  }
1524
- const API_VERSION$4 = "v2025-02-19", datasets = createFetcherStore({
557
+ const API_VERSION$3 = "v2025-02-19", datasets = createFetcherStore({
1525
558
  name: "Datasets",
1526
559
  getKey: (instance, options) => {
1527
560
  const projectId = options?.projectId ?? instance.config.projectId;
@@ -1530,27 +563,31 @@ const API_VERSION$4 = "v2025-02-19", datasets = createFetcherStore({
1530
563
  return projectId;
1531
564
  },
1532
565
  fetcher: (instance) => (options) => getClientState(instance, {
1533
- apiVersion: API_VERSION$4,
566
+ apiVersion: API_VERSION$3,
1534
567
  // non-null assertion is fine because we check above
1535
568
  projectId: options?.projectId ?? instance.config.projectId,
1536
569
  useProjectHostname: !0
1537
570
  }).observable.pipe(switchMap((client) => client.observable.datasets.list()))
1538
- }), getDatasetsState = datasets.getState, resolveDatasets = datasets.resolveState, isSanityMutatePatch = (value) => !(typeof value != "object" || !value || !("type" in value) || typeof value.type != "string" || value.type !== "patch" || !("id" in value) || typeof value.id != "string" || !("patches" in value) || !Array.isArray(value.patches));
571
+ }), getDatasetsState = datasets.getState, resolveDatasets = datasets.resolveState;
572
+ function getEffectiveDocumentId(doc) {
573
+ return doc.liveEdit ? doc.documentId : isReleasePerspective(doc.perspective) ? getVersionId(DocumentId(doc.documentId), doc.perspective.releaseName) : getPublishedId(DocumentId(doc.documentId));
574
+ }
575
+ const isSanityMutatePatch = (value) => !(typeof value != "object" || !value || !("type" in value) || typeof value.type != "string" || value.type !== "patch" || !("id" in value) || typeof value.id != "string" || !("patches" in value) || !Array.isArray(value.patches));
1539
576
  function createDocument(doc, initialValue) {
1540
- return {
577
+ let effectiveDocumentId;
578
+ return typeof doc.documentId == "string" && (effectiveDocumentId = getEffectiveDocumentId({ ...doc, documentId: doc.documentId })), {
1541
579
  type: "document.create",
1542
580
  ...doc,
1543
- ...doc.documentId && {
1544
- documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId)
1545
- },
581
+ ...effectiveDocumentId && { documentId: effectiveDocumentId },
1546
582
  ...initialValue && { initialValue }
1547
583
  };
1548
584
  }
1549
585
  function deleteDocument(doc) {
586
+ const effectiveDocumentId = getEffectiveDocumentId(doc);
1550
587
  return {
1551
588
  type: "document.delete",
1552
589
  ...doc,
1553
- documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId)
590
+ documentId: effectiveDocumentId
1554
591
  };
1555
592
  }
1556
593
  function convertSanityMutatePatch(sanityPatchMutation) {
@@ -1560,45 +597,48 @@ function convertSanityMutatePatch(sanityPatchMutation) {
1560
597
  });
1561
598
  }
1562
599
  function editDocument(doc, patches) {
1563
- const documentId = doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId);
600
+ const effectiveDocumentId = getEffectiveDocumentId(doc);
1564
601
  if (isSanityMutatePatch(patches)) {
1565
602
  const converted = convertSanityMutatePatch(patches) ?? [];
1566
603
  return {
1567
604
  ...doc,
1568
605
  type: "document.edit",
1569
- documentId,
606
+ documentId: effectiveDocumentId,
1570
607
  patches: converted
1571
608
  };
1572
609
  }
1573
610
  return {
1574
611
  ...doc,
1575
612
  type: "document.edit",
1576
- documentId,
613
+ documentId: effectiveDocumentId,
1577
614
  ...patches && { patches: Array.isArray(patches) ? patches : [patches] }
1578
615
  };
1579
616
  }
1580
617
  function publishDocument(doc) {
618
+ const effectiveDocumentId = getEffectiveDocumentId(doc);
1581
619
  return {
1582
620
  type: "document.publish",
1583
621
  ...doc,
1584
- documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId)
622
+ documentId: effectiveDocumentId
1585
623
  };
1586
624
  }
1587
625
  function unpublishDocument(doc) {
626
+ const effectiveDocumentId = getEffectiveDocumentId(doc);
1588
627
  return {
1589
628
  type: "document.unpublish",
1590
629
  ...doc,
1591
- documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId)
630
+ documentId: effectiveDocumentId
1592
631
  };
1593
632
  }
1594
633
  function discardDocument(doc) {
634
+ const effectiveDocumentId = getEffectiveDocumentId(doc);
1595
635
  return {
1596
636
  type: "document.discard",
1597
637
  ...doc,
1598
- documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId)
638
+ documentId: effectiveDocumentId
1599
639
  };
1600
640
  }
1601
- const DOCUMENT_STATE_CLEAR_DELAY = 1e3, INITIAL_OUTGOING_THROTTLE_TIME = 1e3, API_VERSION$3 = "v2025-05-06";
641
+ const DOCUMENT_STATE_CLEAR_DELAY = 1e3, INITIAL_OUTGOING_THROTTLE_TIME = 1e3, API_VERSION$2 = "v2025-05-06";
1602
642
  function generateArrayKey(length = 12) {
1603
643
  const numBytes = Math.ceil(length / 2), bytes = crypto.getRandomValues(new Uint8Array(numBytes));
1604
644
  return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, length);
@@ -1826,7 +866,7 @@ function processMutations({
1826
866
  throw new Error(
1827
867
  `Cannot create document with \`_id\` \`${id}\` because another document with the same ID already exists.`
1828
868
  );
1829
- const document2 = {
869
+ const document = {
1830
870
  // > `_createdAt` and `_updatedAt` may be submitted and will override
1831
871
  // > the default which is of course the current time. This can be used
1832
872
  // > to reconstruct a data-set with its timestamp structure intact.
@@ -1839,11 +879,11 @@ function processMutations({
1839
879
  _rev: transactionId,
1840
880
  _id: id
1841
881
  };
1842
- dataset[id] = document2;
882
+ dataset[id] = document;
1843
883
  continue;
1844
884
  }
1845
885
  if ("createOrReplace" in mutation) {
1846
- const id = getId(mutation.createOrReplace._id), prev = dataset[id], document2 = {
886
+ const id = getId(mutation.createOrReplace._id), prev = dataset[id], document = {
1847
887
  ...mutation.createOrReplace,
1848
888
  // otherwise, if the mutation provided, a `_createdAt` time, use it,
1849
889
  // otherwise default to now
@@ -1870,13 +910,13 @@ function processMutations({
1870
910
  _rev: transactionId,
1871
911
  _id: id
1872
912
  };
1873
- dataset[id] = document2;
913
+ dataset[id] = document;
1874
914
  continue;
1875
915
  }
1876
916
  if ("createIfNotExists" in mutation) {
1877
917
  const id = getId(mutation.createIfNotExists._id);
1878
918
  if (dataset[id]) continue;
1879
- const document2 = {
919
+ const document = {
1880
920
  // same logic as `create`:
1881
921
  // prefer the user's `_createdAt` and `_updatedAt`
1882
922
  _createdAt: now,
@@ -1885,7 +925,7 @@ function processMutations({
1885
925
  _rev: transactionId,
1886
926
  _id: id
1887
927
  };
1888
- dataset[id] = document2;
928
+ dataset[id] = document;
1889
929
  continue;
1890
930
  }
1891
931
  if ("delete" in mutation) {
@@ -2002,17 +1042,17 @@ const listen = ({ state }, documentId) => {
2002
1042
  const { sharedListener, fetchDocument } = state.get();
2003
1043
  return sharedListener.events.pipe(
2004
1044
  concatMap((e) => e.type === "welcome" ? fetchDocument(documentId).pipe(
2005
- map((document2) => ({ type: "sync", document: document2 }))
1045
+ map$1((document) => ({ type: "sync", document }))
2006
1046
  ) : e.type === "mutation" && e.documentId === documentId ? of(e) : EMPTY),
2007
1047
  sortListenerEvents(),
2008
1048
  withLatestFrom(
2009
1049
  state.observable.pipe(
2010
- map((s) => s.documentStates[documentId]),
2011
- filter(Boolean),
1050
+ map$1((s) => s.documentStates[documentId]),
1051
+ filter$1(Boolean),
2012
1052
  distinctUntilChanged()
2013
1053
  )
2014
1054
  ),
2015
- map(([next, documentState]) => {
1055
+ map$1(([next, documentState]) => {
2016
1056
  if (next.type === "sync")
2017
1057
  return {
2018
1058
  type: "sync",
@@ -2021,7 +1061,7 @@ const listen = ({ state }, documentId) => {
2021
1061
  revision: next.document?._rev,
2022
1062
  timestamp: next.document?._updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
2023
1063
  };
2024
- const [document2] = Object.values(
1064
+ const [document] = Object.values(
2025
1065
  processMutations({
2026
1066
  documents: { [documentId]: documentState.remote },
2027
1067
  mutations: next.mutations,
@@ -2032,7 +1072,7 @@ const listen = ({ state }, documentId) => {
2032
1072
  return {
2033
1073
  type: "mutation",
2034
1074
  documentId,
2035
- document: document2 ?? null,
1075
+ document: document ?? null,
2036
1076
  revision: transactionId,
2037
1077
  timestamp,
2038
1078
  ...previousRev && { previousRev }
@@ -2128,7 +1168,15 @@ const documentsCache = new MultiKeyWeakMap(), actionsCache = /* @__PURE__ */ new
2128
1168
  ],
2129
1169
  (documentStates, actions) => {
2130
1170
  const documentIds = new Set(
2131
- actions.map((action) => typeof action.documentId != "string" ? [] : action.liveEdit ? [action.documentId] : [getPublishedId(action.documentId), getDraftId(action.documentId)]).flat()
1171
+ actions.map((action) => {
1172
+ if (typeof action.documentId != "string") return [];
1173
+ if (action.liveEdit) return [action.documentId];
1174
+ const ids = [
1175
+ getPublishedId(DocumentId(action.documentId)),
1176
+ getDraftId(DocumentId(action.documentId))
1177
+ ];
1178
+ return isReleasePerspective(action.perspective) && ids.push(getVersionId(DocumentId(action.documentId), action.perspective.releaseName)), ids;
1179
+ }).flat()
2132
1180
  ), documents = {};
2133
1181
  for (const documentId of documentIds) {
2134
1182
  const local = documentStates[documentId]?.local;
@@ -2155,8 +1203,8 @@ const documentsCache = new MultiKeyWeakMap(), actionsCache = /* @__PURE__ */ new
2155
1203
  return nestedCache.get(actionsKey) || (nestedCache.set(actionsKey, normalizedActions), normalizedActions);
2156
1204
  }
2157
1205
  );
2158
- function checkGrant$1(grantExpr, document2) {
2159
- const value = evaluateSync(grantExpr, { params: { document: document2 } });
1206
+ function checkGrant$1(grantExpr, document) {
1207
+ const value = evaluateSync(grantExpr, { params: { document } });
2160
1208
  return value.type === "boolean" && value.data;
2161
1209
  }
2162
1210
  const enNarrowConjunction = new Intl.ListFormat("en", { style: "narrow", type: "conjunction" });
@@ -2199,11 +1247,16 @@ const _calculatePermissions = createSelector(
2199
1247
  }
2200
1248
  for (const action of actions)
2201
1249
  if (action.type === "document.edit" && !action.patches?.length) {
2202
- const docId = action.documentId, doc = action.liveEdit ? documents[docId] : documents[getDraftId(docId)] ?? documents[getPublishedId(docId)];
2203
- doc ? checkGrant$1(grants.update, doc) || reasons.push({
1250
+ const docId = action.documentId;
1251
+ let doc;
1252
+ action.liveEdit ? doc = documents[docId] : isReleasePerspective(action.perspective) ? doc = documents[getVersionId(DocumentId(docId), action.perspective.releaseName)] : doc = documents[getDraftId(DocumentId(docId))] ?? documents[getPublishedId(DocumentId(docId))], doc ? checkGrant$1(grants.update, doc) || reasons.push({
2204
1253
  type: "access",
2205
1254
  message: `You are not allowed to edit the document with ID "${docId}".`,
2206
1255
  documentId: docId
1256
+ }) : isReleasePerspective(action.perspective) ? reasons.push({
1257
+ type: "precondition",
1258
+ message: `The version document with ID "${docId}" could not be found. Please create it or add it to the release first.`,
1259
+ documentId: docId
2207
1260
  }) : reasons.push({
2208
1261
  type: "precondition",
2209
1262
  message: `The document with ID "${docId}" could not be found. Please check that it exists before editing.`,
@@ -2220,8 +1273,8 @@ const _calculatePermissions = createSelector(
2220
1273
  };
2221
1274
  }
2222
1275
  );
2223
- function checkGrant(grantExpr, document2) {
2224
- const value = evaluateSync(grantExpr, { params: { document: document2 } });
1276
+ function checkGrant(grantExpr, document) {
1277
+ const value = evaluateSync(grantExpr, { params: { document } });
2225
1278
  return value.type === "boolean" && value.data;
2226
1279
  }
2227
1280
  class ActionError extends Error {
@@ -2254,7 +1307,11 @@ function processActions({
2254
1307
  transactionId,
2255
1308
  message: "This document already exists."
2256
1309
  });
2257
- const newDocBase2 = { _type: action.documentType, _id: documentId }, newDocWorking2 = { _type: action.documentType, _id: documentId }, mutations2 = [{ create: newDocWorking2 }];
1310
+ const newDocBase2 = { _type: action.documentType, _id: documentId, ...action.initialValue }, mutations2 = [{ create: {
1311
+ _type: action.documentType,
1312
+ _id: documentId,
1313
+ ...action.initialValue
1314
+ } }];
2258
1315
  if (base = processMutations({
2259
1316
  documents: base,
2260
1317
  transactionId,
@@ -2271,29 +1328,27 @@ function processActions({
2271
1328
  transactionId,
2272
1329
  message: `You do not have permission to create document "${documentId}".`
2273
1330
  });
2274
- outgoingMutations.push(...mutations2), outgoingActions.push({
2275
- actionType: "sanity.action.document.create",
2276
- publishedId: documentId,
2277
- attributes: newDocWorking2
2278
- });
1331
+ outgoingMutations.push(...mutations2);
2279
1332
  continue;
2280
1333
  }
2281
- const draftId = getDraftId(documentId), publishedId = getPublishedId(documentId);
2282
- if (working[draftId])
1334
+ const versionId = isReleasePerspective(action.perspective) ? getVersionId(DocumentId(documentId), action.perspective.releaseName) : void 0, draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId));
1335
+ if (versionId ? working[versionId] : working[draftId]) {
1336
+ const errorDocType = versionId ? "release version" : "draft";
2283
1337
  throw new ActionError({
2284
1338
  documentId,
2285
1339
  transactionId,
2286
- message: "A draft version of this document already exists. Please use or discard the existing draft before creating a new one."
1340
+ message: `A ${errorDocType} of this document already exists. Please use or discard the existing ${errorDocType} before creating a new one.`
2287
1341
  });
1342
+ }
2288
1343
  const newDocBase = {
2289
- ...base[publishedId],
1344
+ ...base[draftId] ?? base[publishedId],
2290
1345
  _type: action.documentType,
2291
- _id: draftId,
1346
+ _id: versionId ?? draftId,
2292
1347
  ...action.initialValue
2293
1348
  }, newDocWorking = {
2294
- ...working[publishedId],
1349
+ ...working[draftId] ?? working[publishedId],
2295
1350
  _type: action.documentType,
2296
- _id: draftId,
1351
+ _id: versionId ?? draftId,
2297
1352
  ...action.initialValue
2298
1353
  }, mutations = [{ create: newDocWorking }];
2299
1354
  if (base = processMutations({
@@ -2306,7 +1361,13 @@ function processActions({
2306
1361
  transactionId,
2307
1362
  mutations,
2308
1363
  timestamp
2309
- }), !checkGrant(grants.create, working[draftId]))
1364
+ }), versionId && !checkGrant(grants.create, working[versionId]))
1365
+ throw new PermissionActionError({
1366
+ documentId,
1367
+ transactionId,
1368
+ message: `You do not have permission to create a release version for document "${documentId}".`
1369
+ });
1370
+ if (!versionId && !checkGrant(grants.create, working[draftId]))
2310
1371
  throw new PermissionActionError({
2311
1372
  documentId,
2312
1373
  transactionId,
@@ -2321,6 +1382,12 @@ function processActions({
2321
1382
  }
2322
1383
  case "document.delete": {
2323
1384
  const documentId = action.documentId;
1385
+ if (isReleasePerspective(action.perspective))
1386
+ throw new ActionError({
1387
+ documentId,
1388
+ transactionId,
1389
+ message: 'Cannot delete a version document. You may want to use the "unpublish" or "discard" actions instead.'
1390
+ });
2324
1391
  if (action.liveEdit) {
2325
1392
  if (!working[documentId])
2326
1393
  throw new ActionError({
@@ -2335,13 +1402,10 @@ function processActions({
2335
1402
  message: "You do not have permission to delete this document."
2336
1403
  });
2337
1404
  const mutations2 = [{ delete: { id: documentId } }];
2338
- base = processMutations({ documents: base, transactionId, mutations: mutations2, timestamp }), working = processMutations({ documents: working, transactionId, mutations: mutations2, timestamp }), outgoingMutations.push(...mutations2), outgoingActions.push({
2339
- actionType: "sanity.action.document.delete",
2340
- publishedId: documentId
2341
- });
1405
+ base = processMutations({ documents: base, transactionId, mutations: mutations2, timestamp }), working = processMutations({ documents: working, transactionId, mutations: mutations2, timestamp }), outgoingMutations.push(...mutations2);
2342
1406
  continue;
2343
1407
  }
2344
- const draftId = getDraftId(documentId), publishedId = getPublishedId(documentId);
1408
+ const draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId));
2345
1409
  if (!working[publishedId])
2346
1410
  throw new ActionError({
2347
1411
  documentId,
@@ -2371,14 +1435,14 @@ function processActions({
2371
1435
  transactionId,
2372
1436
  message: `Cannot discard changes for liveEdit document "${documentId}". LiveEdit documents do not support drafts.`
2373
1437
  });
2374
- const draftId = getDraftId(documentId), mutations = [{ delete: { id: draftId } }];
2375
- if (!working[draftId])
1438
+ const versionId = isReleasePerspective(action.perspective) ? getVersionId(DocumentId(documentId), action.perspective.releaseName) : getDraftId(DocumentId(documentId)), mutations = [{ delete: { id: versionId } }];
1439
+ if (!working[versionId])
2376
1440
  throw new ActionError({
2377
1441
  documentId,
2378
1442
  transactionId,
2379
- message: `There is no draft available to discard for document "${documentId}".`
1443
+ message: `There is no draft or version available to discard for document "${documentId}".`
2380
1444
  });
2381
- if (!checkGrant(grants.update, working[draftId]))
1445
+ if (!checkGrant(grants.update, working[versionId]))
2382
1446
  throw new PermissionActionError({
2383
1447
  documentId,
2384
1448
  transactionId,
@@ -2386,7 +1450,7 @@ function processActions({
2386
1450
  });
2387
1451
  base = processMutations({ documents: base, transactionId, mutations, timestamp }), working = processMutations({ documents: working, transactionId, mutations, timestamp }), outgoingMutations.push(...mutations), outgoingActions.push({
2388
1452
  actionType: "sanity.action.document.version.discard",
2389
- versionId: draftId
1453
+ versionId
2390
1454
  });
2391
1455
  continue;
2392
1456
  }
@@ -2421,38 +1485,37 @@ function processActions({
2421
1485
  transactionId,
2422
1486
  mutations: workingMutations2,
2423
1487
  timestamp
2424
- }), outgoingMutations.push(...workingMutations2), outgoingActions.push(
2425
- ...patches2.map(
2426
- (patch) => ({
2427
- actionType: "sanity.action.document.edit",
2428
- // Server requires draftId to have drafts. prefix for validation, even for liveEdit
2429
- draftId: getDraftId(documentId),
2430
- publishedId: documentId,
2431
- patch
2432
- })
2433
- )
2434
- );
1488
+ }), outgoingMutations.push(...workingMutations2);
2435
1489
  continue;
2436
1490
  }
2437
- const draftId = getDraftId(documentId), publishedId = getPublishedId(documentId), userPatches = action.patches?.map((patch) => ({ patch: { id: draftId, ...patch } }));
1491
+ const versionId = isReleasePerspective(action.perspective) ? getVersionId(DocumentId(documentId), action.perspective.releaseName) : void 0, draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId)), patchDocumentId = isReleasePerspective(action.perspective) ? versionId : draftId, userPatches = action.patches?.map((patch) => ({
1492
+ patch: { id: patchDocumentId, ...patch }
1493
+ }));
2438
1494
  if (!userPatches?.length) continue;
2439
- if (!working[draftId] && !working[publishedId] || !base[draftId] && !base[publishedId])
1495
+ if (isReleasePerspective(action.perspective)) {
1496
+ if (!working[versionId] && !base[versionId])
1497
+ throw new ActionError({
1498
+ documentId,
1499
+ transactionId,
1500
+ message: "This document does not exist in the release. Please create it or add it to the release first."
1501
+ });
1502
+ } else if (!working[draftId] && !working[publishedId] || !base[draftId] && !base[publishedId])
2440
1503
  throw new ActionError({
2441
1504
  documentId,
2442
1505
  transactionId,
2443
1506
  message: "Cannot edit document because it does not exist in draft or published form."
2444
1507
  });
2445
1508
  const baseMutations = [];
2446
- !base[draftId] && base[publishedId] && baseMutations.push({ create: { ...base[publishedId], _id: draftId } });
2447
- const baseBefore = base[draftId] ?? base[publishedId];
1509
+ !isReleasePerspective(action.perspective) && !base[draftId] && base[publishedId] && baseMutations.push({ create: { ...base[publishedId], _id: draftId } });
1510
+ const baseBefore = base[patchDocumentId] ?? base[publishedId];
2448
1511
  userPatches && baseMutations.push(...userPatches), base = processMutations({
2449
1512
  documents: base,
2450
1513
  transactionId,
2451
1514
  mutations: baseMutations,
2452
1515
  timestamp
2453
1516
  });
2454
- const baseAfter = base[draftId], patches = diffValue(baseBefore, baseAfter), workingMutations = [];
2455
- if (!working[draftId] && working[publishedId]) {
1517
+ const baseAfter = base[patchDocumentId], patches = diffValue(baseBefore, baseAfter), workingMutations = [];
1518
+ if (!isReleasePerspective(action.perspective) && !working[draftId] && working[publishedId]) {
2456
1519
  const newDraftFromPublished = { ...working[publishedId], _id: draftId };
2457
1520
  if (!checkGrant(grants.create, newDraftFromPublished))
2458
1521
  throw new PermissionActionError({
@@ -2462,39 +1525,37 @@ function processActions({
2462
1525
  });
2463
1526
  workingMutations.push({ create: newDraftFromPublished });
2464
1527
  }
2465
- const workingBefore = working[draftId] ?? working[publishedId];
1528
+ const workingBefore = working[patchDocumentId] ?? working[publishedId];
2466
1529
  if (!checkGrant(grants.update, workingBefore))
2467
1530
  throw new PermissionActionError({
2468
1531
  documentId,
2469
1532
  transactionId,
2470
1533
  message: `You do not have permission to edit document "${documentId}".`
2471
1534
  });
2472
- workingMutations.push(...patches.map((patch) => ({ patch: { id: draftId, ...patch } }))), working = processMutations({
1535
+ workingMutations.push(...patches.map((patch) => ({ patch: { id: patchDocumentId, ...patch } }))), working = processMutations({
2473
1536
  documents: working,
2474
1537
  transactionId,
2475
1538
  mutations: workingMutations,
2476
1539
  timestamp
2477
1540
  }), outgoingMutations.push(...workingMutations), outgoingActions.push(
2478
- ...patches.map(
2479
- (patch) => ({
2480
- actionType: "sanity.action.document.edit",
2481
- draftId,
2482
- publishedId,
2483
- patch
2484
- })
2485
- )
1541
+ ...patches.map((patch) => ({
1542
+ actionType: "sanity.action.document.edit",
1543
+ draftId: patchDocumentId,
1544
+ publishedId,
1545
+ patch
1546
+ }))
2486
1547
  );
2487
1548
  continue;
2488
1549
  }
2489
1550
  case "document.publish": {
2490
1551
  const documentId = getId(action.documentId);
2491
- if (action.liveEdit)
1552
+ if (action.liveEdit || isReleasePerspective(action.perspective))
2492
1553
  throw new ActionError({
2493
1554
  documentId,
2494
1555
  transactionId,
2495
- message: `Cannot publish liveEdit document "${documentId}". LiveEdit documents do not support drafts or publishing.`
1556
+ message: "Cannot publish this document. Publishing is not supported for liveEdit or version (release) documents."
2496
1557
  });
2497
- const draftId = getDraftId(documentId), publishedId = getPublishedId(documentId), workingDraft = working[draftId], baseDraft = base[draftId];
1558
+ const draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId)), workingDraft = working[draftId], baseDraft = base[draftId];
2498
1559
  if (!workingDraft || !baseDraft)
2499
1560
  throw new ActionError({
2500
1561
  documentId,
@@ -2538,13 +1599,13 @@ function processActions({
2538
1599
  }
2539
1600
  case "document.unpublish": {
2540
1601
  const documentId = getId(action.documentId);
2541
- if (action.liveEdit)
1602
+ if (action.liveEdit || isReleasePerspective(action.perspective))
2542
1603
  throw new ActionError({
2543
1604
  documentId,
2544
1605
  transactionId,
2545
- message: `Cannot unpublish liveEdit document "${documentId}". LiveEdit documents do not support drafts or publishing.`
1606
+ message: "Cannot unpublish this document. Unpublishing is not supported for liveEdit or version (release) documents."
2546
1607
  });
2547
- const draftId = getDraftId(documentId), publishedId = getPublishedId(documentId);
1608
+ const draftId = getDraftId(DocumentId(documentId)), publishedId = getPublishedId(DocumentId(documentId));
2548
1609
  if (!working[publishedId] && !base[publishedId])
2549
1610
  throw new ActionError({
2550
1611
  documentId,
@@ -2618,7 +1679,7 @@ const EMPTY_REVISIONS = {};
2618
1679
  function queueTransaction(prev, transaction) {
2619
1680
  const { transactionId, actions } = transaction;
2620
1681
  return {
2621
- ...getDocumentIdsFromActions(actions).reduce(
1682
+ ...getDocumentIdsFromHandleLikes(actions).reduce(
2622
1683
  (acc, id) => addSubscriptionIdToDocument(acc, id, transactionId),
2623
1684
  prev
2624
1685
  ),
@@ -2628,7 +1689,7 @@ function queueTransaction(prev, transaction) {
2628
1689
  function removeQueuedTransaction(prev, transactionId) {
2629
1690
  const transaction = prev.queued.find((t) => t.transactionId === transactionId);
2630
1691
  return transaction ? {
2631
- ...getDocumentIdsFromActions(transaction.actions).reduce(
1692
+ ...getDocumentIdsFromHandleLikes(transaction.actions).reduce(
2632
1693
  (acc, id) => removeSubscriptionIdFromDocument(acc, id, transactionId),
2633
1694
  prev
2634
1695
  ),
@@ -2638,7 +1699,7 @@ function removeQueuedTransaction(prev, transactionId) {
2638
1699
  function applyFirstQueuedTransaction(prev) {
2639
1700
  const queued = prev.queued.at(0);
2640
1701
  if (!queued || !prev.grants) return prev;
2641
- const ids = getDocumentIdsFromActions(queued.actions);
1702
+ const ids = getDocumentIdsFromHandleLikes(queued.actions);
2642
1703
  if (ids.some((id) => prev.documentStates[id]?.local === void 0)) return prev;
2643
1704
  const working = ids.reduce((acc, id) => (acc[id] = prev.documentStates[id]?.local, acc), {}), timestamp = (/* @__PURE__ */ new Date()).toISOString(), result = processActions({
2644
1705
  ...queued,
@@ -2690,7 +1751,7 @@ function batchAppliedTransactions([curr, ...rest]) {
2690
1751
  if (!rest.length) return editAction;
2691
1752
  const next = batchAppliedTransactions(rest);
2692
1753
  if (next)
2693
- return next.disableBatching ? editAction : {
1754
+ return next.disableBatching || !!action.liveEdit != !!next.actions[0]?.liveEdit ? editAction : {
2694
1755
  disableBatching: !1,
2695
1756
  // Use the transactionId from the later (next) transaction.
2696
1757
  transactionId: next.transactionId,
@@ -2748,7 +1809,7 @@ function cleanupOutgoingTransaction(prev) {
2748
1809
  const { outgoing } = prev;
2749
1810
  if (!outgoing) return prev;
2750
1811
  let next = prev;
2751
- const ids = getDocumentIdsFromActions(outgoing.actions);
1812
+ const ids = getDocumentIdsFromHandleLikes(outgoing.actions);
2752
1813
  for (const transactionId of outgoing.batchedTransactionIds)
2753
1814
  for (const documentId of ids)
2754
1815
  next = removeSubscriptionIdFromDocument(next, documentId, transactionId);
@@ -2787,7 +1848,7 @@ function revertOutgoingTransaction(prev) {
2787
1848
  )
2788
1849
  };
2789
1850
  }
2790
- function applyRemoteDocument(prev, { document: document2, documentId, previousRev, revision, timestamp, type }, events) {
1851
+ function applyRemoteDocument(prev, { document, documentId, previousRev, revision, timestamp, type }, events) {
2791
1852
  if (!prev.grants) return prev;
2792
1853
  const prevDocState = prev.documentStates[documentId];
2793
1854
  if (!prevDocState) return prev;
@@ -2802,13 +1863,13 @@ function applyRemoteDocument(prev, { document: document2, documentId, previousRe
2802
1863
  ...prev.documentStates,
2803
1864
  [documentId]: {
2804
1865
  ...prevDocState,
2805
- remote: document2,
1866
+ remote: document,
2806
1867
  remoteRev: revision,
2807
1868
  unverifiedRevisions
2808
1869
  }
2809
1870
  }
2810
1871
  };
2811
- let working = { ...prev.applied.at(0)?.previous, [documentId]: document2 };
1872
+ let working = { ...prev.applied.at(0)?.previous, [documentId]: document };
2812
1873
  const nextApplied = [];
2813
1874
  for (const curr of prev.applied)
2814
1875
  try {
@@ -2834,7 +1895,7 @@ function applyRemoteDocument(prev, { document: document2, documentId, previousRe
2834
1895
  ...prev.documentStates,
2835
1896
  [documentId]: {
2836
1897
  ...prevDocState,
2837
- remote: document2,
1898
+ remote: document,
2838
1899
  remoteRev: revision,
2839
1900
  local: working[documentId],
2840
1901
  unverifiedRevisions
@@ -2866,15 +1927,8 @@ function removeSubscriptionIdFromDocument(prev, documentId, subscriptionId) {
2866
1927
  }
2867
1928
  } : { ...prev, documentStates: omit(prev.documentStates, documentId) } : prev;
2868
1929
  }
2869
- function manageSubscriberIds({ state }, documentId, options) {
2870
- const expandDraftPublished = options?.expandDraftPublished ?? !0, documentIds = Array.from(
2871
- new Set(
2872
- expandDraftPublished ? (Array.isArray(documentId) ? documentId : [documentId]).flatMap((id) => [
2873
- getPublishedId$1(id),
2874
- getDraftId(id)
2875
- ]) : Array.isArray(documentId) ? documentId : [documentId]
2876
- )
2877
- ), subscriptionId = insecureRandomId();
1930
+ function manageSubscriberIds({ state }, handles) {
1931
+ const documentIds = getDocumentIdsFromHandleLikes(handles), subscriptionId = insecureRandomId();
2878
1932
  return state.set(
2879
1933
  "addSubscribers",
2880
1934
  (prev) => documentIds.reduce(
@@ -2882,7 +1936,7 @@ function manageSubscriberIds({ state }, documentId, options) {
2882
1936
  prev
2883
1937
  )
2884
1938
  ), () => {
2885
- setTimeout(() => {
1939
+ setCleanupTimeout(() => {
2886
1940
  state.set(
2887
1941
  "removeSubscribers",
2888
1942
  (prev) => documentIds.reduce(
@@ -2893,12 +1947,13 @@ function manageSubscriberIds({ state }, documentId, options) {
2893
1947
  }, DOCUMENT_STATE_CLEAR_DELAY);
2894
1948
  };
2895
1949
  }
2896
- function getDocumentIdsFromActions(actions) {
2897
- return Array.from(
2898
- new Set(
2899
- actions.map((i) => i.documentId).filter((i) => typeof i == "string").flatMap((documentId) => [getPublishedId$1(documentId), getDraftId(documentId)])
2900
- )
2901
- );
1950
+ function getDocumentIdsFromHandleLikes(handles) {
1951
+ return handles.flatMap((handle) => {
1952
+ const idsForDocument = [];
1953
+ return handle.documentId ? handle.liveEdit ? [handle.documentId] : (isReleasePerspective(handle.perspective) && idsForDocument.push(
1954
+ getVersionId(DocumentId(handle.documentId), handle.perspective.releaseName)
1955
+ ), idsForDocument.push(getPublishedId(DocumentId(handle.documentId))), idsForDocument.push(getDraftId(DocumentId(handle.documentId))), idsForDocument) : [];
1956
+ });
2902
1957
  }
2903
1958
  function getDocumentEvents(outgoing) {
2904
1959
  const documentIdsByAction = Object.entries(
@@ -2923,10 +1978,12 @@ function getDocumentEvents(outgoing) {
2923
1978
  )
2924
1979
  );
2925
1980
  }
2926
- const API_VERSION$2 = "v2025-05-06";
2927
- function createSharedListener(instance) {
1981
+ const API_VERSION$1 = "v2025-05-06";
1982
+ function createSharedListener(instance, source) {
2928
1983
  const dispose$ = new Subject(), events$ = getClientState(instance, {
2929
- apiVersion: API_VERSION$2
1984
+ apiVersion: API_VERSION$1,
1985
+ // TODO: remove in v3 when we're ready for everything to be queried via source
1986
+ source: source && !isDatasetSource(source) ? source : void 0
2930
1987
  }).observable.pipe(
2931
1988
  switchMap(
2932
1989
  (client) => (
@@ -2960,11 +2017,15 @@ function createSharedListener(instance) {
2960
2017
  dispose: () => dispose$.next()
2961
2018
  };
2962
2019
  }
2963
- function createFetchDocument(instance) {
2020
+ function createFetchDocument(instance, source) {
2964
2021
  return function(documentId) {
2965
- return getClientState(instance, { apiVersion: API_VERSION$2 }).observable.pipe(
2022
+ return getClientState(instance, {
2023
+ apiVersion: API_VERSION$1,
2024
+ // TODO: remove in v3 when we're ready for everything to be queried via source
2025
+ source: source && !isDatasetSource(source) ? source : void 0
2026
+ }).observable.pipe(
2966
2027
  switchMap((client) => createDocumentLoaderFromClient(client)(documentId)),
2967
- map((result) => {
2028
+ map$1((result) => {
2968
2029
  if (!result.accessible) {
2969
2030
  if (result.reason === "existence") return null;
2970
2031
  throw new Error(`Document with ID \`${documentId}\` is inaccessible due to permissions.`);
@@ -2975,15 +2036,15 @@ function createFetchDocument(instance) {
2975
2036
  );
2976
2037
  };
2977
2038
  }
2978
- const documentStore = {
2039
+ const documentStore = defineStore({
2979
2040
  name: "Document",
2980
- getInitialState: (instance) => ({
2041
+ getInitialState: (instance, { source }) => ({
2981
2042
  documentStates: {},
2982
2043
  // these can be emptied on refetch
2983
2044
  queued: [],
2984
2045
  applied: [],
2985
- sharedListener: createSharedListener(instance),
2986
- fetchDocument: createFetchDocument(instance),
2046
+ sharedListener: createSharedListener(instance, source),
2047
+ fetchDocument: createFetchDocument(instance, source),
2987
2048
  events: new Subject()
2988
2049
  }),
2989
2050
  initialize(context) {
@@ -2997,83 +2058,92 @@ const documentStore = {
2997
2058
  sharedListener.dispose(), subscriptions.forEach((subscription) => subscription.unsubscribe());
2998
2059
  };
2999
2060
  }
3000
- };
2061
+ });
3001
2062
  function getDocumentState(...args) {
3002
2063
  return _getDocumentState(...args);
3003
2064
  }
3004
- const _getDocumentState = bindActionByDataset(
2065
+ const _getDocumentState = bindActionBySource(
3005
2066
  documentStore,
3006
2067
  createStateSourceAction({
3007
2068
  selector: ({ state: { error, documentStates } }, options) => {
3008
- const { documentId, path, liveEdit } = options;
2069
+ const { documentId: docId, path, liveEdit, perspective } = options, documentId = DocumentId(docId);
3009
2070
  if (error) throw error;
3010
- if (liveEdit) {
3011
- const document22 = documentStates[documentId]?.local;
3012
- if (document22 === void 0) return;
3013
- if (!path) return document22;
3014
- const result2 = jsonMatch(document22, path).next();
3015
- if (result2.done) return;
3016
- const { value: value2 } = result2.value;
3017
- return value2;
2071
+ let document;
2072
+ if (liveEdit)
2073
+ document = documentStates[documentId]?.local;
2074
+ else {
2075
+ let version;
2076
+ if (isReleasePerspective(perspective)) {
2077
+ const versionId = getVersionId(documentId, perspective.releaseName);
2078
+ if (version = documentStates[versionId]?.local, version === void 0) return;
2079
+ }
2080
+ const draft = documentStates[getDraftId(documentId)]?.local, published = documentStates[getPublishedId(documentId)]?.local;
2081
+ if (draft === void 0 || published === void 0) return;
2082
+ document = version ?? draft ?? published;
3018
2083
  }
3019
- const draftId = getDraftId(documentId), publishedId = getPublishedId$1(documentId), draft = documentStates[draftId]?.local, published = documentStates[publishedId]?.local;
3020
- if (draft === void 0 || published === void 0) return;
3021
- const document2 = draft ?? published;
3022
- if (!path) return document2;
3023
- const result = jsonMatch(document2, path).next();
2084
+ if (!path) return document;
2085
+ const result = jsonMatch(document, path).next();
3024
2086
  if (result.done) return;
3025
2087
  const { value } = result.value;
3026
2088
  return value;
3027
2089
  },
3028
- onSubscribe: (context, options) => manageSubscriberIds(context, options.documentId, { expandDraftPublished: !options.liveEdit })
2090
+ onSubscribe: (context, options) => manageSubscriberIds(context, [options])
3029
2091
  })
3030
2092
  );
3031
2093
  function resolveDocument(...args) {
3032
2094
  return _resolveDocument(...args);
3033
2095
  }
3034
- const _resolveDocument = bindActionByDataset(
2096
+ const _resolveDocument = bindActionBySource(
3035
2097
  documentStore,
3036
2098
  ({ instance }, docHandle) => firstValueFrom(
3037
2099
  getDocumentState(instance, {
3038
2100
  ...docHandle,
3039
2101
  path: void 0
3040
- }).observable.pipe(filter((i) => i !== void 0))
2102
+ }).observable.pipe(filter$1((i) => i !== void 0))
3041
2103
  )
3042
- ), getDocumentSyncStatus = bindActionByDataset(
2104
+ ), getDocumentSyncStatus = bindActionBySource(
3043
2105
  documentStore,
3044
2106
  createStateSourceAction({
3045
2107
  selector: ({ state: { error, documentStates: documents, outgoing, applied, queued } }, doc) => {
3046
- const documentId = typeof doc == "string" ? doc : doc.documentId;
2108
+ const documentId = DocumentId(typeof doc == "string" ? doc : doc.documentId);
3047
2109
  if (error) throw error;
3048
- if (doc.liveEdit)
3049
- return documents[documentId] === void 0 ? void 0 : !queued.length && !applied.length && !outgoing;
3050
- const draftId = getDraftId(documentId), publishedId = getPublishedId$1(documentId), draft = documents[draftId], published = documents[publishedId];
3051
- if (!(draft === void 0 || published === void 0))
3052
- return !queued.length && !applied.length && !outgoing;
2110
+ if (doc.liveEdit) {
2111
+ if (documents[documentId] === void 0) return;
2112
+ } else {
2113
+ const version = isReleasePerspective(doc.perspective) ? documents[getVersionId(documentId, doc.perspective.releaseName)] : void 0;
2114
+ if (isReleasePerspective(doc.perspective) && version === void 0) return;
2115
+ const draft = documents[getDraftId(documentId)], published = documents[getPublishedId(documentId)];
2116
+ if (draft === void 0 || published === void 0) return;
2117
+ }
2118
+ return !queued.length && !applied.length && !outgoing;
3053
2119
  },
3054
- onSubscribe: (context, doc) => manageSubscriberIds(context, doc.documentId)
2120
+ onSubscribe: (context, doc) => manageSubscriberIds(context, [doc])
3055
2121
  })
3056
- ), getPermissionsState = bindActionByDataset(
2122
+ ), getPermissionsState = bindActionBySource(
3057
2123
  documentStore,
3058
2124
  createStateSourceAction({
3059
2125
  selector: calculatePermissions,
3060
- onSubscribe: (context, { actions }) => manageSubscriberIds(context, getDocumentIdsFromActions(actions))
2126
+ onSubscribe: (context, { actions }) => {
2127
+ manageSubscriberIds(context, actions);
2128
+ }
3061
2129
  })
3062
- ), resolvePermissions = bindActionByDataset(
2130
+ ), resolvePermissions = bindActionBySource(
3063
2131
  documentStore,
3064
2132
  ({ instance }, options) => firstValueFrom(
3065
- getPermissionsState(instance, options).observable.pipe(filter((i) => i !== void 0))
2133
+ getPermissionsState(instance, options).observable.pipe(filter$1((i) => i !== void 0))
3066
2134
  )
3067
- ), subscribeDocumentEvents = bindActionByDataset(
2135
+ ), subscribeDocumentEvents = bindActionBySource(
3068
2136
  documentStore,
3069
- ({ state }, eventHandler) => {
3070
- const { events } = state.get(), subscription = events.subscribe(eventHandler);
2137
+ ({ state }, options) => {
2138
+ const { events } = state.get(), subscription = events.subscribe(options.eventHandler);
3071
2139
  return () => subscription.unsubscribe();
3072
2140
  }
3073
- ), subscribeToQueuedAndApplyNextTransaction = ({ state }) => {
2141
+ ), subscribeToQueuedAndApplyNextTransaction = ({
2142
+ state
2143
+ }) => {
3074
2144
  const { events } = state.get();
3075
2145
  return state.observable.pipe(
3076
- map(applyFirstQueuedTransaction),
2146
+ map$1(applyFirstQueuedTransaction),
3077
2147
  distinctUntilChanged(),
3078
2148
  tap$1((next) => state.set("applyFirstQueuedTransaction", next)),
3079
2149
  catchError$1((error, caught) => {
@@ -3093,7 +2163,8 @@ const _resolveDocument = bindActionByDataset(
3093
2163
  ).subscribe({ error: (error) => state.set("setError", { error }) });
3094
2164
  }, subscribeToAppliedAndSubmitNextTransaction = ({
3095
2165
  state,
3096
- instance
2166
+ instance,
2167
+ key: { source }
3097
2168
  }) => {
3098
2169
  const { events } = state.get();
3099
2170
  return state.observable.pipe(
@@ -3108,19 +2179,41 @@ const _resolveDocument = bindActionByDataset(
3108
2179
  ),
3109
2180
  { leading: !1, trailing: !0 }
3110
2181
  ),
3111
- map(transitionAppliedTransactionsToOutgoing),
2182
+ map$1(transitionAppliedTransactionsToOutgoing),
3112
2183
  distinctUntilChanged((a, b) => a.outgoing?.transactionId === b.outgoing?.transactionId),
3113
2184
  tap$1((next) => state.set("transitionAppliedTransactionsToOutgoing", next)),
3114
- map((s) => s.outgoing),
2185
+ map$1((s) => s.outgoing),
3115
2186
  distinctUntilChanged(),
3116
- withLatestFrom(getClientState(instance, { apiVersion: API_VERSION$3 }).observable),
3117
- concatMap(([outgoing, client]) => outgoing ? client.observable.action(outgoing.outgoingActions, {
3118
- transactionId: outgoing.transactionId,
3119
- skipCrossDatasetReferenceValidation: !0
3120
- }).pipe(
3121
- catchError$1((error) => (state.set("revertOutgoingTransaction", revertOutgoingTransaction), events.next({ type: "reverted", message: error.message, outgoing, error }), EMPTY)),
3122
- map((result) => ({ result, outgoing }))
3123
- ) : EMPTY),
2187
+ withLatestFrom(
2188
+ getClientState(instance, {
2189
+ apiVersion: API_VERSION$2,
2190
+ // TODO: remove in v3 when we're ready for everything to be queried via source
2191
+ source: source && !isDatasetSource(source) ? source : void 0
2192
+ }).observable
2193
+ ),
2194
+ concatMap(([outgoing, client]) => {
2195
+ if (!outgoing) return EMPTY;
2196
+ const revertOnError = catchError$1((error) => {
2197
+ state.set("revertOutgoingTransaction", revertOutgoingTransaction);
2198
+ const message = error instanceof Error ? error.message : "Request failed";
2199
+ return events.next({ type: "reverted", message, outgoing, error }), EMPTY;
2200
+ }), toResult = map$1((result) => ({
2201
+ result,
2202
+ outgoing
2203
+ }));
2204
+ return outgoing.actions.some((action) => action.liveEdit) ? client.observable.mutate(outgoing.outgoingMutations, {
2205
+ transactionId: outgoing.transactionId,
2206
+ visibility: "async",
2207
+ returnDocuments: !1,
2208
+ returnFirst: !1,
2209
+ tag: "document.mutate",
2210
+ skipCrossDatasetReferenceValidation: !0
2211
+ }).pipe(revertOnError, toResult) : client.observable.action(outgoing.outgoingActions, {
2212
+ transactionId: outgoing.transactionId,
2213
+ skipCrossDatasetReferenceValidation: !0,
2214
+ tag: "document.action"
2215
+ }).pipe(revertOnError, toResult);
2216
+ }),
3124
2217
  tap$1(({ outgoing, result }) => {
3125
2218
  state.set("cleanupOutgoingTransaction", cleanupOutgoingTransaction);
3126
2219
  for (const e of getDocumentEvents(outgoing)) events.next(e);
@@ -3130,8 +2223,8 @@ const _resolveDocument = bindActionByDataset(
3130
2223
  }, subscribeToSubscriptionsAndListenToDocuments = (context) => {
3131
2224
  const { state } = context, { events } = state.get();
3132
2225
  return state.observable.pipe(
3133
- filter((s) => !!s.grants),
3134
- map((s) => Object.keys(s.documentStates)),
2226
+ filter$1((s) => !!s.grants),
2227
+ map$1((s) => Object.keys(s.documentStates)),
3135
2228
  distinctUntilChanged((curr, next) => {
3136
2229
  if (curr.length !== next.length) return !1;
3137
2230
  const currSet = new Set(curr);
@@ -3144,7 +2237,7 @@ const _resolveDocument = bindActionByDataset(
3144
2237
  ...added.map((id) => ({ id, add: !0 })),
3145
2238
  ...removed.map((id) => ({ id, add: !1 }))
3146
2239
  ].sort((a, b) => {
3147
- const aIsDraft = a.id === getDraftId(a.id), bIsDraft = b.id === getDraftId(b.id);
2240
+ const aIsDraft = a.id === getDraftId(DocumentId(a.id)), bIsDraft = b.id === getDraftId(DocumentId(b.id));
3148
2241
  return aIsDraft && bIsDraft ? a.id.localeCompare(b.id, "en-US") : aIsDraft ? -1 : bIsDraft ? 1 : a.id.localeCompare(b.id, "en-US");
3149
2242
  });
3150
2243
  return of(...changes);
@@ -3169,45 +2262,58 @@ const _resolveDocument = bindActionByDataset(
3169
2262
  }, subscribeToClientAndFetchDatasetAcl = ({
3170
2263
  instance,
3171
2264
  state,
3172
- key: { projectId, dataset }
3173
- }) => getClientState(instance, { apiVersion: API_VERSION$3 }).observable.pipe(
3174
- switchMap(
3175
- (client) => client.observable.request({
3176
- uri: `/projects/${projectId}/datasets/${dataset}/acl`,
3177
- tag: "acl.get",
3178
- withCredentials: !0
3179
- })
3180
- ),
3181
- tap$1((datasetAcl) => state.set("setGrants", { grants: createGrantsLookup(datasetAcl) }))
3182
- ).subscribe({
3183
- error: (error) => state.set("setError", { error })
3184
- });
2265
+ key: { source }
2266
+ }) => {
2267
+ const clientOptions = { apiVersion: API_VERSION$2 };
2268
+ source && !isDatasetSource(source) && (clientOptions.source = source);
2269
+ let uri;
2270
+ if (source && isDatasetSource(source))
2271
+ uri = `/projects/${source.projectId}/datasets/${source.dataset}/acl`;
2272
+ else if (source && isMediaLibrarySource(source))
2273
+ uri = `/media-libraries/${source.mediaLibraryId}/acl`;
2274
+ else if (source && isCanvasSource(source))
2275
+ uri = `/canvases/${source.canvasId}/acl`;
2276
+ else
2277
+ throw new Error(`Received invalid source: ${JSON.stringify(source)}`);
2278
+ return getClientState(instance, clientOptions).observable.pipe(
2279
+ switchMap(
2280
+ (client) => client.observable.request({
2281
+ uri,
2282
+ tag: "acl.get",
2283
+ withCredentials: !0
2284
+ })
2285
+ ),
2286
+ tap$1((datasetAcl) => state.set("setGrants", { grants: createGrantsLookup(datasetAcl) }))
2287
+ ).subscribe({
2288
+ error: (error) => state.set("setError", { error })
2289
+ });
2290
+ };
3185
2291
  function applyDocumentActions(...args) {
3186
2292
  return boundApplyDocumentActions(...args);
3187
2293
  }
3188
- const boundApplyDocumentActions = bindActionByDataset(documentStore, _applyDocumentActions);
2294
+ const boundApplyDocumentActions = bindActionBySource(documentStore, _applyDocumentActions);
3189
2295
  async function _applyDocumentActions({ state }, { actions, transactionId = crypto.randomUUID(), disableBatching }) {
3190
2296
  const { events } = state.get(), transaction = {
3191
2297
  transactionId,
3192
2298
  actions,
3193
2299
  ...disableBatching && { disableBatching }
3194
2300
  }, fatalError$ = state.observable.pipe(
3195
- map((s) => s.error),
2301
+ map$1((s) => s.error),
3196
2302
  first$1(Boolean),
3197
- map((error) => ({ type: "error", error }))
2303
+ map$1((error) => ({ type: "error", error }))
3198
2304
  ), transactionError$ = events.pipe(
3199
- filter((e) => e.type === "error"),
2305
+ filter$1((e) => e.type === "error"),
3200
2306
  first$1((e) => e.transactionId === transactionId)
3201
2307
  ), appliedTransaction$ = state.observable.pipe(
3202
- map((s) => s.applied),
2308
+ map$1((s) => s.applied),
3203
2309
  distinctUntilChanged(),
3204
- map((applied) => applied.find((t) => t.transactionId === transactionId)),
2310
+ map$1((applied) => applied.find((t) => t.transactionId === transactionId)),
3205
2311
  first$1(Boolean)
3206
2312
  ), successfulTransaction$ = events.pipe(
3207
- filter((e) => e.type === "accepted"),
2313
+ filter$1((e) => e.type === "accepted"),
3208
2314
  first$1((e) => e.outgoing.batchedTransactionIds.includes(transactionId))
3209
2315
  ), rejectedTransaction$ = events.pipe(
3210
- filter((e) => e.type === "reverted"),
2316
+ filter$1((e) => e.type === "reverted"),
3211
2317
  first$1((e) => e.outgoing.batchedTransactionIds.includes(transactionId))
3212
2318
  ), appliedTransactionOrError = firstValueFrom(
3213
2319
  race([fatalError$, transactionError$, appliedTransaction$])
@@ -3262,7 +2368,7 @@ const favorites = createFetcherStore({
3262
2368
  }
3263
2369
  };
3264
2370
  return nodeStateSource.observable.pipe(
3265
- filter((nodeState) => !!nodeState),
2371
+ filter$1((nodeState) => !!nodeState),
3266
2372
  // Only proceed when connected
3267
2373
  shareReplay(1),
3268
2374
  switchMap((nodeState) => {
@@ -3274,55 +2380,21 @@ const favorites = createFetcherStore({
3274
2380
  payload
3275
2381
  )
3276
2382
  ).pipe(
3277
- map((response) => ({ isFavorited: response.isFavorited })),
2383
+ map$1((response) => ({ isFavorited: response.isFavorited })),
3278
2384
  catchError$1((err) => (console.error("Favorites service connection error", err), of({ isFavorited: !1 })))
3279
2385
  );
3280
2386
  })
3281
2387
  );
3282
2388
  }
3283
- }), getFavoritesState = favorites.getState, resolveFavoritesState = favorites.resolveState, API_VERSION$1 = "vX", PROJECT_API_VERSION = "2025-07-18", USERS_STATE_CLEAR_DELAY = 5e3, DEFAULT_USERS_BATCH_SIZE = 100, getUsersKey = (instance, {
3284
- resourceType,
3285
- organizationId,
3286
- batchSize = DEFAULT_USERS_BATCH_SIZE,
3287
- projectId = instance.config.projectId,
3288
- userId
3289
- } = {}) => JSON.stringify({
3290
- resourceType,
3291
- organizationId,
3292
- batchSize,
3293
- projectId,
3294
- userId
3295
- }), parseUsersKey = (key) => JSON.parse(key), addSubscription = (subscriptionId, key) => (prev) => {
3296
- const group = prev.users[key], subscriptions = [...group?.subscriptions ?? [], subscriptionId];
3297
- return { ...prev, users: { ...prev.users, [key]: { ...group, subscriptions } } };
3298
- }, removeSubscription = (subscriptionId, key) => (prev) => {
3299
- const group = prev.users[key];
3300
- if (!group) return prev;
3301
- const subscriptions = group.subscriptions.filter((id) => id !== subscriptionId);
3302
- return subscriptions.length ? { ...prev, users: { ...prev.users, [key]: { ...group, subscriptions } } } : { ...prev, users: omit(prev.users, key) };
3303
- }, setUsersData = (key, { data, nextCursor, totalCount }) => (prev) => {
3304
- const group = prev.users[key];
3305
- if (!group) return prev;
3306
- const users = [...group.users ?? [], ...data];
3307
- return { ...prev, users: { ...prev.users, [key]: { ...group, users, totalCount, nextCursor } } };
3308
- }, updateLastLoadMoreRequest = (timestamp, key) => (prev) => {
3309
- const group = prev.users[key];
3310
- return group ? { ...prev, users: { ...prev.users, [key]: { ...group, lastLoadMoreRequest: timestamp } } } : prev;
3311
- }, setUsersError = (key, error) => (prev) => {
3312
- const group = prev.users[key];
3313
- return group ? { ...prev, users: { ...prev.users, [key]: { ...group, error } } } : prev;
3314
- }, cancelRequest = (key) => (prev) => {
3315
- const group = prev.users[key];
3316
- return !group || group.subscriptions.length ? prev : { ...prev, users: omit(prev.users, key) };
3317
- }, initializeRequest = (key) => (prev) => prev.users[key] ? prev : { ...prev, users: { ...prev.users, [key]: { subscriptions: [] } } }, usersStore = {
2389
+ }), getFavoritesState = favorites.getState, resolveFavoritesState = favorites.resolveState, usersStore = defineStore({
3318
2390
  name: "UsersStore",
3319
2391
  getInitialState: () => ({ users: {} }),
3320
2392
  initialize: (context) => {
3321
2393
  const subscription = listenForLoadMoreAndFetch(context);
3322
2394
  return () => subscription.unsubscribe();
3323
2395
  }
3324
- }, errorHandler$1 = (state) => (error) => state.set("setError", { error }), listenForLoadMoreAndFetch = ({ state, instance }) => state.observable.pipe(
3325
- map((s) => new Set(Object.keys(s.users))),
2396
+ }), errorHandler = (state) => (error) => state.set("setError", { error }), listenForLoadMoreAndFetch = ({ state, instance }) => state.observable.pipe(
2397
+ map$1((s) => new Set(Object.keys(s.users))),
3326
2398
  distinctUntilChanged((curr, next) => curr.size !== next.size ? !1 : Array.from(next).every((i) => curr.has(i))),
3327
2399
  startWith$1(/* @__PURE__ */ new Set()),
3328
2400
  pairwise$1(),
@@ -3349,9 +2421,10 @@ const favorites = createFetcherStore({
3349
2421
  useProjectHostname: !0
3350
2422
  }).observable.request({
3351
2423
  method: "GET",
3352
- uri: `/users/${userId}`
2424
+ uri: `/users/${userId}`,
2425
+ tag: "users.get"
3353
2426
  }).pipe(
3354
- map((user) => ({
2427
+ map$1((user) => ({
3355
2428
  data: [{
3356
2429
  sanityUserId: user.sanityUserId,
3357
2430
  profile: {
@@ -3379,13 +2452,14 @@ const favorites = createFetcherStore({
3379
2452
  );
3380
2453
  const scope = userId.startsWith("g") ? "global" : void 0, client = getClient(instance, {
3381
2454
  scope,
3382
- apiVersion: API_VERSION$1
2455
+ apiVersion: API_VERSION$6
3383
2456
  }), resourceType2 = options.resourceType || "project", resourceId = resourceType2 === "organization" ? options.organizationId : options.projectId;
3384
2457
  return resourceId ? client.observable.request({
3385
2458
  method: "GET",
3386
- uri: `access/${resourceType2}/${resourceId}/users/${userId}`
2459
+ uri: `access/${resourceType2}/${resourceId}/users/${userId}`,
2460
+ tag: "users.get"
3387
2461
  }).pipe(
3388
- map((response) => "sanityUserId" in response ? {
2462
+ map$1((response) => "sanityUserId" in response ? {
3389
2463
  data: [response],
3390
2464
  totalCount: 1,
3391
2465
  nextCursor: null
@@ -3395,17 +2469,17 @@ const favorites = createFetcherStore({
3395
2469
  ) : throwError(() => new Error("An organizationId or a projectId is required"));
3396
2470
  }
3397
2471
  const projectId = options.projectId, resourceType = options.resourceType ?? (options.organizationId ? "organization" : projectId ? "project" : "organization"), organizationId$ = options.organizationId ? of(options.organizationId) : getDashboardOrganizationId$1(instance).observable.pipe(
3398
- filter((i) => typeof i == "string")
3399
- ), resource$ = resourceType === "project" ? projectId ? of({ type: "project", id: projectId }) : throwError(() => new Error("Project ID required for this API.")) : organizationId$.pipe(map((id) => ({ type: "organization", id }))), client$ = getClientState(instance, {
2472
+ filter$1((i) => typeof i == "string")
2473
+ ), resource$ = resourceType === "project" ? projectId ? of({ type: "project", id: projectId }) : throwError(() => new Error("Project ID required for this API.")) : organizationId$.pipe(map$1((id) => ({ type: "organization", id }))), client$ = getClientState(instance, {
3400
2474
  scope: "global",
3401
- apiVersion: API_VERSION$1
2475
+ apiVersion: API_VERSION$6
3402
2476
  }).observable, loadMore$ = state.observable.pipe(
3403
- map((s) => s.users[group$.key]?.lastLoadMoreRequest),
2477
+ map$1((s) => s.users[group$.key]?.lastLoadMoreRequest),
3404
2478
  distinctUntilChanged()
3405
2479
  ), cursor$ = state.observable.pipe(
3406
- map((s) => s.users[group$.key]?.nextCursor),
2480
+ map$1((s) => s.users[group$.key]?.nextCursor),
3407
2481
  distinctUntilChanged(),
3408
- filter((cursor) => cursor !== null)
2482
+ filter$1((cursor) => cursor !== null)
3409
2483
  );
3410
2484
  return combineLatest([resource$, client$, loadMore$]).pipe(
3411
2485
  withLatestFrom(cursor$),
@@ -3413,6 +2487,7 @@ const favorites = createFetcherStore({
3413
2487
  ([[resource, client], cursor]) => client.observable.request({
3414
2488
  method: "GET",
3415
2489
  uri: `access/${resource.type}/${resource.id}/users`,
2490
+ tag: "users.list",
3416
2491
  query: cursor ? { nextCursor: cursor, limit: batchSize.toString() } : { limit: batchSize.toString() }
3417
2492
  })
3418
2493
  ),
@@ -3422,7 +2497,7 @@ const favorites = createFetcherStore({
3422
2497
  })
3423
2498
  )
3424
2499
  )
3425
- ).subscribe({ error: errorHandler$1(state) }), getUsersState = bindActionGlobally(
2500
+ ).subscribe({ error: errorHandler(state) }), getUsersState = bindActionGlobally(
3426
2501
  usersStore,
3427
2502
  createStateSourceAction({
3428
2503
  selector: createSelector(
@@ -3441,7 +2516,7 @@ const favorites = createFetcherStore({
3441
2516
  onSubscribe: ({ instance, state }, options) => {
3442
2517
  const subscriptionId = insecureRandomId(), key = getUsersKey(instance, options);
3443
2518
  return state.set("addSubscription", addSubscription(subscriptionId, key)), () => {
3444
- setTimeout(
2519
+ setCleanupTimeout(
3445
2520
  () => state.set("removeSubscription", removeSubscription(subscriptionId, key)),
3446
2521
  USERS_STATE_CLEAR_DELAY
3447
2522
  );
@@ -3465,7 +2540,7 @@ const favorites = createFetcherStore({
3465
2540
  ) : NEVER;
3466
2541
  state.set("initializeRequest", initializeRequest(key));
3467
2542
  const resolved$ = state.observable.pipe(
3468
- map(getCurrent),
2543
+ map$1(getCurrent),
3469
2544
  first$1((i) => i !== void 0)
3470
2545
  );
3471
2546
  return firstValueFrom(race([resolved$, aborted$]));
@@ -3480,7 +2555,7 @@ const favorites = createFetcherStore({
3480
2555
  throw new Error("No more users available to load for this resource.");
3481
2556
  const promise = firstValueFrom(
3482
2557
  users.observable.pipe(
3483
- filter((i) => i !== void 0),
2558
+ filter$1((i) => i !== void 0),
3484
2559
  skip(1)
3485
2560
  )
3486
2561
  ), timestamp = (/* @__PURE__ */ new Date()).toISOString();
@@ -3489,7 +2564,7 @@ const favorites = createFetcherStore({
3489
2564
  ), getUserState = bindActionGlobally(
3490
2565
  usersStore,
3491
2566
  ({ instance }, { userId, ...options }) => getUsersState(instance, { userId, ...options }).observable.pipe(
3492
- map((res) => res?.data[0]),
2567
+ map$1((res) => res?.data[0]),
3493
2568
  distinctUntilChanged((a, b) => a?.profile.updatedAt === b?.profile.updatedAt)
3494
2569
  )
3495
2570
  ), resolveUser = bindActionGlobally(
@@ -3500,7 +2575,11 @@ const favorites = createFetcherStore({
3500
2575
  }))?.data[0]
3501
2576
  );
3502
2577
  function getBifurClient(client, token$) {
3503
- const bifurVersionedClient = client.withConfig({ apiVersion: "2022-06-30" }), { dataset, url: baseUrl, requestTagPrefix = "sanity.studio" } = bifurVersionedClient.config(), urlWithTag = `${`${baseUrl.replace(/\/+$/, "")}/socket/${dataset}`.replace(/^http/, "ws")}?tag=${requestTagPrefix}`;
2578
+ const bifurVersionedClient = client.withConfig({ apiVersion: "2022-06-30" }), {
2579
+ dataset,
2580
+ url: baseUrl,
2581
+ requestTagPrefix = "sanity.sdk.presence"
2582
+ } = bifurVersionedClient.config(), urlWithTag = `${`${baseUrl.replace(/\/+$/, "")}/socket/${dataset}`.replace(/^http/, "ws")}?tag=${requestTagPrefix}`;
3504
2583
  return fromUrl(urlWithTag, { token$ });
3505
2584
  }
3506
2585
  const handleIncomingMessage = (event) => {
@@ -3532,7 +2611,7 @@ const handleIncomingMessage = (event) => {
3532
2611
  throw new Error(`Got unknown presence event: ${JSON.stringify(event)}`);
3533
2612
  }
3534
2613
  }, createBifurTransport = (options) => {
3535
- const { client, token$, sessionId } = options, bifur = getBifurClient(client, token$), incomingEvents$ = bifur.listen("presence").pipe(map$1(handleIncomingMessage)), dispatchMessage = (message) => {
2614
+ const { client, token$, sessionId } = options, bifur = getBifurClient(client, token$), incomingEvents$ = bifur.listen("presence").pipe(map(handleIncomingMessage)), dispatchMessage = (message) => {
3536
2615
  switch (message.type) {
3537
2616
  case "rollCall":
3538
2617
  return bifur.request("presence_rollcall", { session: sessionId });
@@ -3550,7 +2629,7 @@ const handleIncomingMessage = (event) => {
3550
2629
  }, getInitialState = () => ({
3551
2630
  locations: /* @__PURE__ */ new Map(),
3552
2631
  users: {}
3553
- }), presenceStore = {
2632
+ }), presenceStore = defineStore({
3554
2633
  name: "presence",
3555
2634
  getInitialState,
3556
2635
  initialize: (context) => {
@@ -3587,7 +2666,7 @@ const handleIncomingMessage = (event) => {
3587
2666
  dispatch({ type: "disconnect" }).subscribe(), subscription.unsubscribe();
3588
2667
  };
3589
2668
  }
3590
- }, selectLocations = (state) => state.locations, selectUsers = (state) => state.users, selectPresence = createSelector(
2669
+ }), selectLocations = (state) => state.locations, selectUsers = (state) => state.users, selectPresence = createSelector(
3591
2670
  selectLocations,
3592
2671
  selectUsers,
3593
2672
  (locations, users) => Array.from(locations.entries()).map(([sessionId, { userId, locations: locs }]) => ({
@@ -3606,7 +2685,7 @@ const handleIncomingMessage = (event) => {
3606
2685
  selector: (context, _) => selectPresence(context.state),
3607
2686
  onSubscribe: (context, _) => {
3608
2687
  const subscription = context.state.observable.pipe(
3609
- map(
2688
+ map$1(
3610
2689
  (state) => Array.from(state.locations.values()).map((l) => l.userId).filter((id) => !!id)
3611
2690
  ),
3612
2691
  distinctUntilChanged((a, b) => a.length === b.length && a.every((v, i) => v === b[i]))
@@ -3619,7 +2698,7 @@ const handleIncomingMessage = (event) => {
3619
2698
  userId,
3620
2699
  resourceType: "project",
3621
2700
  projectId: context.key.projectId
3622
- }).pipe(filter((v) => !!v))
2701
+ }).pipe(filter$1((v) => !!v))
3623
2702
  );
3624
2703
  return combineLatest(userObservables);
3625
2704
  })
@@ -3636,489 +2715,13 @@ const handleIncomingMessage = (event) => {
3636
2715
  }
3637
2716
  })
3638
2717
  );
3639
- function sortReleases(releases = []) {
3640
- return [...releases].sort((a, b) => {
3641
- if (a.metadata.releaseType === "undecided" && b.metadata.releaseType !== "undecided")
3642
- return -1;
3643
- if (a.metadata.releaseType !== "undecided" && b.metadata.releaseType === "undecided")
3644
- return 1;
3645
- if (a.metadata.releaseType === "undecided" && b.metadata.releaseType === "undecided")
3646
- return new Date(b._createdAt).getTime() - new Date(a._createdAt).getTime();
3647
- if (a.metadata.releaseType === "scheduled" && b.metadata.releaseType === "scheduled") {
3648
- const aPublishAt = a.publishAt || a.metadata.intendedPublishAt;
3649
- if (!aPublishAt)
3650
- return 1;
3651
- const bPublishAt = b.publishAt || b.metadata.intendedPublishAt;
3652
- return bPublishAt ? new Date(bPublishAt).getTime() - new Date(aPublishAt).getTime() : -1;
3653
- }
3654
- return a.metadata.releaseType === "asap" && b.metadata.releaseType !== "asap" ? 1 : a.metadata.releaseType !== "asap" && b.metadata.releaseType === "asap" ? -1 : a.metadata.releaseType === "asap" && b.metadata.releaseType === "asap" ? new Date(b._createdAt).getTime() - new Date(a._createdAt).getTime() : 0;
3655
- });
3656
- }
3657
- const ARCHIVED_RELEASE_STATES = ["archived", "published"], STABLE_EMPTY_RELEASES = [], releasesStore = {
3658
- name: "Releases",
3659
- getInitialState: () => ({
3660
- activeReleases: void 0
3661
- }),
3662
- initialize: (context) => {
3663
- const subscription = subscribeToReleases(context);
3664
- return () => subscription.unsubscribe();
3665
- }
3666
- }, getActiveReleasesState = bindActionByDataset(
3667
- releasesStore,
3668
- createStateSourceAction({
3669
- selector: ({ state }, _) => state.activeReleases
3670
- })
3671
- ), RELEASES_QUERY = "releases::all()", subscribeToReleases = ({
3672
- instance,
3673
- state,
3674
- key: { projectId, dataset }
3675
- }) => {
3676
- const { observable: releases$ } = getQueryState(instance, {
3677
- query: RELEASES_QUERY,
3678
- perspective: "raw",
3679
- projectId,
3680
- dataset,
3681
- tag: "releases"
3682
- });
3683
- return releases$.pipe(
3684
- map((releases) => {
3685
- state.set("setActiveReleases", {
3686
- activeReleases: sortReleases(releases ?? STABLE_EMPTY_RELEASES).filter((release) => !ARCHIVED_RELEASE_STATES.includes(release.state)).reverse()
3687
- });
3688
- })
3689
- ).subscribe({ error: (error) => state.set("setError", { error }) });
3690
- }, DEFAULT_PERSPECTIVE = "drafts", optionsCache = /* @__PURE__ */ new Map(), selectInstancePerspective = (context, _) => context.instance.config.perspective, selectActiveReleases = (context) => context.state.activeReleases, selectOptions = (_context, options) => options, memoizedOptionsSelector = createSelector(
3691
- [selectActiveReleases, selectOptions],
3692
- (activeReleases, options) => {
3693
- if (!options || !activeReleases) return options;
3694
- const releaseIds = activeReleases.map((release) => release._id).join(",");
3695
- let nestedCache = optionsCache.get(releaseIds);
3696
- nestedCache || (nestedCache = /* @__PURE__ */ new Map(), optionsCache.set(releaseIds, nestedCache));
3697
- const optionsKey = JSON.stringify(options);
3698
- let cachedOptions = nestedCache.get(optionsKey);
3699
- return cachedOptions || (cachedOptions = options, nestedCache.set(optionsKey, cachedOptions)), cachedOptions;
3700
- }
3701
- ), _getPerspectiveStateSelector = createStateSourceAction({
3702
- selector: createSelector(
3703
- [selectInstancePerspective, selectActiveReleases, memoizedOptionsSelector],
3704
- (instancePerspective, activeReleases, memoizedOptions) => {
3705
- const perspective = memoizedOptions?.perspective ?? instancePerspective ?? DEFAULT_PERSPECTIVE;
3706
- if (!isReleasePerspective(perspective)) return perspective;
3707
- if (!activeReleases || activeReleases.length === 0) return;
3708
- const releaseNames = sortReleases(activeReleases).map((release) => release.name), index = releaseNames.findIndex((name) => name === perspective.releaseName);
3709
- if (index < 0)
3710
- throw new Error(`Release "${perspective.releaseName}" not found in active releases`);
3711
- return ["drafts", ...releaseNames.slice(0, index + 1)].filter((name) => !perspective.excludedPerspectives?.includes(name)).reverse();
3712
- }
3713
- )
3714
- });
3715
- let _boundGetPerspectiveState;
3716
- const getPerspectiveState = (...args) => (_boundGetPerspectiveState || (_boundGetPerspectiveState = bindActionByDataset(
3717
- releasesStore,
3718
- _getPerspectiveStateSelector
3719
- )), _boundGetPerspectiveState(...args)), QUERY_STATE_CLEAR_DELAY = 1e3, QUERY_STORE_API_VERSION = "v2025-05-06", QUERY_STORE_DEFAULT_PERSPECTIVE = "drafts", setQueryError = (key, error) => (prev) => {
3720
- const prevQuery = prev.queries[key];
3721
- return prevQuery ? { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, error } } } : prev;
3722
- }, setQueryData = (key, result, syncTags) => (prev) => {
3723
- const prevQuery = prev.queries[key];
3724
- return prevQuery ? {
3725
- ...prev,
3726
- queries: { ...prev.queries, [key]: { ...prevQuery, result: result ?? null, syncTags } }
3727
- } : prev;
3728
- }, setLastLiveEventId = (key, lastLiveEventId) => (prev) => {
3729
- const prevQuery = prev.queries[key];
3730
- return prevQuery ? { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, lastLiveEventId } } } : prev;
3731
- }, addSubscriber = (key, subscriptionId) => (prev) => {
3732
- const prevQuery = prev.queries[key], subscribers = [...prevQuery?.subscribers ?? [], subscriptionId];
3733
- return { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, subscribers } } };
3734
- }, removeSubscriber = (key, subscriptionId) => (prev) => {
3735
- const prevQuery = prev.queries[key];
3736
- if (!prevQuery) return prev;
3737
- const subscribers = prevQuery.subscribers.filter((id) => id !== subscriptionId);
3738
- return subscribers.length ? { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, subscribers } } } : { ...prev, queries: omit(prev.queries, key) };
3739
- }, cancelQuery = (key) => (prev) => {
3740
- const prevQuery = prev.queries[key];
3741
- return !prevQuery || prevQuery.subscribers.length ? prev : { ...prev, queries: omit(prev.queries, key) };
3742
- }, initializeQuery = (key) => (prev) => prev.queries[key] ? prev : { ...prev, queries: { ...prev.queries, [key]: { subscribers: [] } } }, EMPTY_ARRAY = [], getQueryKey = (options) => JSON.stringify(options), parseQueryKey = (key) => JSON.parse(key);
3743
- function normalizeOptionsWithPerspective(instance, options) {
3744
- if (options.perspective !== void 0) return options;
3745
- const instancePerspective = instance.config.perspective;
3746
- return {
3747
- ...options,
3748
- perspective: instancePerspective !== void 0 ? instancePerspective : QUERY_STORE_DEFAULT_PERSPECTIVE
3749
- };
3750
- }
3751
- const queryStore = {
3752
- name: "QueryStore",
3753
- getInitialState: () => ({ queries: {} }),
3754
- initialize(context) {
3755
- const subscriptions = [
3756
- listenForNewSubscribersAndFetch(context),
3757
- listenToLiveClientAndSetLastLiveEventIds(context)
3758
- ];
3759
- return () => {
3760
- for (const subscription of subscriptions)
3761
- subscription.unsubscribe();
3762
- };
3763
- }
3764
- }, errorHandler = (state) => (error) => state.set("setError", { error }), listenForNewSubscribersAndFetch = ({ state, instance }) => state.observable.pipe(
3765
- map((s) => new Set(Object.keys(s.queries))),
3766
- distinctUntilChanged((curr, next) => curr.size !== next.size ? !1 : Array.from(next).every((i) => curr.has(i))),
3767
- startWith$1(/* @__PURE__ */ new Set()),
3768
- pairwise$1(),
3769
- mergeMap$1(([curr, next]) => {
3770
- const added = Array.from(next).filter((i) => !curr.has(i)), removed = Array.from(curr).filter((i) => !next.has(i));
3771
- return [
3772
- ...added.map((key) => ({ key, added: !0 })),
3773
- ...removed.map((key) => ({ key, added: !1 }))
3774
- ];
3775
- }),
3776
- groupBy$1((i) => i.key),
3777
- mergeMap$1(
3778
- (group$) => group$.pipe(
3779
- switchMap((e) => {
3780
- if (!e.added) return EMPTY;
3781
- const lastLiveEventId$ = state.observable.pipe(
3782
- map((s) => s.queries[group$.key]?.lastLiveEventId),
3783
- distinctUntilChanged()
3784
- ), {
3785
- query,
3786
- params,
3787
- projectId,
3788
- dataset,
3789
- tag,
3790
- source,
3791
- perspective: perspectiveFromOptions,
3792
- ...restOptions
3793
- } = parseQueryKey(group$.key), perspective$ = isReleasePerspective(perspectiveFromOptions) ? getPerspectiveState(instance, {
3794
- perspective: perspectiveFromOptions
3795
- }).observable.pipe(filter(Boolean)) : of(perspectiveFromOptions ?? QUERY_STORE_DEFAULT_PERSPECTIVE), client$ = getClientState(instance, {
3796
- apiVersion: QUERY_STORE_API_VERSION,
3797
- projectId,
3798
- dataset,
3799
- source
3800
- }).observable;
3801
- return combineLatest({
3802
- lastLiveEventId: lastLiveEventId$,
3803
- client: client$,
3804
- perspective: perspective$
3805
- }).pipe(
3806
- switchMap(
3807
- ({ lastLiveEventId, client, perspective }) => client.observable.fetch(query, params, {
3808
- ...restOptions,
3809
- perspective,
3810
- filterResponse: !1,
3811
- returnQuery: !1,
3812
- lastLiveEventId,
3813
- tag
3814
- })
3815
- )
3816
- );
3817
- }),
3818
- catchError$1((error) => (state.set("setQueryError", setQueryError(group$.key, error)), EMPTY)),
3819
- tap$1(({ result, syncTags }) => {
3820
- state.set("setQueryData", setQueryData(group$.key, result, syncTags));
3821
- })
3822
- )
3823
- )
3824
- ).subscribe({ error: errorHandler(state) }), listenToLiveClientAndSetLastLiveEventIds = ({
3825
- state,
3826
- instance,
3827
- key: { source }
3828
- }) => {
3829
- const liveMessages$ = getClientState(instance, {
3830
- apiVersion: QUERY_STORE_API_VERSION,
3831
- // temporary guard here until we're ready for everything to be queried via global api
3832
- ...source && !isDatasetSource(source) ? { source } : {}
3833
- }).observable.pipe(
3834
- switchMap(
3835
- (client) => defer(
3836
- () => client.live.events({ includeDrafts: !!client.config().token, tag: "query-store" })
3837
- ).pipe(
3838
- catchError$1((error) => {
3839
- if (error instanceof CorsOriginError)
3840
- return state.set("setError", { error }), EMPTY;
3841
- throw error;
3842
- })
3843
- )
3844
- ),
3845
- share(),
3846
- filter((e) => e.type === "message")
3847
- );
3848
- return state.observable.pipe(
3849
- mergeMap$1((s) => Object.entries(s.queries)),
3850
- groupBy$1(([key]) => key),
3851
- mergeMap$1((group$) => {
3852
- const syncTags$ = group$.pipe(
3853
- map(([, queryState]) => queryState),
3854
- map((i) => i?.syncTags ?? EMPTY_ARRAY),
3855
- distinctUntilChanged()
3856
- );
3857
- return combineLatest([liveMessages$, syncTags$]).pipe(
3858
- filter(([message, syncTags]) => message.tags.some((tag) => syncTags.includes(tag))),
3859
- tap$1(([message]) => {
3860
- state.set("setLastLiveEventId", setLastLiveEventId(group$.key, message.id));
3861
- })
3862
- );
3863
- })
3864
- ).subscribe({ error: errorHandler(state) });
3865
- };
3866
- function getQueryState(...args) {
3867
- return _getQueryState(...args);
3868
- }
3869
- const _getQueryState = bindActionBySource(
3870
- queryStore,
3871
- createStateSourceAction({
3872
- selector: ({ state, instance }, options) => {
3873
- if (state.error) throw state.error;
3874
- const key = getQueryKey(normalizeOptionsWithPerspective(instance, options)), queryState = state.queries[key];
3875
- if (queryState?.error) throw queryState.error;
3876
- return queryState?.result;
3877
- },
3878
- onSubscribe: ({ state, instance }, options) => {
3879
- const subscriptionId = insecureRandomId(), key = getQueryKey(normalizeOptionsWithPerspective(instance, options));
3880
- return state.set("addSubscriber", addSubscriber(key, subscriptionId)), () => {
3881
- setTimeout(
3882
- () => state.set("removeSubscriber", removeSubscriber(key, subscriptionId)),
3883
- QUERY_STATE_CLEAR_DELAY
3884
- );
3885
- };
3886
- }
3887
- })
3888
- );
3889
- function resolveQuery(...args) {
3890
- return _resolveQuery(...args);
3891
- }
3892
- const _resolveQuery = bindActionBySource(
3893
- queryStore,
3894
- ({ state, instance }, { signal, ...options }) => {
3895
- const normalized = normalizeOptionsWithPerspective(instance, options), { getCurrent } = getQueryState(instance, normalized), key = getQueryKey(normalized), aborted$ = signal ? new Observable((observer) => {
3896
- const cleanup = () => {
3897
- signal.removeEventListener("abort", listener);
3898
- }, listener = () => {
3899
- observer.error(new DOMException("The operation was aborted.", "AbortError")), observer.complete(), cleanup();
3900
- };
3901
- return signal.addEventListener("abort", listener), cleanup;
3902
- }).pipe(
3903
- catchError$1((error) => {
3904
- throw error instanceof Error && error.name === "AbortError" && state.set("cancelQuery", cancelQuery(key)), error;
3905
- })
3906
- ) : NEVER;
3907
- state.set("initializeQuery", initializeQuery(key));
3908
- const resolved$ = state.observable.pipe(
3909
- map(getCurrent),
3910
- first$1((i) => i !== void 0)
3911
- );
3912
- return firstValueFrom(race([resolved$, aborted$]));
3913
- }
3914
- );
3915
2718
  function hashString(str) {
3916
2719
  let hash = 0;
3917
2720
  for (let i = 0; i < str.length; i++)
3918
2721
  hash = (hash * 31 + str.charCodeAt(i)) % 2147483647;
3919
2722
  return Math.abs(hash).toString(16).padStart(8, "0");
3920
2723
  }
3921
- const TITLE_CANDIDATES = ["title", "name", "label", "heading", "header", "caption"], SUBTITLE_CANDIDATES = ["description", "subtitle", ...TITLE_CANDIDATES], PREVIEW_PROJECTION = `{
3922
- // Get all potential title fields
3923
- "titleCandidates": {
3924
- ${TITLE_CANDIDATES.map((field) => `"${field}": ${field}`).join(`,
3925
- `)}
3926
- },
3927
- // Get all potential subtitle fields
3928
- "subtitleCandidates": {
3929
- ${SUBTITLE_CANDIDATES.map((field) => `"${field}": ${field}`).join(`,
3930
- `)}
3931
- },
3932
- "media": coalesce(
3933
- select(
3934
- defined(asset) => {"type": "image-asset", "_ref": asset._ref},
3935
- defined(image.asset) => {"type": "image-asset", "_ref": image.asset._ref},
3936
- defined(mainImage.asset) => {"type": "image-asset", "_ref": mainImage.asset._ref},
3937
- null
3938
- )
3939
- ),
3940
- _type,
3941
- _id,
3942
- _updatedAt
3943
- }`, PREVIEW_TAG = "preview", PREVIEW_PERSPECTIVE = "raw", STABLE_EMPTY_PREVIEW = { data: null, isPending: !1 }, STABLE_ERROR_PREVIEW = {
3944
- data: {
3945
- title: "Preview Error",
3946
- ...!!getEnv("DEV") && { subtitle: "Check the console for more details" }
3947
- },
3948
- isPending: !1
3949
- };
3950
- function assetIdToUrl(assetId, projectId, dataset) {
3951
- const pattern = /^image-(?<assetName>[A-Za-z0-9]+)-(?<dimensions>\d+x\d+)-(?<format>[a-z]+)$/, match = assetId.match(pattern);
3952
- if (!match?.groups)
3953
- throw new Error(
3954
- `Invalid asset ID \`${assetId}\`. Expected: image-{assetName}-{width}x{height}-{format}`
3955
- );
3956
- const { assetName, dimensions, format } = match.groups;
3957
- return `https://cdn.sanity.io/images/${projectId}/${dataset}/${assetName}-${dimensions}.${format}`;
3958
- }
3959
- function hasImageRef(value) {
3960
- return isObject(value) && "_ref" in value && typeof value._ref == "string";
3961
- }
3962
- function normalizeMedia(media, projectId, dataset) {
3963
- return !media || !hasImageRef(media) ? null : {
3964
- type: "image-asset",
3965
- _ref: media._ref,
3966
- url: assetIdToUrl(media._ref, projectId, dataset)
3967
- };
3968
- }
3969
- function findFirstDefined(fieldsToSearch, candidates, exclude) {
3970
- if (candidates)
3971
- for (const field of fieldsToSearch) {
3972
- const value = candidates[field];
3973
- if (typeof value == "string" && value.trim() !== "" && value !== exclude)
3974
- return value;
3975
- }
3976
- }
3977
- function processPreviewQuery({
3978
- projectId,
3979
- dataset,
3980
- ids,
3981
- results
3982
- }) {
3983
- const resultMap = results.reduce((acc, next) => (acc[next._id] = next, acc), {});
3984
- return Object.fromEntries(
3985
- Array.from(ids).map((id) => {
3986
- const publishedId = getPublishedId(id), draftId = getDraftId(id), draftResult = resultMap[draftId], publishedResult = resultMap[publishedId];
3987
- if (!draftResult && !publishedResult) return [id, STABLE_EMPTY_PREVIEW];
3988
- try {
3989
- const result = draftResult || publishedResult;
3990
- if (!result) return [id, STABLE_EMPTY_PREVIEW];
3991
- const title = findFirstDefined(TITLE_CANDIDATES, result.titleCandidates), subtitle = findFirstDefined(SUBTITLE_CANDIDATES, result.subtitleCandidates, title), preview = {
3992
- title: String(title || `${result._type}: ${result._id}`),
3993
- subtitle: subtitle || void 0,
3994
- media: normalizeMedia(result.media, projectId, dataset)
3995
- }, _status = {
3996
- ...draftResult?._updatedAt && { lastEditedDraftAt: draftResult._updatedAt },
3997
- ...publishedResult?._updatedAt && { lastEditedPublishedAt: publishedResult._updatedAt }
3998
- };
3999
- return [id, { data: { ...preview, _status }, isPending: !1 }];
4000
- } catch (e) {
4001
- return console.warn(e), [id, STABLE_ERROR_PREVIEW];
4002
- }
4003
- })
4004
- );
4005
- }
4006
- function createPreviewQuery(documentIds) {
4007
- const allIds = Array.from(documentIds).flatMap((id) => [getPublishedId(id), getDraftId(id)]), queryHash = hashString(PREVIEW_PROJECTION);
4008
- return {
4009
- query: `*[_id in $__ids_${queryHash}]${PREVIEW_PROJECTION}`,
4010
- params: {
4011
- [`__ids_${queryHash}`]: allIds
4012
- }
4013
- };
4014
- }
4015
- const BATCH_DEBOUNCE_TIME$1 = 50, isSetEqual$1 = (a, b) => a.size === b.size && Array.from(a).every((i) => b.has(i)), subscribeToStateAndFetchBatches$1 = ({
4016
- state,
4017
- instance,
4018
- key: { projectId, dataset }
4019
- }) => state.observable.pipe(
4020
- map(({ subscriptions }) => new Set(Object.keys(subscriptions))),
4021
- distinctUntilChanged(isSetEqual$1),
4022
- debounceTime(BATCH_DEBOUNCE_TIME$1),
4023
- startWith$1(/* @__PURE__ */ new Set()),
4024
- pairwise$1(),
4025
- tap$1(([prevIds, currIds]) => {
4026
- const newIds = [...currIds].filter((element) => !prevIds.has(element));
4027
- state.set("updatingPending", (prev) => {
4028
- const pendingValues = newIds.reduce((acc, id) => {
4029
- const prevValue = prev.values[id], value = prevValue?.data ? prevValue.data : null;
4030
- return acc[id] = { data: value, isPending: !0 }, acc;
4031
- }, {});
4032
- return { values: { ...prev.values, ...pendingValues } };
4033
- });
4034
- }),
4035
- map(([, ids]) => ids),
4036
- distinctUntilChanged(isSetEqual$1)
4037
- ).pipe(
4038
- switchMap((ids) => {
4039
- if (!ids.size) return EMPTY;
4040
- const { query, params } = createPreviewQuery(ids), controller = new AbortController();
4041
- return new Observable((observer) => {
4042
- const { getCurrent, observable } = getQueryState(instance, {
4043
- query,
4044
- params,
4045
- tag: PREVIEW_TAG,
4046
- perspective: PREVIEW_PERSPECTIVE,
4047
- projectId,
4048
- dataset
4049
- }), subscription = defer(() => getCurrent() === void 0 ? from(
4050
- resolveQuery(instance, {
4051
- query,
4052
- params,
4053
- tag: PREVIEW_TAG,
4054
- perspective: PREVIEW_PERSPECTIVE,
4055
- signal: controller.signal,
4056
- projectId,
4057
- dataset
4058
- })
4059
- ).pipe(switchMap(() => observable)) : observable).pipe(filter((result) => result !== void 0)).subscribe(observer);
4060
- return () => {
4061
- controller.signal.aborted || controller.abort(), subscription.unsubscribe();
4062
- };
4063
- }).pipe(map((data) => ({ data, ids })));
4064
- }),
4065
- map(({ ids, data }) => ({
4066
- values: processPreviewQuery({
4067
- projectId,
4068
- dataset,
4069
- ids,
4070
- results: data
4071
- })
4072
- }))
4073
- ).subscribe({
4074
- next: ({ values }) => {
4075
- state.set("updateResult", (prev) => ({ values: { ...prev.values, ...values } }));
4076
- }
4077
- }), previewStore = {
4078
- name: "Preview",
4079
- getInitialState() {
4080
- return {
4081
- subscriptions: {},
4082
- values: {}
4083
- };
4084
- },
4085
- initialize: (context) => {
4086
- const subscription = subscribeToStateAndFetchBatches$1(context);
4087
- return () => subscription.unsubscribe;
4088
- }
4089
- };
4090
- function getPreviewState(...args) {
4091
- return _getPreviewState(...args);
4092
- }
4093
- const _getPreviewState = bindActionByDataset(
4094
- previewStore,
4095
- createStateSourceAction({
4096
- selector: ({ state }, docHandle) => state.values[docHandle.documentId] ?? STABLE_EMPTY_PREVIEW,
4097
- onSubscribe: ({ state }, docHandle) => {
4098
- const subscriptionId = insecureRandomId(), documentId = getPublishedId(docHandle.documentId);
4099
- return state.set("addSubscription", (prev) => ({
4100
- subscriptions: {
4101
- ...prev.subscriptions,
4102
- [documentId]: {
4103
- ...prev.subscriptions[documentId],
4104
- [subscriptionId]: !0
4105
- }
4106
- }
4107
- })), () => {
4108
- state.set("removeSubscription", (prev) => {
4109
- const documentSubscriptions = omit(prev.subscriptions[documentId], subscriptionId), hasSubscribers = !!Object.keys(documentSubscriptions).length, prevValue = prev.values[documentId], previewValue = prevValue?.data ? prevValue.data : null;
4110
- return {
4111
- subscriptions: hasSubscribers ? { ...prev.subscriptions, [documentId]: documentSubscriptions } : omit(prev.subscriptions, documentId),
4112
- values: hasSubscribers ? prev.values : { ...prev.values, [documentId]: { data: previewValue, isPending: !1 } }
4113
- };
4114
- });
4115
- };
4116
- }
4117
- })
4118
- ), resolvePreview = bindActionByDataset(
4119
- previewStore,
4120
- ({ instance }, docHandle) => firstValueFrom(getPreviewState(instance, docHandle).observable.pipe(filter((i) => !!i.data)))
4121
- ), PROJECTION_TAG = "projection", PROJECTION_STATE_CLEAR_DELAY = 1e3, STABLE_EMPTY_PROJECTION = {
2724
+ const PROJECTION_TAG = "projection", PROJECTION_STATE_CLEAR_DELAY = 1e3, STABLE_EMPTY_PROJECTION = {
4122
2725
  data: null,
4123
2726
  isPending: !1
4124
2727
  };
@@ -4155,7 +2758,7 @@ function processProjectionQuery({
4155
2758
  }) {
4156
2759
  const groupedResults = {};
4157
2760
  for (const result of results) {
4158
- const originalId = getPublishedId(result._id), hash = result.__projectionHash;
2761
+ const originalId = getPublishedId(DocumentId(result._id)), hash = result.__projectionHash;
4159
2762
  ids.has(originalId) && (groupedResults[originalId] || (groupedResults[originalId] = {}), groupedResults[originalId][hash] || (groupedResults[originalId][hash] = void 0), groupedResults[originalId][hash] = result);
4160
2763
  }
4161
2764
  const finalValues = {};
@@ -4181,7 +2784,7 @@ function processProjectionQuery({
4181
2784
  function buildStatusQueryIds(documentIds, perspective) {
4182
2785
  const ids = [], releaseName = isReleasePerspective(perspective) ? perspective.releaseName : null;
4183
2786
  for (const id of documentIds) {
4184
- const publishedId = getPublishedId$2(DocumentId(id)), draftId = getDraftId$1(publishedId);
2787
+ const publishedId = getPublishedId(DocumentId(id)), draftId = getDraftId(publishedId);
4185
2788
  ids.push(draftId, publishedId), releaseName && ids.push(getVersionId(publishedId, releaseName));
4186
2789
  }
4187
2790
  return ids;
@@ -4189,7 +2792,7 @@ function buildStatusQueryIds(documentIds, perspective) {
4189
2792
  function processStatusQueryResults(results) {
4190
2793
  const documentStatuses = {};
4191
2794
  for (const result of results) {
4192
- const id = DocumentId(result._id), updatedAt = result._updatedAt, publishedId = getPublishedId$2(id), statusData = documentStatuses[publishedId] ?? {};
2795
+ const id = DocumentId(result._id), updatedAt = result._updatedAt, publishedId = getPublishedId(id), statusData = documentStatuses[publishedId] ?? {};
4193
2796
  isDraftId(id) ? statusData.lastEditedDraftAt = updatedAt : isVersionId(id) ? statusData.lastEditedVersionAt = updatedAt : isPublishedId(id) && (statusData.lastEditedPublishedAt = updatedAt), documentStatuses[publishedId] = statusData;
4194
2797
  }
4195
2798
  return documentStatuses;
@@ -4200,10 +2803,10 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
4200
2803
  key: { source, perspective }
4201
2804
  }) => {
4202
2805
  const documentProjections$ = state.observable.pipe(
4203
- map((s) => s.documentProjections),
2806
+ map$1((s) => s.documentProjections),
4204
2807
  distinctUntilChanged(isEqual)
4205
2808
  ), activeDocumentIds$ = state.observable.pipe(
4206
- map(({ subscriptions }) => new Set(Object.keys(subscriptions))),
2809
+ map$1(({ subscriptions }) => new Set(Object.keys(subscriptions))),
4207
2810
  distinctUntilChanged(isSetEqual)
4208
2811
  ), pendingUpdateSubscription = activeDocumentIds$.pipe(
4209
2812
  debounceTime(BATCH_DEBOUNCE_TIME),
@@ -4253,7 +2856,7 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
4253
2856
  // temporary guard here until we're ready for everything to be queried via global API in v3
4254
2857
  ...source && !isDatasetSource(source) ? { source } : {}
4255
2858
  })
4256
- ).pipe(switchMap(() => observable)) : observable).pipe(filter((result) => result !== void 0)).subscribe(observer);
2859
+ ).pipe(switchMap(() => observable)) : observable).pipe(filter$1((result) => result !== void 0)).subscribe(observer);
4257
2860
  return () => {
4258
2861
  controller.signal.aborted || controller.abort(), subscription.unsubscribe();
4259
2862
  };
@@ -4275,23 +2878,23 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
4275
2878
  // temporary guard here until we're ready for everything to be queried via global API
4276
2879
  ...source && !isDatasetSource(source) ? { source } : {}
4277
2880
  })
4278
- ).pipe(switchMap(() => observable)) : observable).pipe(filter((result) => result !== void 0)).subscribe(observer);
2881
+ ).pipe(switchMap(() => observable)) : observable).pipe(filter$1((result) => result !== void 0)).subscribe(observer);
4279
2882
  return () => {
4280
2883
  subscription.unsubscribe();
4281
2884
  };
4282
2885
  });
4283
2886
  return combineLatest([projectionQuery$, statusQuery$]).pipe(
4284
- filter(
2887
+ filter$1(
4285
2888
  (pair) => pair[0] !== void 0 && pair[1] !== void 0
4286
2889
  ),
4287
- map(([projection, status]) => ({
2890
+ map$1(([projection, status]) => ({
4288
2891
  data: projection,
4289
2892
  ids,
4290
2893
  statusResults: status
4291
2894
  }))
4292
2895
  );
4293
2896
  }),
4294
- map(({ ids, data, statusResults }) => {
2897
+ map$1(({ ids, data, statusResults }) => {
4295
2898
  const documentStatuses = processStatusQueryResults(statusResults);
4296
2899
  state.set("updateStatuses", (prev) => ({
4297
2900
  documentStatuses: {
@@ -4325,7 +2928,7 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
4325
2928
  return new Subscription(() => {
4326
2929
  pendingUpdateSubscription.unsubscribe(), queryExecutionSubscription.unsubscribe();
4327
2930
  });
4328
- }, projectionStore = {
2931
+ }, projectionStore = defineStore({
4329
2932
  name: "Projection",
4330
2933
  getInitialState() {
4331
2934
  return {
@@ -4339,7 +2942,7 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
4339
2942
  const batchSubscription = subscribeToStateAndFetchBatches(context);
4340
2943
  return () => batchSubscription.unsubscribe();
4341
2944
  }
4342
- };
2945
+ });
4343
2946
  function getProjectionState(...args) {
4344
2947
  return _getProjectionState(...args);
4345
2948
  }
@@ -4347,11 +2950,11 @@ const _getProjectionState = bindActionBySourceAndPerspective(
4347
2950
  projectionStore,
4348
2951
  createStateSourceAction({
4349
2952
  selector: ({ state }, options) => {
4350
- const documentId = getPublishedId$2(DocumentId(options.documentId)), projectionHash = hashString(options.projection);
2953
+ const documentId = getPublishedId(DocumentId(options.documentId)), projectionHash = hashString(options.projection);
4351
2954
  return state.values[documentId]?.[projectionHash] ?? STABLE_EMPTY_PROJECTION;
4352
2955
  },
4353
2956
  onSubscribe: ({ state }, options) => {
4354
- const { projection, ...docHandle } = options, subscriptionId = insecureRandomId(), documentId = getPublishedId$2(DocumentId(docHandle.documentId)), validProjection = validateProjection(projection), projectionHash = hashString(validProjection);
2957
+ const { projection, ...docHandle } = options, subscriptionId = insecureRandomId(), documentId = getPublishedId(DocumentId(docHandle.documentId)), validProjection = validateProjection(projection), projectionHash = hashString(validProjection);
4355
2958
  return state.set("addSubscription", (prev) => ({
4356
2959
  documentProjections: {
4357
2960
  ...prev.documentProjections,
@@ -4371,7 +2974,7 @@ const _getProjectionState = bindActionBySourceAndPerspective(
4371
2974
  }
4372
2975
  }
4373
2976
  })), () => {
4374
- setTimeout(() => {
2977
+ setCleanupTimeout(() => {
4375
2978
  state.set("removeSubscription", (prev) => {
4376
2979
  const documentSubscriptionsForHash = omit(
4377
2980
  prev.subscriptions[documentId]?.[projectionHash],
@@ -4400,6 +3003,20 @@ const _getProjectionState = bindActionBySourceAndPerspective(
4400
3003
  }
4401
3004
  })
4402
3005
  );
3006
+ function getPreviewState(instance, options) {
3007
+ const projectionState = getProjectionState(instance, {
3008
+ ...options,
3009
+ projection: PREVIEW_PROJECTION
3010
+ }), transformResult = (current) => !current || current.data === null ? { data: null, isPending: current?.isPending ?? !1 } : {
3011
+ data: transformProjectionToPreview(instance, current.data, options.source),
3012
+ isPending: current.isPending
3013
+ };
3014
+ return {
3015
+ getCurrent: () => transformResult(projectionState.getCurrent()),
3016
+ subscribe: (callback) => projectionState.subscribe(callback),
3017
+ observable: projectionState.observable.pipe(map$1(transformResult))
3018
+ };
3019
+ }
4403
3020
  function resolveProjection(...args) {
4404
3021
  return _resolveProjection(...args);
4405
3022
  }
@@ -4407,10 +3024,21 @@ const _resolveProjection = bindActionBySourceAndPerspective(
4407
3024
  projectionStore,
4408
3025
  ({ instance }, options) => firstValueFrom(
4409
3026
  getProjectionState(instance, options).observable.pipe(
4410
- filter((state) => !!state?.data)
3027
+ filter$1((state) => !!state?.data)
4411
3028
  )
4412
3029
  )
4413
- ), API_VERSION = "v2025-02-19", projects = createFetcherStore({
3030
+ );
3031
+ async function resolvePreview(instance, options) {
3032
+ const projectionResult = await resolveProjection(instance, {
3033
+ ...options,
3034
+ projection: PREVIEW_PROJECTION
3035
+ });
3036
+ return projectionResult.data ? {
3037
+ data: transformProjectionToPreview(instance, projectionResult.data, options.source),
3038
+ isPending: projectionResult.isPending
3039
+ } : { data: null, isPending: projectionResult.isPending };
3040
+ }
3041
+ const API_VERSION = "v2025-02-19", projects = createFetcherStore({
4414
3042
  name: "Projects",
4415
3043
  getKey: (_instance, options) => {
4416
3044
  const orgKey = options?.organizationId ? `:org:${options.organizationId}` : "", membersKey = options?.includeMembers === !1 ? ":no-members" : "";
@@ -4430,29 +3058,7 @@ const _resolveProjection = bindActionBySourceAndPerspective(
4430
3058
  });
4431
3059
  })
4432
3060
  )
4433
- }), getProjectsState = projects.getState, resolveProjects = projects.resolveState, TOKEN_REGEX = /(?:[^\s"]+|"[^"]*")+/g;
4434
- function isNegationToken(token) {
4435
- return typeof token < "u" && token.trim().startsWith("-");
4436
- }
4437
- function isPrefixToken(token) {
4438
- return typeof token < "u" && token.trim().endsWith("*");
4439
- }
4440
- function isExactMatchToken(token) {
4441
- return !!token && token.length >= 2 && token.startsWith('"') && token.endsWith('"');
4442
- }
4443
- function createGroqSearchFilter(query) {
4444
- const trimmedQuery = query.trim();
4445
- if (!trimmedQuery)
4446
- return "";
4447
- const tokens = trimmedQuery.match(TOKEN_REGEX) ?? [], reversedIndex = [...tokens].reverse().findIndex(
4448
- (token) => !isNegationToken(token) && !isExactMatchToken(token)
4449
- ), finalIncrementalTokenIndex = reversedIndex === -1 ? -1 : tokens.length - 1 - reversedIndex, finalIncrementalToken = tokens[finalIncrementalTokenIndex], processedTokens = [...tokens];
4450
- return finalIncrementalToken !== void 0 && !isPrefixToken(finalIncrementalToken) && processedTokens.splice(
4451
- finalIncrementalTokenIndex,
4452
- 1,
4453
- `${finalIncrementalToken}*`
4454
- ), `[@] match text::query("${processedTokens.join(" ").replace(/"/g, '\\"')}")`;
4455
- }
3061
+ }), getProjectsState = projects.getState, resolveProjects = projects.resolveState;
4456
3062
  function defineIntent(intent) {
4457
3063
  if (!intent.id)
4458
3064
  throw new Error("Intent must have an id");
@@ -4511,11 +3117,10 @@ function getCorsErrorProjectId(error) {
4511
3117
  const projMatch = (error.message || "").match(/manage\/project\/([^/?#]+)/);
4512
3118
  return projMatch ? projMatch[1] : null;
4513
3119
  }
4514
- var version = "2.8.0";
4515
- const CORE_SDK_VERSION = getEnv("PKG_VERSION") || `${version}-development`;
4516
3120
  export {
4517
3121
  AuthStateType,
4518
3122
  CORE_SDK_VERSION,
3123
+ PREVIEW_PROJECTION,
4519
3124
  agentGenerate,
4520
3125
  agentPatch,
4521
3126
  agentPrompt,
@@ -4601,6 +3206,7 @@ export {
4601
3206
  slicePath2 as slicePath,
4602
3207
  stringifyPath2 as stringifyPath,
4603
3208
  subscribeDocumentEvents,
3209
+ transformProjectionToPreview,
4604
3210
  unpublishDocument
4605
3211
  };
4606
3212
  //# sourceMappingURL=index.js.map