@sanity/sdk 2.19.0 → 2.20.1

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 (62) hide show
  1. package/dist/_exports/_internal.d.ts +2 -2
  2. package/dist/_exports/_internal.js +196 -22
  3. package/dist/_exports/_internal.js.map +1 -1
  4. package/dist/authStore-CWTAuieY.js +1072 -0
  5. package/dist/authStore-CWTAuieY.js.map +1 -0
  6. package/dist/clientStore-CMzJ7XhZ.js +168 -0
  7. package/dist/clientStore-CMzJ7XhZ.js.map +1 -0
  8. package/dist/createGroqSearchFilter-B0NdA-EP.js +1222 -0
  9. package/dist/createGroqSearchFilter-B0NdA-EP.js.map +1 -0
  10. package/dist/getEnv-76AjZd_f.js +178 -0
  11. package/dist/getEnv-76AjZd_f.js.map +1 -0
  12. package/dist/index.d.ts +2 -2105
  13. package/dist/index.js +4140 -3870
  14. package/dist/index.js.map +1 -1
  15. package/dist/rolldown-runtime-vyAXikos.js +9 -0
  16. package/dist/telemetryManager-w-AMXtmz.js +127 -0
  17. package/dist/telemetryManager-w-AMXtmz.js.map +1 -0
  18. package/dist/utils-BMwA8Kg9.d.ts +3334 -0
  19. package/dist/utils-BMwA8Kg9.d.ts.map +1 -0
  20. package/dist/version-ByqNiWrK.js +9 -0
  21. package/dist/version-ByqNiWrK.js.map +1 -0
  22. package/package.json +12 -20
  23. package/src/_exports/_internal.ts +1 -0
  24. package/src/_exports/index.ts +30 -0
  25. package/src/comments/addonDatasetStore.test.ts +215 -0
  26. package/src/comments/addonDatasetStore.ts +249 -0
  27. package/src/comments/buildCommentThreads.test.ts +83 -0
  28. package/src/comments/buildCommentThreads.ts +54 -0
  29. package/src/comments/commentActions.test.ts +540 -0
  30. package/src/comments/commentActions.ts +555 -0
  31. package/src/comments/commentFieldPath.test.ts +40 -0
  32. package/src/comments/commentFieldPath.ts +44 -0
  33. package/src/comments/commentsConstants.ts +80 -0
  34. package/src/comments/commentsStore.test.ts +419 -0
  35. package/src/comments/commentsStore.ts +483 -0
  36. package/src/comments/normalizeComment.test.ts +116 -0
  37. package/src/comments/normalizeComment.ts +45 -0
  38. package/src/comments/observeComments.test.ts +193 -0
  39. package/src/comments/observeComments.ts +113 -0
  40. package/src/comments/reducers.test.ts +277 -0
  41. package/src/comments/reducers.ts +316 -0
  42. package/src/comments/types.ts +249 -0
  43. package/src/comments/weakenReferences.test.ts +47 -0
  44. package/src/comments/weakenReferences.ts +29 -0
  45. package/src/document/documentConstants.ts +8 -0
  46. package/src/document/documentStore.test.ts +98 -1
  47. package/src/document/documentStore.ts +36 -5
  48. package/src/document/patchOperations.test.ts +27 -0
  49. package/src/document/patchOperations.ts +10 -1
  50. package/src/document/permissions.test.ts +3 -1
  51. package/src/document/reducers.test.ts +133 -0
  52. package/src/document/reducers.ts +18 -3
  53. package/src/projection/projectionStore.test.ts +0 -8
  54. package/dist/_chunks-dts/createGroqSearchFilter.d.ts +0 -923
  55. package/dist/_chunks-dts/createGroqSearchFilter.d.ts.map +0 -1
  56. package/dist/_chunks-es/_internal.js +0 -134
  57. package/dist/_chunks-es/_internal.js.map +0 -1
  58. package/dist/_chunks-es/createGroqSearchFilter.js +0 -1590
  59. package/dist/_chunks-es/createGroqSearchFilter.js.map +0 -1
  60. package/dist/_chunks-es/telemetryManager.js +0 -93
  61. package/dist/_chunks-es/telemetryManager.js.map +0 -1
  62. package/dist/index.d.ts.map +0 -1
@@ -1,1590 +0,0 @@
1
- import { createClient, CorsOriginError, DisconnectError, ConnectionFailedError } from "@sanity/client";
2
- import { createImageUrlBuilder } from "@sanity/image-url";
3
- import "groq";
4
- import { Observable, map, distinctUntilChanged, shareReplay, skip, defer, finalize, filter, exhaustMap, timer, switchMap, takeWhile, catchError, EMPTY, fromEvent, retry, BehaviorSubject, combineLatest, startWith, tap, pairwise, mergeMap, groupBy, of, share, NEVER, first, firstValueFrom, race } from "rxjs";
5
- import "@sanity/types";
6
- import { devtools } from "zustand/middleware";
7
- import { createStore } from "zustand/vanilla";
8
- import { createSelector } from "reselect";
9
- function isDatasetResource(resource) {
10
- return "projectId" in resource && "dataset" in resource;
11
- }
12
- function isMediaLibraryResource(resource) {
13
- return "mediaLibraryId" in resource;
14
- }
15
- function isCanvasResource(resource) {
16
- return "canvasId" in resource;
17
- }
18
- function isDatasetSource(source) {
19
- return isDatasetResource(source);
20
- }
21
- function isMediaLibrarySource(source) {
22
- return isMediaLibraryResource(source);
23
- }
24
- function isCanvasSource(source) {
25
- return isCanvasResource(source);
26
- }
27
- const DEFAULT_BASE = "http://localhost", AUTH_CODE_PARAM = "sid", DEFAULT_API_VERSION$1 = "2021-06-07", REQUEST_TAG_PREFIX = "sanity.sdk.auth";
28
- function resolveAuthMode(config, locationHref) {
29
- return isStudioConfig(config) ? "studio" : detectDashboardContext(locationHref) ? "dashboard" : "standalone";
30
- }
31
- function isStudioConfig(config) {
32
- return !!config.studio || !!config.studioMode?.enabled;
33
- }
34
- function detectDashboardContext(locationHref) {
35
- try {
36
- const contextParam = new URL(locationHref, DEFAULT_BASE).searchParams.get("_context");
37
- if (!contextParam) return !1;
38
- const parsed = JSON.parse(contextParam);
39
- return typeof parsed == "object" && parsed !== null && !Array.isArray(parsed) && Object.keys(parsed).length > 0;
40
- } catch (err) {
41
- return console.error("Failed to parse dashboard context from initial location:", err), !1;
42
- }
43
- }
44
- var AuthStateType = /* @__PURE__ */ ((AuthStateType2) => (AuthStateType2.LOGGED_IN = "logged-in", AuthStateType2.LOGGING_IN = "logging-in", AuthStateType2.ERROR = "error", AuthStateType2.LOGGED_OUT = "logged-out", AuthStateType2))(AuthStateType || {});
45
- const isReleasePerspective = (perspective) => typeof perspective == "object" && perspective !== null && "releaseName" in perspective;
46
- function insecureRandomId() {
47
- return Array.from({ length: 16 }, () => Math.floor(Math.random() * 16).toString(16)).join("");
48
- }
49
- const LOG_LEVEL_PRIORITY = {
50
- error: 0,
51
- warn: 1,
52
- info: 2,
53
- debug: 3,
54
- trace: 4
55
- }, DEFAULT_CONFIG = {
56
- level: "warn",
57
- namespaces: [],
58
- internal: !1,
59
- timestamps: !0,
60
- enableInProduction: !1,
61
- handler: {
62
- // eslint-disable-next-line no-console
63
- error: console.error.bind(console),
64
- // eslint-disable-next-line no-console
65
- warn: console.warn.bind(console),
66
- // eslint-disable-next-line no-console
67
- info: console.info.bind(console),
68
- // eslint-disable-next-line no-console
69
- debug: console.debug.bind(console),
70
- // eslint-disable-next-line no-console
71
- trace: console.debug.bind(console)
72
- // trace uses console.debug
73
- }
74
- };
75
- function parseDebugEnvVar() {
76
- if (typeof process > "u" || !process.env?.DEBUG)
77
- return null;
78
- const debug = process.env.DEBUG;
79
- if (!debug.includes("sanity"))
80
- return null;
81
- const config = {}, levelMatch = debug.match(/sanity:(trace|debug|info|warn|error):/), hasLevelSpecifier = !!levelMatch;
82
- if (levelMatch ? config.level = levelMatch[1] : config.level = "debug", debug === "sanity")
83
- config.namespaces = ["*"];
84
- else if (hasLevelSpecifier && debug.match(/sanity:(trace|debug|info|warn|error):\*/))
85
- config.namespaces = ["*"];
86
- else if (!hasLevelSpecifier && debug.includes("sanity:*"))
87
- config.namespaces = ["*"];
88
- else {
89
- const namespaces = debug.split(",").filter((s) => s.includes("sanity:")).map((s) => {
90
- const cleaned = s.replace(/^sanity:/, "");
91
- return hasLevelSpecifier && cleaned.match(/^(trace|debug|info|warn|error):/) ? cleaned.split(":").slice(1).join(":") : cleaned.split(":")[0];
92
- }).filter(Boolean).filter((ns) => ns !== "*");
93
- namespaces.length > 0 && (config.namespaces = namespaces);
94
- }
95
- return debug.includes(":internal") && (config.internal = !0), config;
96
- }
97
- const envConfig = parseDebugEnvVar();
98
- let globalConfig = {
99
- ...DEFAULT_CONFIG,
100
- ...envConfig ?? {}
101
- };
102
- envConfig && (["info", "debug", "trace"].includes(globalConfig.level) || globalConfig.level === "warn") && console.info(
103
- `[${(/* @__PURE__ */ new Date()).toISOString()}] [INFO] [sdk] Logging auto-configured from DEBUG environment variable`,
104
- {
105
- level: globalConfig.level,
106
- namespaces: globalConfig.namespaces,
107
- internal: globalConfig.internal,
108
- source: "env:DEBUG",
109
- value: typeof process < "u" ? process.env?.DEBUG : void 0
110
- }
111
- );
112
- function configureLogging(config) {
113
- globalConfig = {
114
- ...globalConfig,
115
- ...config,
116
- handler: config.handler ?? globalConfig.handler
117
- };
118
- }
119
- function isLoggingEnabled() {
120
- return typeof process < "u" && process.env?.NODE_ENV === "production" ? globalConfig.enableInProduction : !0;
121
- }
122
- function isNamespaceEnabled(namespace) {
123
- return isLoggingEnabled() ? globalConfig.namespaces.includes("*") ? !0 : globalConfig.namespaces.includes(namespace) : !1;
124
- }
125
- function isLevelEnabled(level) {
126
- return isLoggingEnabled() ? LOG_LEVEL_PRIORITY[level] <= LOG_LEVEL_PRIORITY[globalConfig.level] : !1;
127
- }
128
- function formatMessage(namespace, level, message, context) {
129
- const parts = [];
130
- if (globalConfig.timestamps) {
131
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
132
- parts.push(`[${timestamp}]`);
133
- }
134
- parts.push(`[${level.toUpperCase()}]`), parts.push(`[${namespace}]`);
135
- const instanceContext = context?.instanceContext;
136
- 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];
137
- }
138
- function sanitizeContext(context) {
139
- if (!context || Object.keys(context).length === 0) return;
140
- const sanitized = { ...context }, sensitiveKeys = ["token", "password", "secret", "apiKey", "authorization"];
141
- for (const key of Object.keys(sanitized))
142
- sensitiveKeys.some((sensitive) => key.toLowerCase().includes(sensitive)) && (sanitized[key] = "[REDACTED]");
143
- return sanitized;
144
- }
145
- function createLogger(namespace, baseContext) {
146
- const logAtLevel = (level, message, context) => {
147
- if (!isNamespaceEnabled(namespace) || !isLevelEnabled(level) || context?.internal && !globalConfig.internal) return;
148
- const mergedContext = { ...baseContext, ...context }, sanitized = sanitizeContext(mergedContext), [formatted, finalContext] = formatMessage(namespace, level, message, sanitized);
149
- globalConfig.handler[level](formatted, finalContext);
150
- };
151
- return {
152
- namespace,
153
- error: (message, context) => logAtLevel("error", message, context),
154
- warn: (message, context) => logAtLevel("warn", message, context),
155
- info: (message, context) => logAtLevel("info", message, context),
156
- debug: (message, context) => logAtLevel("debug", message, context),
157
- trace: (message, context) => logAtLevel("trace", message, { ...context, internal: !0 }),
158
- isLevelEnabled: (level) => isNamespaceEnabled(namespace) && isLevelEnabled(level),
159
- child: (childContext) => createLogger(namespace, { ...baseContext, ...childContext }),
160
- getInstanceContext: () => baseContext?.instanceContext
161
- };
162
- }
163
- function isObject(value) {
164
- return typeof value == "object" && value !== null;
165
- }
166
- const hasOwn = (value, key) => Object.prototype.hasOwnProperty.call(value, key), isPlainObject = (value) => {
167
- if (!isObject(value)) return !1;
168
- const prototype = Object.getPrototypeOf(value);
169
- return prototype === Object.prototype || prototype === null;
170
- };
171
- function omitProperty(value, key) {
172
- if (!value) return {};
173
- const { [key]: _omitted, ...rest } = value;
174
- return rest;
175
- }
176
- function pickProperties(value, keys) {
177
- const result = {};
178
- for (const key of keys)
179
- hasOwn(value, key) && (result[key] = value[key]);
180
- return result;
181
- }
182
- const areSetsEqual = (left, right) => {
183
- if (left.size !== right.size) return !1;
184
- const unmatched = [...right];
185
- outer: for (const leftValue of left) {
186
- for (let index = 0; index < unmatched.length; index++)
187
- if (isDeepEqual(leftValue, unmatched[index])) {
188
- unmatched.splice(index, 1);
189
- continue outer;
190
- }
191
- return !1;
192
- }
193
- return unmatched.length === 0;
194
- }, areMapsEqual = (left, right) => {
195
- if (left.size !== right.size) return !1;
196
- const unmatched = [...right.entries()];
197
- outer: for (const [leftKey, leftValue] of left) {
198
- for (let index = 0; index < unmatched.length; index++) {
199
- const [rightKey, rightValue] = unmatched[index];
200
- if (isDeepEqual(leftKey, rightKey) && isDeepEqual(leftValue, rightValue)) {
201
- unmatched.splice(index, 1);
202
- continue outer;
203
- }
204
- }
205
- return !1;
206
- }
207
- return unmatched.length === 0;
208
- };
209
- function isDeepEqual(left, right) {
210
- if (Object.is(left, right)) return !0;
211
- if (!isObject(left) || !isObject(right)) return !1;
212
- if (left instanceof Date && right instanceof Date)
213
- return left.getTime() === right.getTime();
214
- if (left instanceof RegExp && right instanceof RegExp)
215
- return left.source === right.source && left.flags === right.flags;
216
- if (left instanceof Set && right instanceof Set)
217
- return areSetsEqual(left, right);
218
- if (left instanceof Map && right instanceof Map)
219
- return areMapsEqual(left, right);
220
- if (Array.isArray(left) || Array.isArray(right))
221
- return !Array.isArray(left) || !Array.isArray(right) || left.length !== right.length ? !1 : left.every((value, index) => isDeepEqual(value, right[index]));
222
- if (!isPlainObject(left) || !isPlainObject(right)) return !1;
223
- const leftKeys = Object.keys(left), rightKeys = Object.keys(right);
224
- if (leftKeys.length !== rightKeys.length) return !1;
225
- for (const key of leftKeys)
226
- if (!hasOwn(right, key) || !isDeepEqual(left[key], right[key]))
227
- return !1;
228
- return !0;
229
- }
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 defineStore(storeDefinition) {
255
- return storeDefinition;
256
- }
257
- function createStoreInstance(instance, key, { name, getInitialState, initialize }) {
258
- const state = createStoreState(getInitialState(instance, key), {
259
- enabled: !!getEnv("DEV"),
260
- name: `${name}-${key.name}`
261
- }), dispose = initialize?.({ state, instance, key }), disposed = { current: !1 };
262
- return {
263
- state,
264
- dispose: () => {
265
- disposed.current || (disposed.current = !0, dispose?.());
266
- },
267
- isDisposed: () => disposed.current
268
- };
269
- }
270
- function createActionBinder(keyFn) {
271
- const instanceRegistry = /* @__PURE__ */ new Map(), storeRegistry = /* @__PURE__ */ new Map();
272
- return function(storeDefinition, action) {
273
- return function(instance, ...params) {
274
- const key = keyFn(instance, ...params), compositeKey = storeDefinition.name + (key.name ? `:${key.name}` : "");
275
- let instances = instanceRegistry.get(compositeKey);
276
- instances || (instances = /* @__PURE__ */ new Set(), instanceRegistry.set(compositeKey, instances)), instances.has(instance.instanceId) || (instances.add(instance.instanceId), instance.onDispose(() => {
277
- instances.delete(instance.instanceId), instances.size === 0 && (storeRegistry.get(compositeKey)?.dispose(), storeRegistry.delete(compositeKey), instanceRegistry.delete(compositeKey));
278
- }));
279
- let storeInstance = storeRegistry.get(compositeKey);
280
- return storeInstance || (storeInstance = createStoreInstance(instance, key, storeDefinition), storeRegistry.set(compositeKey, storeInstance)), action({ instance, state: storeInstance.state, key }, ...params);
281
- };
282
- };
283
- }
284
- const createResourceKey = (instance, resource) => {
285
- let name, resourceForKey;
286
- if (resource) {
287
- if (resourceForKey = resource, isDatasetResource(resource))
288
- name = `${resource.projectId}.${resource.dataset}`;
289
- else if (isMediaLibraryResource(resource))
290
- name = `media-library:${resource.mediaLibraryId}`;
291
- else if (isCanvasResource(resource))
292
- name = `canvas:${resource.canvasId}`;
293
- else
294
- throw new Error(`Received invalid resource: ${JSON.stringify(resource)}`);
295
- return { name, resource: resourceForKey };
296
- }
297
- const { projectId, dataset } = instance.config;
298
- if (!projectId || !dataset)
299
- throw new Error("This API requires a project ID and dataset configured.");
300
- return { name: `${projectId}.${dataset}`, resource: { projectId, dataset } };
301
- }, bindActionByResource = createActionBinder((instance, { resource }) => createResourceKey(instance, resource)), bindActionByResourceAndPerspective = createActionBinder((instance, options) => {
302
- const { resource, perspective } = options, utilizedPerspective = perspective ?? instance.config.perspective ?? "drafts";
303
- let perspectiveKey;
304
- isReleasePerspective(utilizedPerspective) ? perspectiveKey = utilizedPerspective.releaseName : typeof utilizedPerspective == "string" ? perspectiveKey = utilizedPerspective : perspectiveKey = JSON.stringify(utilizedPerspective);
305
- const sourceKey = createResourceKey(instance, resource);
306
- return {
307
- name: `${sourceKey.name}:${perspectiveKey}`,
308
- resource: sourceKey.resource,
309
- perspective: utilizedPerspective
310
- };
311
- }), bindActionGlobally = createActionBinder((..._rest) => ({ name: "global" }));
312
- function createStateSourceAction(options) {
313
- const selector = typeof options == "function" ? options : options.selector, subscribeHandler = options && "onSubscribe" in options ? options.onSubscribe : void 0, isEqual = options && "isEqual" in options ? options.isEqual ?? Object.is : Object.is, selectorContextCache = /* @__PURE__ */ new WeakMap();
314
- function stateSourceAction(context, ...params) {
315
- const { state, instance } = context, getCurrent = (currentState) => {
316
- if (typeof currentState != "object" || currentState === null)
317
- throw new Error(
318
- `Expected store state to be an object but got "${typeof currentState}" instead`
319
- );
320
- let instanceCache = selectorContextCache.get(currentState);
321
- instanceCache || (instanceCache = /* @__PURE__ */ new WeakMap(), selectorContextCache.set(currentState, instanceCache));
322
- let selectorContext = instanceCache.get(instance);
323
- return selectorContext || (selectorContext = { state: currentState, instance }, instanceCache.set(instance, selectorContext)), selector(selectorContext, ...params);
324
- };
325
- let values = state.observable.pipe(map(getCurrent), distinctUntilChanged(isEqual));
326
- subscribeHandler && (values = withSubscribeHook(values, () => subscribeHandler(context, ...params)));
327
- const sharedValues = values.pipe(shareReplay({ bufferSize: 1, refCount: !0 }));
328
- return {
329
- getCurrent: () => getCurrent(state.get()),
330
- subscribe: (onStoreChanged) => {
331
- const subscription = sharedValues.pipe(skip(1)).subscribe({
332
- next: () => onStoreChanged?.(),
333
- // Propagate selector errors to both subscription types
334
- error: () => onStoreChanged?.()
335
- });
336
- return () => {
337
- subscription.unsubscribe();
338
- };
339
- },
340
- observable: sharedValues
341
- };
342
- }
343
- return stateSourceAction;
344
- }
345
- function withSubscribeHook(obs, fn) {
346
- return defer(() => {
347
- const cleanup = fn();
348
- return cleanup ? obs.pipe(finalize(() => cleanup())) : obs;
349
- });
350
- }
351
- function getStagingApiHost() {
352
- if (typeof __SANITY_STAGING__ < "u" && __SANITY_STAGING__ === !0)
353
- return "https://api.sanity.work";
354
- }
355
- const loggers = /* @__PURE__ */ new WeakMap();
356
- function getAuthLogger(instance) {
357
- let logger = loggers.get(instance);
358
- return logger || (logger = createLogger("auth", {
359
- instanceContext: {
360
- instanceId: instance.instanceId,
361
- projectId: instance.config.projectId,
362
- dataset: instance.config.dataset
363
- }
364
- }), loggers.set(instance, logger)), logger;
365
- }
366
- const REFRESH_INTERVAL = 720 * 60 * 1e3;
367
- function createTokenRefreshStream(token, clientFactory, apiHost) {
368
- return new Observable((subscriber) => {
369
- const subscription = clientFactory({
370
- apiVersion: DEFAULT_API_VERSION$1,
371
- requestTagPrefix: REQUEST_TAG_PREFIX,
372
- useProjectHostname: !1,
373
- useCdn: !1,
374
- token,
375
- ignoreBrowserTokenWarning: !0,
376
- ...apiHost && { apiHost }
377
- }).observable.request({
378
- uri: "auth/refresh-token",
379
- method: "POST",
380
- tag: "refresh-token",
381
- body: {
382
- token
383
- }
384
- }).subscribe(subscriber);
385
- return () => subscription.unsubscribe();
386
- });
387
- }
388
- function shouldRefreshToken(lastRefresh) {
389
- return lastRefresh ? Date.now() - lastRefresh >= REFRESH_INTERVAL : !0;
390
- }
391
- const refreshStampedToken = ({
392
- state,
393
- instance
394
- }) => {
395
- const logger = getAuthLogger(instance), { clientFactory, apiHost, storageArea, storageKey } = state.get().options;
396
- return state.observable.pipe(
397
- map((storeState) => storeState.authState),
398
- filter(
399
- (authState) => authState.type === AuthStateType.LOGGED_IN
400
- ),
401
- distinctUntilChanged((prev, curr) => prev.token === curr.token),
402
- filter((authState) => authState.token.includes("-st")),
403
- // Ensure we only try to refresh stamped tokens
404
- exhaustMap(
405
- () => new Observable((subscriber) => {
406
- const visibilityHandler = () => {
407
- const currentState = state.get();
408
- document.visibilityState === "visible" && currentState.authState.type === AuthStateType.LOGGED_IN && shouldRefreshToken(currentState.authState.lastTokenRefresh) && createTokenRefreshStream(
409
- currentState.authState.token,
410
- clientFactory,
411
- apiHost
412
- ).subscribe({
413
- next: (response) => {
414
- state.set("setRefreshStampedToken", (prev) => ({
415
- authState: prev.authState.type === AuthStateType.LOGGED_IN ? {
416
- ...prev.authState,
417
- token: response.token,
418
- lastTokenRefresh: Date.now()
419
- } : prev.authState
420
- })), subscriber.next(response);
421
- },
422
- error: (error) => subscriber.error(error)
423
- });
424
- }, timerSubscription = timer(REFRESH_INTERVAL, REFRESH_INTERVAL).pipe(
425
- filter(() => document.visibilityState === "visible"),
426
- switchMap(() => {
427
- const currentState = state.get().authState;
428
- if (currentState.type !== AuthStateType.LOGGED_IN)
429
- throw new Error("User logged out before refresh could complete");
430
- return createTokenRefreshStream(currentState.token, clientFactory, apiHost);
431
- })
432
- ).subscribe({
433
- next: (response) => {
434
- state.set("setRefreshStampedToken", (prev) => ({
435
- authState: prev.authState.type === AuthStateType.LOGGED_IN ? {
436
- ...prev.authState,
437
- token: response.token,
438
- lastTokenRefresh: Date.now()
439
- } : prev.authState
440
- })), subscriber.next(response);
441
- },
442
- error: (error) => subscriber.error(error)
443
- });
444
- return document.addEventListener("visibilitychange", visibilityHandler), () => {
445
- document.removeEventListener("visibilitychange", visibilityHandler), timerSubscription.unsubscribe();
446
- };
447
- }).pipe(
448
- takeWhile(() => state.get().authState.type === AuthStateType.LOGGED_IN),
449
- map((response) => ({ token: response.token }))
450
- )
451
- )
452
- ).subscribe({
453
- next: (response) => {
454
- logger.debug("Token refresh completed, updating state"), state.set("setRefreshStampedToken", (prev) => ({
455
- authState: prev.authState.type === AuthStateType.LOGGED_IN ? {
456
- ...prev.authState,
457
- token: response.token,
458
- lastTokenRefresh: Date.now()
459
- } : prev.authState
460
- })), storageArea?.setItem(storageKey, JSON.stringify({ token: response.token }));
461
- },
462
- error: (error) => {
463
- logger.error("Token refresh failed", { error }), state.set("setRefreshStampedTokenError", { authState: { type: AuthStateType.ERROR, error } });
464
- }
465
- });
466
- }, subscribeToStateAndFetchCurrentUser = ({ state, instance }, fetchOptions) => {
467
- const logger = getAuthLogger(instance), { clientFactory, apiHost } = state.get().options, useProjectHostname = fetchOptions?.useProjectHostname ?? isStudioConfig(instance.config), projectId = instance.config.projectId;
468
- return state.observable.pipe(
469
- map(({ authState, options: storeOptions }) => ({
470
- authState,
471
- authMethod: storeOptions.authMethod
472
- })),
473
- filter(
474
- (value) => value.authState.type === AuthStateType.LOGGED_IN && !value.authState.currentUser
475
- ),
476
- map((value) => ({ token: value.authState.token, authMethod: value.authMethod })),
477
- distinctUntilChanged(
478
- (prev, curr) => prev.token === curr.token && prev.authMethod === curr.authMethod
479
- )
480
- ).pipe(
481
- map(
482
- ({ token, authMethod }) => clientFactory({
483
- apiVersion: DEFAULT_API_VERSION$1,
484
- requestTagPrefix: REQUEST_TAG_PREFIX,
485
- token: authMethod === "cookie" ? void 0 : token,
486
- ignoreBrowserTokenWarning: !0,
487
- useProjectHostname,
488
- useCdn: !1,
489
- ...authMethod === "cookie" ? { withCredentials: !0 } : {},
490
- ...useProjectHostname && projectId ? { projectId } : {},
491
- ...apiHost && { apiHost }
492
- })
493
- ),
494
- switchMap(
495
- (client) => client.observable.request({
496
- uri: "/users/me",
497
- method: "GET",
498
- tag: "users.get-current"
499
- }).pipe(
500
- /**
501
- * Catch inside switchMap so the outer subscription survives.
502
- * Without this, a 401 terminates the subscription permanently
503
- * and subsequent token refreshes via comlink never re-fetch /users/me.
504
- * @see SDK-1409
505
- */
506
- catchError((error) => (logger.error("Failed to fetch current user", { error }), state.set("setError", { authState: { type: AuthStateType.ERROR, error } }), EMPTY))
507
- )
508
- )
509
- ).subscribe({
510
- next: (currentUser) => {
511
- logger.info("Current user fetched successfully", {
512
- hasEmail: !!currentUser.email
513
- }), logger.debug("Current user details", { userId: currentUser.id }), state.set("setCurrentUser", (prev) => ({
514
- authState: prev.authState.type === AuthStateType.LOGGED_IN ? { ...prev.authState, currentUser } : prev.authState
515
- }));
516
- }
517
- });
518
- };
519
- function parseDashboardContext(locationHref) {
520
- try {
521
- const contextParam = new URL(locationHref, DEFAULT_BASE).searchParams.get("_context");
522
- if (contextParam) {
523
- const parsedContext = JSON.parse(contextParam);
524
- if (parsedContext && typeof parsedContext == "object" && !Array.isArray(parsedContext) && Object.keys(parsedContext).length > 0)
525
- return delete parsedContext.sid, parsedContext;
526
- }
527
- } catch (err) {
528
- console.error("Failed to parse dashboard context from initial location:", err);
529
- }
530
- return {};
531
- }
532
- function getDashboardInitialState(options) {
533
- const { authConfig, initialLocationHref } = options, providedToken = authConfig.token, callbackUrl = authConfig.callbackUrl, storageKey = "__sanity_auth_token", dashboardContext = parseDashboardContext(initialLocationHref), storageArea = void 0;
534
- return providedToken ? {
535
- authState: createLoggedInAuthState(providedToken, null),
536
- storageKey,
537
- storageArea,
538
- authMethod: void 0,
539
- dashboardContext
540
- } : getAuthCode(callbackUrl, initialLocationHref) || getTokenFromLocation(initialLocationHref) ? {
541
- authState: { type: AuthStateType.LOGGING_IN, isExchangingToken: !1 },
542
- storageKey,
543
- storageArea,
544
- authMethod: void 0,
545
- dashboardContext
546
- } : {
547
- authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 },
548
- storageKey,
549
- storageArea,
550
- authMethod: void 0,
551
- dashboardContext
552
- };
553
- }
554
- function initializeDashboardAuth(context, tokenRefresherRunning2) {
555
- const subscriptions = [];
556
- let startedRefresher = !1;
557
- return subscriptions.push(subscribeToStateAndFetchCurrentUser(context, { useProjectHostname: !1 })), tokenRefresherRunning2 || (startedRefresher = !0, subscriptions.push(refreshStampedToken(context))), {
558
- dispose: () => {
559
- for (const subscription of subscriptions)
560
- subscription.unsubscribe();
561
- },
562
- tokenRefresherStarted: startedRefresher
563
- };
564
- }
565
- const subscribeToStorageEventsAndSetToken = ({
566
- state
567
- }) => {
568
- const { storageArea, storageKey } = state.get().options;
569
- return defer(getStorageEvents).pipe(
570
- filter(
571
- (e) => e.storageArea === storageArea && e.key === storageKey
572
- ),
573
- map(() => getTokenFromStorage(storageArea, storageKey)),
574
- distinctUntilChanged()
575
- ).subscribe((token) => {
576
- state.set("updateTokenFromStorageEvent", {
577
- authState: token ? createLoggedInAuthState(token, null) : { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }
578
- });
579
- });
580
- };
581
- function getStandaloneInitialState(options) {
582
- const { authConfig, initialLocationHref } = options, providedToken = authConfig.token, callbackUrl = authConfig.callbackUrl, storageKey = "__sanity_auth_token", storageArea = authConfig.storageArea ?? getDefaultStorage();
583
- if (providedToken)
584
- return {
585
- authState: createLoggedInAuthState(providedToken, null),
586
- storageKey,
587
- storageArea,
588
- authMethod: void 0,
589
- dashboardContext: {}
590
- };
591
- if (getAuthCode(callbackUrl, initialLocationHref) || getTokenFromLocation(initialLocationHref))
592
- return {
593
- authState: { type: AuthStateType.LOGGING_IN, isExchangingToken: !1 },
594
- storageKey,
595
- storageArea,
596
- authMethod: void 0,
597
- dashboardContext: {}
598
- };
599
- const token = getTokenFromStorage(storageArea, storageKey);
600
- return token ? {
601
- authState: createLoggedInAuthState(token, null),
602
- storageKey,
603
- storageArea,
604
- authMethod: "localstorage",
605
- dashboardContext: {}
606
- } : {
607
- authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 },
608
- storageKey,
609
- storageArea,
610
- authMethod: void 0,
611
- dashboardContext: {}
612
- };
613
- }
614
- function initializeStandaloneAuth(context, tokenRefresherRunning2) {
615
- const subscriptions = [];
616
- let startedRefresher = !1;
617
- return subscriptions.push(subscribeToStateAndFetchCurrentUser(context, { useProjectHostname: !1 })), context.state.get().options?.storageArea && subscriptions.push(subscribeToStorageEventsAndSetToken(context)), tokenRefresherRunning2 || (startedRefresher = !0, subscriptions.push(refreshStampedToken(context))), {
618
- dispose: () => {
619
- for (const subscription of subscriptions)
620
- subscription.unsubscribe();
621
- },
622
- tokenRefresherStarted: startedRefresher
623
- };
624
- }
625
- const COOKIE_AUTH_TIMEOUT_MS = 1e4;
626
- async function checkForCookieAuth(projectId, clientFactory) {
627
- if (!projectId) return !1;
628
- try {
629
- const user = await clientFactory({
630
- projectId,
631
- useCdn: !1,
632
- requestTagPrefix: REQUEST_TAG_PREFIX,
633
- timeout: COOKIE_AUTH_TIMEOUT_MS
634
- }).request({
635
- uri: "/users/me",
636
- withCredentials: !0,
637
- tag: "users.get-current"
638
- });
639
- return user != null && typeof user == "object" && typeof user.id == "string";
640
- } catch {
641
- return !1;
642
- }
643
- }
644
- function getStudioTokenFromLocalStorage(storageArea, storageKey) {
645
- return !storageArea || !storageKey ? null : getTokenFromStorage(storageArea, storageKey) || null;
646
- }
647
- function getStudioInitialState(options) {
648
- const { authConfig, projectId, tokenSource } = options, storageArea = authConfig.storageArea ?? getDefaultStorage(), studioStorageKey = `__studio_auth_token_${projectId ?? ""}`;
649
- if (tokenSource)
650
- return {
651
- authState: { type: AuthStateType.LOGGING_IN, isExchangingToken: !1 },
652
- storageKey: studioStorageKey,
653
- storageArea,
654
- authMethod: void 0,
655
- dashboardContext: {}
656
- };
657
- const providedToken = authConfig.token;
658
- let authMethod;
659
- const token = getStudioTokenFromLocalStorage(storageArea, studioStorageKey);
660
- return token && (authMethod = "localstorage"), providedToken ? {
661
- authState: createLoggedInAuthState(providedToken, null),
662
- storageKey: studioStorageKey,
663
- storageArea,
664
- authMethod,
665
- dashboardContext: {}
666
- } : token ? {
667
- authState: createLoggedInAuthState(token, null),
668
- storageKey: studioStorageKey,
669
- storageArea,
670
- authMethod: "localstorage",
671
- dashboardContext: {}
672
- } : {
673
- authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 },
674
- storageKey: studioStorageKey,
675
- storageArea,
676
- authMethod: void 0,
677
- dashboardContext: {}
678
- };
679
- }
680
- function initializeStudioAuth(context, tokenRefresherRunning2) {
681
- const tokenSource = context.instance.config.studio?.auth?.token;
682
- return tokenSource ? initializeWithTokenSource(context, tokenSource) : initializeWithFallback(context, tokenRefresherRunning2);
683
- }
684
- function initializeWithTokenSource(context, tokenSource) {
685
- const subscriptions = [], studioAuthenticated = context.instance.config.studio?.authenticated === !0;
686
- subscriptions.push(subscribeToStateAndFetchCurrentUser(context, { useProjectHostname: !0 }));
687
- const tokenSub = tokenSource.subscribe({
688
- next: (token) => {
689
- const { state } = context;
690
- token ? state.set("studioTokenSource", (prev) => ({
691
- options: { ...prev.options, authMethod: void 0 },
692
- authState: createLoggedInAuthState(token, null)
693
- })) : studioAuthenticated ? state.set("studioTokenSourceCookieAuth", (prev) => ({
694
- options: { ...prev.options, authMethod: "cookie" },
695
- authState: prev.authState.type === AuthStateType.LOGGED_IN ? prev.authState : createLoggedInAuthState("", null)
696
- })) : state.set("studioTokenSourceLoggedOut", (prev) => ({
697
- options: { ...prev.options, authMethod: void 0 },
698
- authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }
699
- }));
700
- }
701
- });
702
- return {
703
- dispose: () => {
704
- tokenSub.unsubscribe();
705
- for (const subscription of subscriptions)
706
- subscription.unsubscribe();
707
- },
708
- // Studio handles token refresh — do not start the SDK's refresher
709
- tokenRefresherStarted: !1
710
- };
711
- }
712
- function initializeWithFallback(context, tokenRefresherRunning2) {
713
- const subscriptions = [];
714
- let startedRefresher = !1;
715
- subscriptions.push(subscribeToStateAndFetchCurrentUser(context, { useProjectHostname: !0 })), context.state.get().options?.storageArea && subscriptions.push(subscribeToStorageEventsAndSetToken(context));
716
- try {
717
- const { instance, state } = context;
718
- if (!(state.get().authState?.type === AuthStateType.LOGGED_IN && state.get().authState.token)) {
719
- const projectIdValue = instance.config.projectId, clientFactory = state.get().options.clientFactory;
720
- checkForCookieAuth(projectIdValue, clientFactory).then((isCookieAuthEnabled) => {
721
- isCookieAuthEnabled && state.set("enableCookieAuth", (prev) => ({
722
- options: { ...prev.options, authMethod: "cookie" },
723
- authState: prev.authState.type === AuthStateType.LOGGED_IN ? prev.authState : createLoggedInAuthState("", null)
724
- }));
725
- });
726
- }
727
- } catch {
728
- }
729
- return tokenRefresherRunning2 || (startedRefresher = !0, subscriptions.push(refreshStampedToken(context))), {
730
- dispose: () => {
731
- for (const subscription of subscriptions)
732
- subscription.unsubscribe();
733
- },
734
- tokenRefresherStarted: startedRefresher
735
- };
736
- }
737
- let tokenRefresherRunning = !1;
738
- const authStore = {
739
- name: "Auth",
740
- getInitialState(instance) {
741
- const logger = getAuthLogger(instance);
742
- logger.debug("Initializing auth store", {
743
- hasProvidedToken: !!instance.config.auth?.token,
744
- hasCustomProviders: !!(instance.config.auth?.providers && instance.config.auth.providers.length > 0),
745
- studioMode: instance.config.studioMode?.enabled ?? !1
746
- });
747
- const {
748
- apiHost: configApiHost,
749
- callbackUrl,
750
- providers: customProviders,
751
- token: providedToken,
752
- clientFactory = createClient,
753
- initialLocationHref = getDefaultLocation()
754
- } = instance.config.auth ?? {}, apiHost = configApiHost ?? getStagingApiHost(), authConfig = instance.config.auth ?? {};
755
- let loginDomain = "https://www.sanity.io";
756
- try {
757
- apiHost && new URL(apiHost).hostname.endsWith(".sanity.work") && (loginDomain = "https://www.sanity.work");
758
- } catch {
759
- }
760
- const loginUrl = new URL("/login", loginDomain);
761
- loginUrl.searchParams.set("origin", getCleanedUrl(initialLocationHref)), loginUrl.searchParams.set("type", "stampedToken"), loginUrl.searchParams.set("withSid", "true");
762
- const mode = resolveAuthMode(instance.config, initialLocationHref), strategyOptions = {
763
- authConfig,
764
- projectId: instance.config.projectId,
765
- initialLocationHref,
766
- tokenSource: instance.config.studio?.auth?.token
767
- };
768
- let result;
769
- switch (mode) {
770
- case "studio":
771
- result = getStudioInitialState(strategyOptions);
772
- break;
773
- case "dashboard":
774
- result = getDashboardInitialState(strategyOptions);
775
- break;
776
- case "standalone":
777
- result = getStandaloneInitialState(strategyOptions);
778
- break;
779
- }
780
- return logger.debug("Auth state initialized", {
781
- authStateType: result.authState.type,
782
- mode,
783
- authMethod: result.authMethod
784
- }), {
785
- authState: result.authState,
786
- dashboardContext: result.dashboardContext,
787
- options: {
788
- apiHost,
789
- loginUrl: loginUrl.toString(),
790
- callbackUrl,
791
- customProviders,
792
- providedToken,
793
- clientFactory,
794
- initialLocationHref,
795
- storageKey: result.storageKey,
796
- storageArea: result.storageArea,
797
- authMethod: result.authMethod
798
- }
799
- };
800
- },
801
- initialize(context) {
802
- const logger = getAuthLogger(context.instance), initialLocationHref = context.state.get().options?.initialLocationHref ?? getDefaultLocation(), mode = resolveAuthMode(context.instance.config, initialLocationHref);
803
- logger.debug("Setting up auth subscriptions", { mode });
804
- let initResult;
805
- switch (mode) {
806
- case "studio":
807
- initResult = initializeStudioAuth(context, tokenRefresherRunning);
808
- break;
809
- case "dashboard":
810
- initResult = initializeDashboardAuth(context, tokenRefresherRunning);
811
- break;
812
- case "standalone":
813
- initResult = initializeStandaloneAuth(context, tokenRefresherRunning);
814
- break;
815
- }
816
- return initResult.tokenRefresherStarted && (tokenRefresherRunning = !0), () => {
817
- logger.debug("Cleaning up auth subscriptions"), initResult.dispose();
818
- };
819
- }
820
- }, getCurrentUserState = bindActionGlobally(
821
- authStore,
822
- createStateSourceAction(
823
- ({ state: { authState } }) => authState.type === AuthStateType.LOGGED_IN ? authState.currentUser : null
824
- )
825
- ), getTokenState = bindActionGlobally(
826
- authStore,
827
- createStateSourceAction(
828
- ({ state: { authState } }) => authState.type === AuthStateType.LOGGED_IN ? authState.token : null
829
- )
830
- ), getAuthMethodState = bindActionGlobally(
831
- authStore,
832
- createStateSourceAction(({ state: { options } }) => options.authMethod)
833
- ), getLoginUrlState = bindActionGlobally(
834
- authStore,
835
- createStateSourceAction(({ state: { options } }) => options.loginUrl)
836
- ), getAuthState = bindActionGlobally(
837
- authStore,
838
- createStateSourceAction(({ state: { authState } }) => authState)
839
- ), getDashboardOrganizationId = bindActionGlobally(
840
- authStore,
841
- createStateSourceAction(({ state: { dashboardContext } }) => dashboardContext?.orgId)
842
- ), getIsInDashboardState = bindActionGlobally(
843
- authStore,
844
- createStateSourceAction(
845
- ({ state: { dashboardContext } }) => (
846
- // Check if dashboardContext exists and is not empty
847
- !!dashboardContext && Object.keys(dashboardContext).length > 0
848
- )
849
- )
850
- ), setAuthToken = bindActionGlobally(
851
- authStore,
852
- ({ state, instance }, token) => {
853
- const logger = getAuthLogger(instance), currentAuthState = state.get().authState;
854
- if (token) {
855
- if (currentAuthState.type !== AuthStateType.LOGGED_IN || currentAuthState.token !== token) {
856
- logger.info("Setting auth token");
857
- const currentUser = currentAuthState.type === AuthStateType.LOGGED_IN ? currentAuthState.currentUser : null, preservedLastTokenRefresh = currentAuthState.type === AuthStateType.LOGGED_IN ? currentAuthState.lastTokenRefresh : void 0;
858
- state.set("setToken", {
859
- authState: createLoggedInAuthState(token, currentUser, preservedLastTokenRefresh)
860
- });
861
- }
862
- } else
863
- currentAuthState.type !== AuthStateType.LOGGED_OUT && (logger.info("Clearing auth token"), state.set("setToken", {
864
- authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }
865
- }));
866
- }
867
- );
868
- var authStore$1 = /* @__PURE__ */ Object.freeze({
869
- __proto__: null,
870
- authStore,
871
- getAuthMethodState,
872
- getAuthState,
873
- getCurrentUserState,
874
- getDashboardOrganizationId,
875
- getIsInDashboardState,
876
- getLoginUrlState,
877
- getTokenState,
878
- setAuthToken
879
- });
880
- function createLoggedInAuthState(token, currentUser, existingLastTokenRefresh) {
881
- const isStampedToken = token.includes("-st"), lastTokenRefresh = existingLastTokenRefresh ?? (isStampedToken ? Date.now() : void 0);
882
- return {
883
- type: AuthStateType.LOGGED_IN,
884
- token,
885
- currentUser,
886
- ...lastTokenRefresh !== void 0 && { lastTokenRefresh }
887
- };
888
- }
889
- function getAuthCode(callbackUrl, locationHref) {
890
- 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;
891
- let authCode = new URLSearchParams(loc.hash.slice(1)).get(AUTH_CODE_PARAM) || new URLSearchParams(loc.search).get(AUTH_CODE_PARAM);
892
- if (!authCode) {
893
- const contextParam = new URLSearchParams(loc.search).get("_context");
894
- if (contextParam)
895
- try {
896
- const parsedContext = JSON.parse(contextParam);
897
- parsedContext && typeof parsedContext == "object" && typeof parsedContext.sid == "string" && parsedContext.sid && (authCode = parsedContext.sid);
898
- } catch {
899
- }
900
- }
901
- return authCode && callbackLocationMatches ? authCode : null;
902
- }
903
- function getTokenFromLocation(locationHref) {
904
- const loc = new URL(locationHref);
905
- return new URLSearchParams(loc.hash.slice(1)).get("token") || null;
906
- }
907
- function getTokenFromStorage(storageArea, storageKey) {
908
- if (!storageArea) return null;
909
- const item = storageArea.getItem(storageKey);
910
- if (item === null) return null;
911
- try {
912
- const parsed = JSON.parse(item);
913
- if (typeof parsed != "object" || parsed === null || !("token" in parsed) || typeof parsed.token != "string")
914
- throw new Error("Invalid stored auth data structure");
915
- return parsed.token;
916
- } catch {
917
- return storageArea.removeItem(storageKey), null;
918
- }
919
- }
920
- function getStorageEvents() {
921
- return typeof window < "u" && typeof window.addEventListener == "function" ? fromEvent(window, "storage") : EMPTY;
922
- }
923
- function getDefaultStorage() {
924
- try {
925
- return typeof localStorage < "u" && typeof localStorage.getItem == "function" ? localStorage : void 0;
926
- } catch {
927
- return;
928
- }
929
- }
930
- function getDefaultLocation() {
931
- try {
932
- return typeof location > "u" ? DEFAULT_BASE : typeof location.href == "string" ? location.href : DEFAULT_BASE;
933
- } catch {
934
- return DEFAULT_BASE;
935
- }
936
- }
937
- function getCleanedUrl(locationUrl) {
938
- const loc = new URL(locationUrl), rawHash = loc.hash.startsWith("#") ? loc.hash.slice(1) : loc.hash;
939
- if (rawHash && rawHash.includes("=")) {
940
- const hashParams = new URLSearchParams(rawHash);
941
- hashParams.delete("token"), hashParams.delete("withSid");
942
- const nextHash = hashParams.toString();
943
- loc.hash = nextHash ? `#${nextHash}` : "";
944
- }
945
- return loc.searchParams.delete("sid"), loc.searchParams.delete("url"), loc.toString();
946
- }
947
- function getClientErrorApiBody(error) {
948
- const body = error.response?.body;
949
- return body && typeof body == "object" ? body : void 0;
950
- }
951
- function getClientErrorApiType(error) {
952
- const body = getClientErrorApiBody(error);
953
- return body?.error?.type ?? body?.type;
954
- }
955
- function getClientErrorApiDescription(error) {
956
- const body = getClientErrorApiBody(error);
957
- return body?.error?.description ?? body?.description;
958
- }
959
- function isProjectUserNotFoundClientError(error) {
960
- return getClientErrorApiType(error) === "projectUserNotFoundError";
961
- }
962
- const TITLE_CANDIDATES = ["title", "name", "label", "heading", "header", "caption"], SUBTITLE_CANDIDATES = ["description", "subtitle", ...TITLE_CANDIDATES], PREVIEW_PROJECTION = `{
963
- // Get all potential title fields
964
- "titleCandidates": {
965
- ${TITLE_CANDIDATES.map((field) => `"${field}": ${field}`).join(`,
966
- `)}
967
- },
968
- // Get all potential subtitle fields
969
- "subtitleCandidates": {
970
- ${SUBTITLE_CANDIDATES.map((field) => `"${field}": ${field}`).join(`,
971
- `)}
972
- },
973
- "media": coalesce(
974
- select(
975
- defined(asset) => {"type": "image-asset", "_ref": asset._ref},
976
- defined(image.asset) => {"type": "image-asset", "_ref": image.asset._ref},
977
- defined(mainImage.asset) => {"type": "image-asset", "_ref": mainImage.asset._ref},
978
- null
979
- )
980
- ),
981
- _type,
982
- _id,
983
- _updatedAt
984
- }`, DEFAULT_API_VERSION = "2024-11-12", DEFAULT_REQUEST_TAG_PREFIX = "sanity.sdk", allowedKeys = Object.keys({
985
- apiHost: null,
986
- useCdn: null,
987
- token: null,
988
- perspective: null,
989
- proxy: null,
990
- withCredentials: null,
991
- timeout: null,
992
- maxRetries: null,
993
- dataset: null,
994
- projectId: null,
995
- scope: null,
996
- apiVersion: null,
997
- requestTagPrefix: null,
998
- useProjectHostname: null,
999
- resource: null
1000
- }), DEFAULT_CLIENT_CONFIG = {
1001
- apiVersion: DEFAULT_API_VERSION,
1002
- useCdn: !1,
1003
- ignoreBrowserTokenWarning: !0,
1004
- allowReconfigure: !1,
1005
- requestTagPrefix: DEFAULT_REQUEST_TAG_PREFIX
1006
- }, clientStore = {
1007
- name: "clientStore",
1008
- getInitialState: (instance) => ({
1009
- clients: {},
1010
- token: getTokenState(instance).getCurrent()
1011
- }),
1012
- initialize(context) {
1013
- const subscription = listenToToken(context), authMethodSubscription = listenToAuthMethod(context);
1014
- return () => {
1015
- subscription.unsubscribe(), authMethodSubscription.unsubscribe();
1016
- };
1017
- }
1018
- }, listenToToken = ({ instance, state }) => getTokenState(instance).observable.subscribe((token) => {
1019
- state.set("setTokenAndResetClients", { token, clients: {} });
1020
- }), listenToAuthMethod = ({ instance, state }) => getAuthMethodState(instance).observable.subscribe((authMethod) => {
1021
- state.set("setAuthMethod", { authMethod });
1022
- }), getClientConfigKey = (options) => JSON.stringify(pickProperties(options, allowedKeys)), getClient = bindActionGlobally(
1023
- clientStore,
1024
- ({ state, instance }, options) => {
1025
- if (!options || typeof options != "object")
1026
- throw new Error(
1027
- 'getClient() requires a configuration object with at least an "apiVersion" property. Example: getClient(instance, { apiVersion: "2024-11-12" })'
1028
- );
1029
- const disallowedKeys = Object.keys(options).filter((key2) => !allowedKeys.includes(key2));
1030
- if (disallowedKeys.length > 0) {
1031
- const listFormatter = new Intl.ListFormat("en", { style: "long", type: "conjunction" });
1032
- throw new Error(
1033
- `The client options provided contains unsupported properties: ${listFormatter.format(disallowedKeys)}. Allowed keys are: ${listFormatter.format(allowedKeys)}.`
1034
- );
1035
- }
1036
- const tokenFromState = state.get().token, { clients, authMethod } = state.get();
1037
- let projectId = options.projectId ?? instance.config.projectId, dataset = options.dataset ?? instance.config.dataset, resource;
1038
- options.resource && (isMediaLibraryResource(options.resource) ? resource = { type: "media-library", id: options.resource.mediaLibraryId } : isCanvasResource(options.resource) ? resource = { type: "canvas", id: options.resource.canvasId } : isDatasetResource(options.resource) && (projectId = options.resource.projectId, dataset = options.resource.dataset));
1039
- const apiHost = options.apiHost ?? instance.config.auth?.apiHost ?? getStagingApiHost(), effectiveOptions = {
1040
- ...DEFAULT_CLIENT_CONFIG,
1041
- ...(options.scope === "global" || !projectId || resource) && { useProjectHostname: !1 },
1042
- token: authMethod === "cookie" ? void 0 : tokenFromState ?? void 0,
1043
- ...options,
1044
- ...projectId && { projectId },
1045
- ...dataset && { dataset },
1046
- ...resource ? { resource } : { resource: void 0 },
1047
- ...apiHost && { apiHost }
1048
- };
1049
- resource && (delete effectiveOptions.projectId, delete effectiveOptions.dataset), effectiveOptions.token === null || typeof effectiveOptions.token > "u" ? (delete effectiveOptions.token, authMethod === "cookie" && (effectiveOptions.withCredentials = !0)) : delete effectiveOptions.withCredentials;
1050
- const key = getClientConfigKey(effectiveOptions);
1051
- if (clients[key]) return clients[key];
1052
- const client = createClient(effectiveOptions);
1053
- return state.set("addClient", (prev) => ({ clients: { ...prev.clients, [key]: client } })), client;
1054
- }
1055
- ), getClientState = bindActionGlobally(
1056
- clientStore,
1057
- createStateSourceAction(({ instance }, options) => getClient(instance, options))
1058
- );
1059
- var clientStore$1 = /* @__PURE__ */ Object.freeze({
1060
- __proto__: null,
1061
- getClient,
1062
- getClientState
1063
- });
1064
- const API_VERSION$1 = "v2025-05-06";
1065
- function hasImageRef(value) {
1066
- return isObject(value) && "_ref" in value && typeof value._ref == "string";
1067
- }
1068
- function normalizeMedia(media, client) {
1069
- if (!media || !hasImageRef(media)) return null;
1070
- const url = createImageUrlBuilder(client).image({ _ref: media._ref }).url();
1071
- return {
1072
- type: "image-asset",
1073
- _ref: media._ref,
1074
- url
1075
- };
1076
- }
1077
- function findFirstDefined(fieldsToSearch, candidates, exclude) {
1078
- if (candidates)
1079
- for (const field of fieldsToSearch) {
1080
- const value = candidates[field];
1081
- if (typeof value == "string" && value.trim() !== "" && value !== exclude)
1082
- return value;
1083
- }
1084
- }
1085
- function transformProjectionToPreview(instance, projectionResult, resource) {
1086
- const title = findFirstDefined(TITLE_CANDIDATES, projectionResult.titleCandidates), subtitle = findFirstDefined(SUBTITLE_CANDIDATES, projectionResult.subtitleCandidates, title), client = getClient(instance, {
1087
- apiVersion: API_VERSION$1,
1088
- resource
1089
- });
1090
- return {
1091
- title: String(title || `${projectionResult._type}: ${projectionResult._id}`),
1092
- subtitle: subtitle || void 0,
1093
- media: normalizeMedia(projectionResult.media, client),
1094
- ...projectionResult._status && { _status: projectionResult._status }
1095
- };
1096
- }
1097
- const LIVE_EVENTS_API_VERSION = "v2025-05-06", LIVE_EVENTS_RETRY_DELAY = 1e3;
1098
- function observeLiveEvents(instance, { resource, onCorsError }) {
1099
- return getClientState(instance, {
1100
- apiVersion: LIVE_EVENTS_API_VERSION,
1101
- resource
1102
- }).observable.pipe(
1103
- switchMap(
1104
- (client) => defer(
1105
- () => client.live.events({ includeDrafts: !!client.config().token, tag: "live-events" })
1106
- ).pipe(
1107
- catchError((error) => {
1108
- if (error instanceof CorsOriginError)
1109
- return onCorsError(error), EMPTY;
1110
- if (error instanceof DisconnectError)
1111
- return EMPTY;
1112
- if (error instanceof ConnectionFailedError && typeof error.status == "number" && error.status >= 400 && error.status < 500)
1113
- return EMPTY;
1114
- throw error;
1115
- }),
1116
- // Server-initiated live errors (e.g. ChannelError, MessageError) are
1117
- // retried, not surfaced. Dropped connections are already reconnected
1118
- // inside @sanity/client.
1119
- retry({ delay: LIVE_EVENTS_RETRY_DELAY })
1120
- )
1121
- ),
1122
- filter((e) => e.type === "message")
1123
- );
1124
- }
1125
- const RELEASES_QUERY = "releases::all()", RELEASES_API_VERSION = "v2025-05-06";
1126
- function observeReleases(instance, { resource, onCorsError }) {
1127
- return getClientState(instance, {
1128
- apiVersion: RELEASES_API_VERSION,
1129
- resource
1130
- }).observable.pipe(
1131
- switchMap((client) => {
1132
- const syncTags$ = new BehaviorSubject(void 0);
1133
- return combineLatest([
1134
- observeLiveEvents(instance, { resource, onCorsError }).pipe(startWith(void 0)),
1135
- syncTags$
1136
- ]).pipe(
1137
- filter(
1138
- ([message, syncTags]) => message === void 0 || message.tags.some((tag) => syncTags?.includes(tag))
1139
- ),
1140
- map(([message]) => message?.id),
1141
- distinctUntilChanged()
1142
- ).pipe(
1143
- switchMap(
1144
- (lastLiveEventId) => client.observable.fetch(
1145
- RELEASES_QUERY,
1146
- {},
1147
- {
1148
- perspective: "raw",
1149
- filterResponse: !1,
1150
- returnQuery: !1,
1151
- lastLiveEventId,
1152
- tag: "releases"
1153
- }
1154
- )
1155
- ),
1156
- tap((response) => {
1157
- syncTags$.next(response.syncTags);
1158
- }),
1159
- map((response) => response.result)
1160
- );
1161
- }),
1162
- // Emit synchronously on subscribe (mirroring StateSource semantics, which
1163
- // the releases store previously consumed) so the store can immediately
1164
- // record an empty list: consumers distinguish "no releases yet" from
1165
- // "never loaded", and the React hooks don't suspend on first load.
1166
- startWith(void 0)
1167
- );
1168
- }
1169
- function sortReleases(releases = []) {
1170
- return [...releases].sort((a, b) => {
1171
- const aType = a.metadata?.releaseType, bType = b.metadata?.releaseType;
1172
- if (aType === "undecided" && bType !== "undecided")
1173
- return -1;
1174
- if (aType !== "undecided" && bType === "undecided")
1175
- return 1;
1176
- if (aType === "undecided" && bType === "undecided")
1177
- return new Date(b._createdAt).getTime() - new Date(a._createdAt).getTime();
1178
- if (aType === "scheduled" && bType === "scheduled") {
1179
- const aPublishAt = a.publishAt || a.metadata?.intendedPublishAt;
1180
- if (!aPublishAt)
1181
- return 1;
1182
- const bPublishAt = b.publishAt || b.metadata?.intendedPublishAt;
1183
- return bPublishAt ? new Date(bPublishAt).getTime() - new Date(aPublishAt).getTime() : -1;
1184
- }
1185
- return aType === "asap" && bType !== "asap" ? 1 : aType !== "asap" && bType === "asap" ? -1 : aType === "asap" && bType === "asap" ? new Date(b._createdAt).getTime() - new Date(a._createdAt).getTime() : 0;
1186
- });
1187
- }
1188
- const ARCHIVED_RELEASE_STATES = ["archived", "published"], STABLE_EMPTY_RELEASES = [], releasesStore = {
1189
- name: "Releases",
1190
- getInitialState: () => ({
1191
- activeReleases: void 0,
1192
- allReleases: void 0
1193
- }),
1194
- initialize: (context) => {
1195
- const subscription = subscribeToReleases(context);
1196
- return () => subscription.unsubscribe();
1197
- }
1198
- }, _getActiveReleasesState = bindActionByResource(
1199
- releasesStore,
1200
- createStateSourceAction({
1201
- selector: ({ state }) => {
1202
- if (state.error) throw state.error;
1203
- return state.activeReleases;
1204
- }
1205
- })
1206
- ), getActiveReleasesState = (instance, options) => (
1207
- // bindActionByResource keyFn destructures { resource } from the first param, so pass {} when no options
1208
- _getActiveReleasesState(instance, options ?? {})
1209
- ), _getAllReleasesState = bindActionByResource(
1210
- releasesStore,
1211
- createStateSourceAction({
1212
- selector: ({ state }) => {
1213
- if (state.error) throw state.error;
1214
- return state.allReleases;
1215
- }
1216
- })
1217
- ), getAllReleasesState = (instance, options) => _getAllReleasesState(instance, options ?? {}), subscribeToReleases = ({
1218
- instance,
1219
- state,
1220
- key: { resource }
1221
- }) => observeReleases(instance, {
1222
- resource,
1223
- // Surface CORS errors as store state instead of erroring the stream so
1224
- // they can be handled by the Cors Error component
1225
- onCorsError: (error) => state.set("setError", { error })
1226
- }).pipe(
1227
- map((releases) => {
1228
- const sorted = sortReleases(releases ?? STABLE_EMPTY_RELEASES).reverse();
1229
- state.set("setReleases", {
1230
- allReleases: sorted,
1231
- activeReleases: sorted.filter(
1232
- (release) => !ARCHIVED_RELEASE_STATES.includes(release.state)
1233
- )
1234
- });
1235
- })
1236
- ).subscribe({ error: (error) => state.set("setError", { error }) }), DEFAULT_PERSPECTIVE = "drafts", optionsCache = /* @__PURE__ */ new Map(), selectInstancePerspective = (context, _) => context.instance.config.perspective, selectActiveReleases = (context) => context.state.activeReleases, selectOptions = (_context, options) => options, memoizedOptionsSelector = createSelector(
1237
- [selectActiveReleases, selectOptions],
1238
- (activeReleases, options) => {
1239
- if (!options || !activeReleases) return options;
1240
- const releaseIds = activeReleases.map((release) => release._id).join(",");
1241
- let nestedCache = optionsCache.get(releaseIds);
1242
- nestedCache || (nestedCache = /* @__PURE__ */ new Map(), optionsCache.set(releaseIds, nestedCache));
1243
- const optionsKey = JSON.stringify(options);
1244
- let cachedOptions = nestedCache.get(optionsKey);
1245
- return cachedOptions || (cachedOptions = options, nestedCache.set(optionsKey, cachedOptions)), cachedOptions;
1246
- }
1247
- ), _getPerspectiveStateSelector = createStateSourceAction({
1248
- selector: createSelector(
1249
- [selectInstancePerspective, selectActiveReleases, memoizedOptionsSelector],
1250
- (instancePerspective, activeReleases, memoizedOptions) => {
1251
- const perspective = memoizedOptions?.perspective ?? instancePerspective ?? DEFAULT_PERSPECTIVE;
1252
- if (!isReleasePerspective(perspective)) return perspective;
1253
- if (!activeReleases || activeReleases.length === 0) return;
1254
- const releaseNames = sortReleases(activeReleases).map((release) => release.name), index = releaseNames.findIndex((name) => name === perspective.releaseName);
1255
- if (index < 0)
1256
- throw new Error(`Release "${perspective.releaseName}" not found in active releases`);
1257
- return ["drafts", ...releaseNames.slice(0, index + 1)].filter((name) => !perspective.excludedPerspectives?.includes(name)).reverse();
1258
- }
1259
- )
1260
- }), _boundGetPerspectiveState = bindActionByResource(
1261
- releasesStore,
1262
- _getPerspectiveStateSelector
1263
- ), getPerspectiveState = (instance, ...rest) => (
1264
- // bindActionByResource keyFn destructures { resource } from the first param, so pass {} when no options
1265
- _boundGetPerspectiveState(instance, ...rest.length ? rest : [{}])
1266
- );
1267
- function setCleanupTimeout(fn, delay) {
1268
- const timer2 = setTimeout(fn, delay), t = timer2;
1269
- return typeof t == "object" && t !== null && "unref" in t && typeof t.unref == "function" && t.unref(), timer2;
1270
- }
1271
- const QUERY_STATE_CLEAR_DELAY = 1e3, QUERY_STORE_API_VERSION = "v2025-05-06", QUERY_STORE_DEFAULT_PERSPECTIVE = "drafts", setQueryError = (key, error) => (prev) => {
1272
- const prevQuery = prev.queries[key];
1273
- return prevQuery ? { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, error } } } : prev;
1274
- }, setQueryData = (key, result, syncTags) => (prev) => {
1275
- const prevQuery = prev.queries[key];
1276
- return prevQuery ? {
1277
- ...prev,
1278
- queries: { ...prev.queries, [key]: { ...prevQuery, result: result ?? null, syncTags } }
1279
- } : prev;
1280
- }, setLastLiveEventId = (key, lastLiveEventId) => (prev) => {
1281
- const prevQuery = prev.queries[key];
1282
- return prevQuery ? { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, lastLiveEventId } } } : prev;
1283
- }, addSubscriber = (key, subscriptionId) => (prev) => {
1284
- const prevQuery = prev.queries[key], subscribers = [...prevQuery?.subscribers ?? [], subscriptionId];
1285
- return { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, subscribers } } };
1286
- }, removeSubscriber = (key, subscriptionId) => (prev) => {
1287
- const prevQuery = prev.queries[key];
1288
- if (!prevQuery) return prev;
1289
- const subscribers = prevQuery.subscribers.filter((id) => id !== subscriptionId);
1290
- return subscribers.length ? { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, subscribers } } } : { ...prev, queries: omitProperty(prev.queries, key) };
1291
- }, EMPTY_ARRAY = [], getQueryKey = (options) => JSON.stringify(options), parseQueryKey = (key) => JSON.parse(key);
1292
- function normalizeOptionsWithPerspective(instance, options) {
1293
- if (options.perspective !== void 0) return options;
1294
- const instancePerspective = instance.config.perspective;
1295
- return {
1296
- ...options,
1297
- perspective: instancePerspective !== void 0 ? instancePerspective : QUERY_STORE_DEFAULT_PERSPECTIVE
1298
- };
1299
- }
1300
- const queryStore = {
1301
- name: "QueryStore",
1302
- getInitialState: () => ({ queries: {} }),
1303
- initialize(context) {
1304
- const subscriptions = [
1305
- listenForNewSubscribersAndFetch(context),
1306
- listenToLiveClientAndSetLastLiveEventIds(context)
1307
- ];
1308
- return () => {
1309
- for (const subscription of subscriptions)
1310
- subscription.unsubscribe();
1311
- };
1312
- }
1313
- }, errorHandler = (state) => (error) => state.set("setError", { error }), listenForNewSubscribersAndFetch = ({ state, instance }) => state.observable.pipe(
1314
- map((s) => new Set(Object.keys(s.queries))),
1315
- distinctUntilChanged((curr, next) => curr.size !== next.size ? !1 : Array.from(next).every((i) => curr.has(i))),
1316
- startWith(/* @__PURE__ */ new Set()),
1317
- pairwise(),
1318
- mergeMap(([curr, next]) => {
1319
- const added = Array.from(next).filter((i) => !curr.has(i)), removed = Array.from(curr).filter((i) => !next.has(i));
1320
- return [
1321
- ...added.map((key) => ({ key, added: !0 })),
1322
- ...removed.map((key) => ({ key, added: !1 }))
1323
- ];
1324
- }),
1325
- groupBy((i) => i.key),
1326
- mergeMap(
1327
- (group$) => group$.pipe(
1328
- switchMap((e) => {
1329
- if (!e.added) return EMPTY;
1330
- const lastLiveEventId$ = state.observable.pipe(
1331
- map((s) => s.queries[group$.key]?.lastLiveEventId),
1332
- distinctUntilChanged()
1333
- ), {
1334
- query,
1335
- params,
1336
- projectId,
1337
- dataset,
1338
- tag,
1339
- resource,
1340
- perspective: perspectiveFromOptions,
1341
- ...restOptions
1342
- } = parseQueryKey(group$.key), perspective$ = isReleasePerspective(perspectiveFromOptions) ? getPerspectiveState(instance, {
1343
- perspective: perspectiveFromOptions,
1344
- resource
1345
- }).observable.pipe(filter(Boolean)) : of(perspectiveFromOptions ?? QUERY_STORE_DEFAULT_PERSPECTIVE), client$ = getClientState(instance, {
1346
- apiVersion: QUERY_STORE_API_VERSION,
1347
- projectId,
1348
- dataset,
1349
- resource
1350
- }).observable;
1351
- return combineLatest({
1352
- lastLiveEventId: lastLiveEventId$,
1353
- client: client$,
1354
- perspective: perspective$
1355
- }).pipe(
1356
- switchMap(
1357
- ({ lastLiveEventId, client, perspective }) => client.observable.fetch(query, params, {
1358
- ...restOptions,
1359
- perspective,
1360
- filterResponse: !1,
1361
- returnQuery: !1,
1362
- lastLiveEventId,
1363
- tag
1364
- })
1365
- ),
1366
- tap(({ result, syncTags }) => {
1367
- state.set("setQueryData", setQueryData(group$.key, result, syncTags));
1368
- }),
1369
- // Catch inside the per-event stream: erroring the group pipe would
1370
- // complete the group's subscription, and since `groupBy` above never
1371
- // removes its group subjects, re-adding the key would emit into a
1372
- // subject with no subscribers — the key could never be fetched again.
1373
- catchError((error) => (state.set("setQueryError", setQueryError(group$.key, error)), EMPTY))
1374
- );
1375
- })
1376
- )
1377
- )
1378
- ).subscribe({ error: errorHandler(state) }), listenToLiveClientAndSetLastLiveEventIds = ({
1379
- state,
1380
- instance,
1381
- key: { resource }
1382
- }) => {
1383
- const liveMessages$ = observeLiveEvents(instance, {
1384
- resource,
1385
- // Surface CORS errors as store state (handled by the Cors Error
1386
- // component) instead of erroring the stream: a stream error here would
1387
- // reach the outer subscription's errorHandler, set the store-wide
1388
- // `state.error`, and permanently brick every query selector.
1389
- onCorsError: (error) => state.set("setError", { error })
1390
- }).pipe(share());
1391
- return state.observable.pipe(
1392
- mergeMap((s) => Object.entries(s.queries)),
1393
- groupBy(([key]) => key),
1394
- mergeMap((group$) => {
1395
- const syncTags$ = group$.pipe(
1396
- map(([, queryState]) => queryState),
1397
- map((i) => i?.syncTags ?? EMPTY_ARRAY),
1398
- distinctUntilChanged()
1399
- );
1400
- return combineLatest([liveMessages$, syncTags$]).pipe(
1401
- filter(([message, syncTags]) => message.tags.some((tag) => syncTags.includes(tag))),
1402
- tap(([message]) => {
1403
- state.set("setLastLiveEventId", setLastLiveEventId(group$.key, message.id));
1404
- })
1405
- );
1406
- })
1407
- ).subscribe({ error: errorHandler(state) });
1408
- };
1409
- function getQueryState(...args) {
1410
- return _getQueryState(...args);
1411
- }
1412
- const _getQueryState = bindActionByResource(
1413
- queryStore,
1414
- createStateSourceAction({
1415
- selector: ({ state, instance }, options) => {
1416
- if (state.error) throw state.error;
1417
- const key = getQueryKey(normalizeOptionsWithPerspective(instance, options)), queryState = state.queries[key];
1418
- if (queryState?.error) throw queryState.error;
1419
- return queryState?.result;
1420
- },
1421
- onSubscribe: ({ state, instance }, options) => {
1422
- const subscriptionId = insecureRandomId(), key = getQueryKey(normalizeOptionsWithPerspective(instance, options));
1423
- return state.set("addSubscriber", addSubscriber(key, subscriptionId)), () => {
1424
- setCleanupTimeout(
1425
- () => state.set("removeSubscriber", removeSubscriber(key, subscriptionId)),
1426
- QUERY_STATE_CLEAR_DELAY
1427
- );
1428
- };
1429
- }
1430
- })
1431
- );
1432
- function resolveQuery(...args) {
1433
- return _resolveQuery(...args);
1434
- }
1435
- const _resolveQuery = bindActionByResource(
1436
- queryStore,
1437
- ({ state, instance }, { signal, ...options }) => {
1438
- const normalized = normalizeOptionsWithPerspective(instance, options), { getCurrent } = getQueryState(instance, normalized), key = getQueryKey(normalized), subscriptionId = insecureRandomId();
1439
- state.set("addSubscriber", addSubscriber(key, subscriptionId));
1440
- const aborted$ = signal ? new Observable((observer) => {
1441
- const cleanup = () => {
1442
- signal.removeEventListener("abort", listener);
1443
- }, listener = () => {
1444
- observer.error(new DOMException("The operation was aborted.", "AbortError")), observer.complete(), cleanup();
1445
- };
1446
- return signal.addEventListener("abort", listener), cleanup;
1447
- }).pipe(
1448
- catchError((error) => {
1449
- throw error instanceof Error && error.name === "AbortError" && state.set("removeSubscriber", removeSubscriber(key, subscriptionId)), error;
1450
- })
1451
- ) : NEVER, resolved$ = state.observable.pipe(
1452
- map(getCurrent),
1453
- first((i) => i !== void 0)
1454
- ), promise = firstValueFrom(race([resolved$, aborted$])), releaseSubscriber = () => {
1455
- setCleanupTimeout(() => {
1456
- state.set("removeSubscriber", removeSubscriber(key, subscriptionId));
1457
- }, QUERY_STATE_CLEAR_DELAY);
1458
- };
1459
- return promise.then(releaseSubscriber, releaseSubscriber), promise;
1460
- }
1461
- );
1462
- var version = "2.19.0";
1463
- const CORE_SDK_VERSION = getEnv("PKG_VERSION") || `${version}-development`, API_VERSION = "vX", PROJECT_API_VERSION = "2025-07-18", USERS_STATE_CLEAR_DELAY = 5e3, DEFAULT_USERS_BATCH_SIZE = 100, getUsersKey = (instance, {
1464
- resourceType,
1465
- organizationId,
1466
- batchSize = DEFAULT_USERS_BATCH_SIZE,
1467
- projectId = instance.config.projectId,
1468
- userId
1469
- } = {}) => JSON.stringify({
1470
- resourceType,
1471
- organizationId,
1472
- batchSize,
1473
- projectId,
1474
- userId
1475
- }), parseUsersKey = (key) => JSON.parse(key), addSubscription = (subscriptionId, key) => (prev) => {
1476
- const group = prev.users[key], subscriptions = [...group?.subscriptions ?? [], subscriptionId];
1477
- return { ...prev, users: { ...prev.users, [key]: { ...group, subscriptions } } };
1478
- }, removeSubscription = (subscriptionId, key) => (prev) => {
1479
- const group = prev.users[key];
1480
- if (!group) return prev;
1481
- const subscriptions = group.subscriptions.filter((id) => id !== subscriptionId);
1482
- return subscriptions.length ? { ...prev, users: { ...prev.users, [key]: { ...group, subscriptions } } } : { ...prev, users: omitProperty(prev.users, key) };
1483
- }, setUsersData = (key, { data, nextCursor, totalCount }) => (prev) => {
1484
- const group = prev.users[key];
1485
- if (!group) return prev;
1486
- const users = [...group.users ?? [], ...data];
1487
- return { ...prev, users: { ...prev.users, [key]: { ...group, users, totalCount, nextCursor } } };
1488
- }, updateLastLoadMoreRequest = (timestamp, key) => (prev) => {
1489
- const group = prev.users[key];
1490
- return group ? { ...prev, users: { ...prev.users, [key]: { ...group, lastLoadMoreRequest: timestamp } } } : prev;
1491
- }, setUsersError = (key, error) => (prev) => {
1492
- const group = prev.users[key];
1493
- return group ? { ...prev, users: { ...prev.users, [key]: { ...group, error } } } : prev;
1494
- }, cancelRequest = (key) => (prev) => {
1495
- const group = prev.users[key];
1496
- return !group || group.subscriptions.length ? prev : { ...prev, users: omitProperty(prev.users, key) };
1497
- }, initializeRequest = (key) => (prev) => prev.users[key] ? prev : { ...prev, users: { ...prev.users, [key]: { subscriptions: [] } } }, TOKEN_REGEX = /(?:[^\s"]+|"[^"]*")+/g;
1498
- function isNegationToken(token) {
1499
- return typeof token < "u" && token.trim().startsWith("-");
1500
- }
1501
- function isPrefixToken(token) {
1502
- return typeof token < "u" && token.trim().endsWith("*");
1503
- }
1504
- function isExactMatchToken(token) {
1505
- return !!token && token.length >= 2 && token.startsWith('"') && token.endsWith('"');
1506
- }
1507
- function createGroqSearchFilter(query) {
1508
- const trimmedQuery = query.trim();
1509
- if (!trimmedQuery)
1510
- return "";
1511
- const tokens = trimmedQuery.match(TOKEN_REGEX) ?? [], reversedIndex = [...tokens].reverse().findIndex(
1512
- (token) => !isNegationToken(token) && !isExactMatchToken(token)
1513
- ), finalIncrementalTokenIndex = reversedIndex === -1 ? -1 : tokens.length - 1 - reversedIndex, finalIncrementalToken = tokens[finalIncrementalTokenIndex], processedTokens = [...tokens];
1514
- return finalIncrementalToken !== void 0 && !isPrefixToken(finalIncrementalToken) && processedTokens.splice(
1515
- finalIncrementalTokenIndex,
1516
- 1,
1517
- `${finalIncrementalToken}*`
1518
- ), `[@] match text::query("${processedTokens.join(" ").replace(/"/g, '\\"')}")`;
1519
- }
1520
- export {
1521
- API_VERSION,
1522
- AuthStateType,
1523
- CORE_SDK_VERSION,
1524
- DEFAULT_API_VERSION$1 as DEFAULT_API_VERSION,
1525
- PREVIEW_PROJECTION,
1526
- PROJECT_API_VERSION,
1527
- REQUEST_TAG_PREFIX,
1528
- USERS_STATE_CLEAR_DELAY,
1529
- addSubscription,
1530
- authStore,
1531
- authStore$1,
1532
- bindActionByResource,
1533
- bindActionByResourceAndPerspective,
1534
- bindActionGlobally,
1535
- cancelRequest,
1536
- clientStore$1 as clientStore,
1537
- configureLogging,
1538
- createGroqSearchFilter,
1539
- createLoggedInAuthState,
1540
- createLogger,
1541
- createStateSourceAction,
1542
- defineStore,
1543
- getActiveReleasesState,
1544
- getAllReleasesState,
1545
- getAuthCode,
1546
- getAuthLogger,
1547
- getAuthState,
1548
- getCleanedUrl,
1549
- getClient,
1550
- getClientErrorApiBody,
1551
- getClientErrorApiDescription,
1552
- getClientErrorApiType,
1553
- getClientState,
1554
- getCurrentUserState,
1555
- getDashboardOrganizationId,
1556
- getDefaultLocation,
1557
- getIsInDashboardState,
1558
- getLoginUrlState,
1559
- getPerspectiveState,
1560
- getQueryKey,
1561
- getQueryState,
1562
- getTokenFromLocation,
1563
- getTokenState,
1564
- getUsersKey,
1565
- initializeRequest,
1566
- insecureRandomId,
1567
- isCanvasResource,
1568
- isCanvasSource,
1569
- isDatasetResource,
1570
- isDatasetSource,
1571
- isDeepEqual,
1572
- isMediaLibraryResource,
1573
- isMediaLibrarySource,
1574
- isProjectUserNotFoundClientError,
1575
- isReleasePerspective,
1576
- isStudioConfig,
1577
- omitProperty,
1578
- parseQueryKey,
1579
- parseUsersKey,
1580
- pickProperties,
1581
- removeSubscription,
1582
- resolveQuery,
1583
- setAuthToken,
1584
- setCleanupTimeout,
1585
- setUsersData,
1586
- setUsersError,
1587
- transformProjectionToPreview,
1588
- updateLastLoadMoreRequest
1589
- };
1590
- //# sourceMappingURL=createGroqSearchFilter.js.map