@sanity/sdk 2.5.0 → 2.7.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.
- package/dist/index.d.ts +429 -27
- package/dist/index.js +657 -266
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/_exports/index.ts +18 -3
- package/src/auth/authMode.test.ts +56 -0
- package/src/auth/authMode.ts +71 -0
- package/src/auth/authStore.test.ts +85 -4
- package/src/auth/authStore.ts +63 -125
- package/src/auth/authStrategy.ts +39 -0
- package/src/auth/dashboardAuth.ts +132 -0
- package/src/auth/standaloneAuth.ts +109 -0
- package/src/auth/studioAuth.ts +217 -0
- package/src/auth/studioModeAuth.test.ts +43 -1
- package/src/auth/studioModeAuth.ts +10 -1
- package/src/auth/subscribeToStateAndFetchCurrentUser.ts +21 -6
- package/src/client/clientStore.test.ts +45 -43
- package/src/client/clientStore.ts +23 -9
- package/src/config/loggingConfig.ts +149 -0
- package/src/config/sanityConfig.ts +82 -22
- package/src/projection/getProjectionState.ts +6 -5
- package/src/projection/projectionQuery.test.ts +38 -55
- package/src/projection/projectionQuery.ts +27 -31
- package/src/projection/projectionStore.test.ts +4 -4
- package/src/projection/projectionStore.ts +3 -2
- package/src/projection/resolveProjection.ts +2 -2
- package/src/projection/statusQuery.test.ts +35 -0
- package/src/projection/statusQuery.ts +71 -0
- package/src/projection/subscribeToStateAndFetchBatches.test.ts +63 -50
- package/src/projection/subscribeToStateAndFetchBatches.ts +106 -27
- package/src/projection/types.ts +12 -0
- package/src/projection/util.ts +0 -1
- package/src/query/queryStore.test.ts +64 -0
- package/src/query/queryStore.ts +33 -11
- package/src/releases/getPerspectiveState.test.ts +17 -14
- package/src/releases/getPerspectiveState.ts +58 -38
- package/src/releases/releasesStore.test.ts +59 -61
- package/src/releases/releasesStore.ts +21 -35
- package/src/releases/utils/isReleasePerspective.ts +7 -0
- package/src/store/createActionBinder.test.ts +211 -1
- package/src/store/createActionBinder.ts +102 -13
- package/src/store/createSanityInstance.test.ts +85 -1
- package/src/store/createSanityInstance.ts +55 -4
- package/src/utils/logger-usage-example.md +141 -0
- package/src/utils/logger.test.ts +757 -0
- package/src/utils/logger.ts +537 -0
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
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,
|
|
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
2
|
import { createClient, CorsOriginError } from "@sanity/client";
|
|
3
3
|
import { pick, omit, isEqual, isObject } from "lodash-es";
|
|
4
4
|
import { devtools } from "zustand/middleware";
|
|
5
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
|
|
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";
|
|
7
7
|
import { createController, createNode } from "@sanity/comlink";
|
|
8
8
|
import { createSelector } from "reselect";
|
|
9
9
|
import { SanityEncoder } from "@sanity/mutate";
|
|
@@ -17,16 +17,17 @@ import { isKeySegment, isKeyedObject } from "@sanity/types";
|
|
|
17
17
|
import { createDocumentLoaderFromClient } from "@sanity/mutate/_unstable_store";
|
|
18
18
|
import { SDK_CHANNEL_NAME, SDK_NODE_NAME } from "@sanity/message-protocol";
|
|
19
19
|
import { fromUrl } from "@sanity/bifur-client";
|
|
20
|
-
|
|
21
|
-
function
|
|
22
|
-
return
|
|
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
23
|
}
|
|
24
|
-
function
|
|
25
|
-
return
|
|
24
|
+
function isMediaLibrarySource(source) {
|
|
25
|
+
return "mediaLibraryId" in source;
|
|
26
26
|
}
|
|
27
|
-
function
|
|
28
|
-
return
|
|
27
|
+
function isCanvasSource(source) {
|
|
28
|
+
return "canvasId" in source;
|
|
29
29
|
}
|
|
30
|
+
const isReleasePerspective = (perspective) => typeof perspective == "object" && perspective !== null && "releaseName" in perspective;
|
|
30
31
|
function getPublishedId(id) {
|
|
31
32
|
const draftsPrefix = "drafts.";
|
|
32
33
|
return id.startsWith(draftsPrefix) ? id.slice(draftsPrefix.length) : id;
|
|
@@ -38,13 +39,154 @@ function getDraftId(id) {
|
|
|
38
39
|
function insecureRandomId() {
|
|
39
40
|
return Array.from({ length: 16 }, () => Math.floor(Math.random() * 16).toString(16)).join("");
|
|
40
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
|
+
}
|
|
41
156
|
function createSanityInstance(config = {}) {
|
|
42
|
-
const instanceId = crypto.randomUUID(), disposeListeners = /* @__PURE__ */ new Map(), disposed = { current: !1 },
|
|
157
|
+
const instanceId = crypto.randomUUID(), disposeListeners = /* @__PURE__ */ new Map(), disposed = { current: !1 }, instanceContext = {
|
|
158
|
+
instanceId,
|
|
159
|
+
projectId: config.projectId,
|
|
160
|
+
dataset: config.dataset
|
|
161
|
+
}, logger = createLogger("sdk", { instanceContext });
|
|
162
|
+
logger.info("Sanity instance created", {
|
|
163
|
+
hasProjectId: !!config.projectId,
|
|
164
|
+
hasDataset: !!config.dataset,
|
|
165
|
+
hasAuth: !!config.auth,
|
|
166
|
+
hasPerspective: !!config.perspective
|
|
167
|
+
}), logger.debug("Instance configuration", {
|
|
168
|
+
projectId: config.projectId,
|
|
169
|
+
dataset: config.dataset,
|
|
170
|
+
perspective: config.perspective,
|
|
171
|
+
hasStudioConfig: !!config.studio,
|
|
172
|
+
hasStudioTokenSource: !!config.studio?.auth?.token,
|
|
173
|
+
legacyStudioMode: config.studioMode?.enabled,
|
|
174
|
+
hasAuthProviders: !!config.auth?.providers,
|
|
175
|
+
hasAuthToken: !!config.auth?.token
|
|
176
|
+
});
|
|
177
|
+
const instance = {
|
|
43
178
|
instanceId,
|
|
44
179
|
config,
|
|
45
180
|
isDisposed: () => disposed.current,
|
|
46
181
|
dispose: () => {
|
|
47
|
-
|
|
182
|
+
if (disposed.current) {
|
|
183
|
+
logger.trace("Dispose called on already disposed instance", { internal: !0 });
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
logger.trace("Disposing instance", {
|
|
187
|
+
internal: !0,
|
|
188
|
+
listenerCount: disposeListeners.size
|
|
189
|
+
}), disposed.current = !0, disposeListeners.forEach((listener) => listener()), disposeListeners.clear(), logger.info("Instance disposed");
|
|
48
190
|
},
|
|
49
191
|
onDispose: (cb) => {
|
|
50
192
|
const listenerId = insecureRandomId();
|
|
@@ -54,14 +196,26 @@ function createSanityInstance(config = {}) {
|
|
|
54
196
|
},
|
|
55
197
|
getParent: () => {
|
|
56
198
|
},
|
|
57
|
-
createChild: (next) =>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
199
|
+
createChild: (next) => {
|
|
200
|
+
logger.debug("Creating child instance", {
|
|
201
|
+
parentInstanceId: instanceId.slice(0, 8),
|
|
202
|
+
overridingProjectId: !!next.projectId,
|
|
203
|
+
overridingDataset: !!next.dataset,
|
|
204
|
+
overridingAuth: !!next.auth
|
|
205
|
+
});
|
|
206
|
+
const child = Object.assign(
|
|
207
|
+
createSanityInstance({
|
|
208
|
+
...config,
|
|
209
|
+
...next,
|
|
210
|
+
...config.auth === next.auth ? config.auth : config.auth && next.auth && { auth: { ...config.auth, ...next.auth } }
|
|
211
|
+
}),
|
|
212
|
+
{ getParent: () => instance }
|
|
213
|
+
);
|
|
214
|
+
return logger.trace("Child instance created", {
|
|
215
|
+
internal: !0,
|
|
216
|
+
childInstanceId: child.instanceId.slice(0, 8)
|
|
217
|
+
}), child;
|
|
218
|
+
},
|
|
65
219
|
match: (targetConfig) => {
|
|
66
220
|
if (Object.entries(pick(targetConfig, "auth", "projectId", "dataset")).every(
|
|
67
221
|
([key, value]) => config[key] === value
|
|
@@ -129,16 +283,33 @@ const bindActionByDataset = createActionBinder((instance, options) => {
|
|
|
129
283
|
if (!projectId || !dataset)
|
|
130
284
|
throw new Error("This API requires a project ID and dataset configured.");
|
|
131
285
|
return { name: `${projectId}.${dataset}`, projectId, dataset };
|
|
132
|
-
}),
|
|
286
|
+
}), createSourceKey = (instance, source) => {
|
|
287
|
+
let name, sourceForKey;
|
|
133
288
|
if (source) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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 };
|
|
137
298
|
}
|
|
138
299
|
const { projectId, dataset } = instance.config;
|
|
139
300
|
if (!projectId || !dataset)
|
|
140
301
|
throw new Error("This API requires a project ID and dataset configured.");
|
|
141
|
-
return { name: `${projectId}.${dataset}
|
|
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
|
+
};
|
|
142
313
|
}), bindActionGlobally = createActionBinder((..._rest) => ({ name: "global" }));
|
|
143
314
|
function createStateSourceAction(options) {
|
|
144
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();
|
|
@@ -187,8 +358,25 @@ function createStateSourceAction(options) {
|
|
|
187
358
|
}
|
|
188
359
|
return stateSourceAction;
|
|
189
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
|
+
}
|
|
190
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 || {});
|
|
191
|
-
const
|
|
379
|
+
const REFRESH_INTERVAL = 720 * 60 * 1e3, LOCK_NAME = "sanity-token-refresh-lock";
|
|
192
380
|
function getLastRefreshTime(storageArea, storageKey) {
|
|
193
381
|
try {
|
|
194
382
|
const data = storageArea?.getItem(`${storageKey}_last_refresh`), parsed = data ? parseInt(data, 10) : 0;
|
|
@@ -351,6 +539,47 @@ const refreshStampedToken = ({ state }) => {
|
|
|
351
539
|
state.set("setRefreshStampedTokenError", { authState: { type: AuthStateType.ERROR, error } });
|
|
352
540
|
}
|
|
353
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
|
+
});
|
|
354
583
|
};
|
|
355
584
|
function getAuthCode(callbackUrl, locationHref) {
|
|
356
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;
|
|
@@ -425,66 +654,53 @@ function getClientErrorApiDescription(error) {
|
|
|
425
654
|
function isProjectUserNotFoundClientError(error) {
|
|
426
655
|
return getClientErrorApiType(error) === "projectUserNotFoundError";
|
|
427
656
|
}
|
|
428
|
-
|
|
429
|
-
if (!projectId) return !1;
|
|
657
|
+
function parseDashboardContext(locationHref) {
|
|
430
658
|
try {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
} catch {
|
|
440
|
-
return !1;
|
|
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);
|
|
441
667
|
}
|
|
668
|
+
return {};
|
|
442
669
|
}
|
|
443
|
-
function
|
|
444
|
-
|
|
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
|
+
};
|
|
445
691
|
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
})
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
filter(
|
|
454
|
-
(value) => value.authState.type === AuthStateType.LOGGED_IN && !value.authState.currentUser
|
|
455
|
-
),
|
|
456
|
-
map((value) => ({ token: value.authState.token, authMethod: value.authMethod })),
|
|
457
|
-
distinctUntilChanged(
|
|
458
|
-
(prev, curr) => prev.token === curr.token && prev.authMethod === curr.authMethod
|
|
459
|
-
)
|
|
460
|
-
).pipe(
|
|
461
|
-
map(
|
|
462
|
-
({ token, authMethod }) => clientFactory({
|
|
463
|
-
apiVersion: DEFAULT_API_VERSION$1,
|
|
464
|
-
requestTagPrefix: REQUEST_TAG_PREFIX,
|
|
465
|
-
token: authMethod === "cookie" ? void 0 : token,
|
|
466
|
-
ignoreBrowserTokenWarning: !0,
|
|
467
|
-
useProjectHostname,
|
|
468
|
-
useCdn: !1,
|
|
469
|
-
...authMethod === "cookie" ? { withCredentials: !0 } : {},
|
|
470
|
-
...useProjectHostname && projectId ? { projectId } : {},
|
|
471
|
-
...apiHost && { apiHost }
|
|
472
|
-
})
|
|
473
|
-
),
|
|
474
|
-
switchMap(
|
|
475
|
-
(client) => client.observable.request({ uri: "/users/me", method: "GET" })
|
|
476
|
-
)
|
|
477
|
-
).subscribe({
|
|
478
|
-
next: (currentUser) => {
|
|
479
|
-
state.set("setCurrentUser", (prev) => ({
|
|
480
|
-
authState: prev.authState.type === AuthStateType.LOGGED_IN ? { ...prev.authState, currentUser } : prev.authState
|
|
481
|
-
}));
|
|
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();
|
|
482
699
|
},
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}, subscribeToStorageEventsAndSetToken = ({
|
|
700
|
+
tokenRefresherStarted: startedRefresher
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
const subscribeToStorageEventsAndSetToken = ({
|
|
488
704
|
state
|
|
489
705
|
}) => {
|
|
490
706
|
const { storageArea, storageKey } = state.get().options;
|
|
@@ -500,6 +716,159 @@ const subscribeToStateAndFetchCurrentUser = ({
|
|
|
500
716
|
});
|
|
501
717
|
});
|
|
502
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
|
+
}
|
|
503
872
|
let tokenRefresherRunning = !1;
|
|
504
873
|
const authStore = {
|
|
505
874
|
name: "Auth",
|
|
@@ -511,9 +880,7 @@ const authStore = {
|
|
|
511
880
|
token: providedToken,
|
|
512
881
|
clientFactory = createClient,
|
|
513
882
|
initialLocationHref = getDefaultLocation()
|
|
514
|
-
} = instance.config.auth ?? {};
|
|
515
|
-
let storageArea = instance.config.auth?.storageArea, storageKey = "__sanity_auth_token";
|
|
516
|
-
const studioModeEnabled = instance.config.studioMode?.enabled;
|
|
883
|
+
} = instance.config.auth ?? {}, authConfig = instance.config.auth ?? {};
|
|
517
884
|
let loginDomain = "https://www.sanity.io";
|
|
518
885
|
try {
|
|
519
886
|
apiHost && new URL(apiHost).hostname.endsWith(".sanity.work") && (loginDomain = "https://www.sanity.work");
|
|
@@ -521,27 +888,27 @@ const authStore = {
|
|
|
521
888
|
}
|
|
522
889
|
const loginUrl = new URL("/login", loginDomain);
|
|
523
890
|
loginUrl.searchParams.set("origin", getCleanedUrl(initialLocationHref)), loginUrl.searchParams.set("type", "stampedToken"), loginUrl.searchParams.set("withSid", "true");
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
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;
|
|
533
908
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
const studioStorageKey = `__studio_auth_token_${instance.config.projectId ?? ""}`;
|
|
538
|
-
storageKey = studioStorageKey, token = getStudioTokenFromLocalStorage(storageArea, studioStorageKey), token && (authMethod = "localstorage");
|
|
539
|
-
} else
|
|
540
|
-
token = getTokenFromStorage(storageArea, storageKey), token && (authMethod = "localstorage");
|
|
541
|
-
let authState;
|
|
542
|
-
return providedToken ? authState = { type: AuthStateType.LOGGED_IN, token: providedToken, currentUser: null } : token && studioModeEnabled ? authState = { type: AuthStateType.LOGGED_IN, token: token ?? "", currentUser: null } : getAuthCode(callbackUrl, initialLocationHref) || getTokenFromLocation(initialLocationHref) ? authState = { type: AuthStateType.LOGGING_IN, isExchangingToken: !1 } : token && !isInDashboard && !studioModeEnabled ? authState = { type: AuthStateType.LOGGED_IN, token, currentUser: null } : authState = { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }, {
|
|
543
|
-
authState,
|
|
544
|
-
dashboardContext,
|
|
909
|
+
return {
|
|
910
|
+
authState: result.authState,
|
|
911
|
+
dashboardContext: result.dashboardContext,
|
|
545
912
|
options: {
|
|
546
913
|
apiHost,
|
|
547
914
|
loginUrl: loginUrl.toString(),
|
|
@@ -550,32 +917,27 @@ const authStore = {
|
|
|
550
917
|
providedToken,
|
|
551
918
|
clientFactory,
|
|
552
919
|
initialLocationHref,
|
|
553
|
-
storageKey,
|
|
554
|
-
storageArea,
|
|
555
|
-
authMethod
|
|
920
|
+
storageKey: result.storageKey,
|
|
921
|
+
storageArea: result.storageArea,
|
|
922
|
+
authMethod: result.authMethod
|
|
556
923
|
}
|
|
557
924
|
};
|
|
558
925
|
},
|
|
559
926
|
initialize(context) {
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
}
|
|
573
|
-
} catch {
|
|
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;
|
|
574
939
|
}
|
|
575
|
-
return
|
|
576
|
-
for (const subscription of subscriptions)
|
|
577
|
-
subscription.unsubscribe();
|
|
578
|
-
};
|
|
940
|
+
return initResult.tokenRefresherStarted && (tokenRefresherRunning = !0), initResult.dispose;
|
|
579
941
|
}
|
|
580
942
|
}, getCurrentUserState = bindActionGlobally(
|
|
581
943
|
authStore,
|
|
@@ -673,12 +1035,12 @@ const authStore = {
|
|
|
673
1035
|
`The client options provided contains unsupported properties: ${listFormatter.format(disallowedKeys)}. Allowed keys are: ${listFormatter.format(allowedKeys)}.`
|
|
674
1036
|
);
|
|
675
1037
|
}
|
|
676
|
-
const tokenFromState = state.get().token, { clients, authMethod } = state.get()
|
|
677
|
-
let
|
|
678
|
-
|
|
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 }));
|
|
679
1041
|
const projectId = options.projectId ?? instance.config.projectId, dataset = options.dataset ?? instance.config.dataset, apiHost = options.apiHost ?? instance.config.auth?.apiHost, effectiveOptions = {
|
|
680
1042
|
...DEFAULT_CLIENT_CONFIG,
|
|
681
|
-
...(options.scope === "global" || !projectId ||
|
|
1043
|
+
...(options.scope === "global" || !projectId || resource) && { useProjectHostname: !1 },
|
|
682
1044
|
token: authMethod === "cookie" ? void 0 : tokenFromState ?? void 0,
|
|
683
1045
|
...options,
|
|
684
1046
|
...projectId && { projectId },
|
|
@@ -686,7 +1048,7 @@ const authStore = {
|
|
|
686
1048
|
...apiHost && { apiHost },
|
|
687
1049
|
...resource && { "~experimental_resource": resource }
|
|
688
1050
|
};
|
|
689
|
-
|
|
1051
|
+
resource && ((options.projectId || options.dataset) && console.warn(
|
|
690
1052
|
"Both source and explicit projectId/dataset are provided. The source will be used and projectId/dataset will be ignored."
|
|
691
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;
|
|
692
1054
|
const key = getClientConfigKey(effectiveOptions);
|
|
@@ -1144,6 +1506,21 @@ function createProjectHandle(handle) {
|
|
|
1144
1506
|
function createDatasetHandle(handle) {
|
|
1145
1507
|
return handle;
|
|
1146
1508
|
}
|
|
1509
|
+
function configureLogging(config) {
|
|
1510
|
+
configureLogging$1(config);
|
|
1511
|
+
const configLevel = config.level || "warn", shouldLog = ["info", "debug", "trace"].includes(configLevel) || configLevel === "warn";
|
|
1512
|
+
shouldLog && config.handler?.info ? config.handler.info(`[${(/* @__PURE__ */ new Date()).toISOString()}] [INFO] [sdk] Logging configured`, {
|
|
1513
|
+
level: configLevel,
|
|
1514
|
+
namespaces: config.namespaces || [],
|
|
1515
|
+
internal: config.internal || !1,
|
|
1516
|
+
source: "programmatic"
|
|
1517
|
+
}) : shouldLog && console.info(`[${(/* @__PURE__ */ new Date()).toISOString()}] [INFO] [sdk] Logging configured`, {
|
|
1518
|
+
level: configLevel,
|
|
1519
|
+
namespaces: config.namespaces || [],
|
|
1520
|
+
internal: config.internal || !1,
|
|
1521
|
+
source: "programmatic"
|
|
1522
|
+
});
|
|
1523
|
+
}
|
|
1147
1524
|
const API_VERSION$4 = "v2025-02-19", datasets = createFetcherStore({
|
|
1148
1525
|
name: "Datasets",
|
|
1149
1526
|
getKey: (instance, options) => {
|
|
@@ -1621,7 +1998,7 @@ function sortListenerEvents(options) {
|
|
|
1621
1998
|
mergeMap((state) => of(...state.emitEvents))
|
|
1622
1999
|
);
|
|
1623
2000
|
}
|
|
1624
|
-
const listen
|
|
2001
|
+
const listen = ({ state }, documentId) => {
|
|
1625
2002
|
const { sharedListener, fetchDocument } = state.get();
|
|
1626
2003
|
return sharedListener.events.pipe(
|
|
1627
2004
|
concatMap((e) => e.type === "welcome" ? fetchDocument(documentId).pipe(
|
|
@@ -2775,9 +3152,9 @@ const _resolveDocument = bindActionByDataset(
|
|
|
2775
3152
|
groupBy$1((i) => i.id),
|
|
2776
3153
|
mergeMap$1(
|
|
2777
3154
|
(group) => group.pipe(
|
|
2778
|
-
switchMap((e) => e.add ? listen
|
|
3155
|
+
switchMap((e) => e.add ? listen(context, e.id).pipe(
|
|
2779
3156
|
catchError$1((error) => {
|
|
2780
|
-
throw error instanceof OutOfSyncError && listen
|
|
3157
|
+
throw error instanceof OutOfSyncError && listen(context, e.id), error;
|
|
2781
3158
|
}),
|
|
2782
3159
|
tap$1(
|
|
2783
3160
|
(remote) => state.set(
|
|
@@ -3258,40 +3635,7 @@ const handleIncomingMessage = (event) => {
|
|
|
3258
3635
|
return () => subscription.unsubscribe();
|
|
3259
3636
|
}
|
|
3260
3637
|
})
|
|
3261
|
-
), fetch = (client, query, params, options) => defer(
|
|
3262
|
-
() => client.observable.fetch(query, params, {
|
|
3263
|
-
tag: options.tag,
|
|
3264
|
-
filterResponse: !0
|
|
3265
|
-
})
|
|
3266
|
-
), listen = (client, query, params, options) => defer(
|
|
3267
|
-
() => client.listen(query, params, {
|
|
3268
|
-
events: ["welcome", "mutation", "reconnect"],
|
|
3269
|
-
includeResult: !1,
|
|
3270
|
-
visibility: "query",
|
|
3271
|
-
tag: options.tag
|
|
3272
|
-
})
|
|
3273
3638
|
);
|
|
3274
|
-
function isWelcomeEvent(event) {
|
|
3275
|
-
return event.type === "welcome";
|
|
3276
|
-
}
|
|
3277
|
-
const listenQuery = (client, query, params = {}, options = {}) => {
|
|
3278
|
-
const fetchQuery = query, listenerQuery = query, fetchOnce$ = fetch(client, fetchQuery, params, options), events$ = listen(client, listenerQuery, params, options).pipe(
|
|
3279
|
-
mergeMap((ev, i) => i === 0 && !isWelcomeEvent(ev) ? throwError(
|
|
3280
|
-
() => new Error(
|
|
3281
|
-
ev.type === "reconnect" ? "Could not establish EventSource connection" : `Received unexpected type of first event "${ev.type}"`
|
|
3282
|
-
)
|
|
3283
|
-
) : of(ev)),
|
|
3284
|
-
share$1()
|
|
3285
|
-
), [welcome$, mutationAndReconnect$] = partition(events$, isWelcomeEvent), isRelevantEvent = (event) => !options.transitions || event.type !== "mutation" ? !0 : options.transitions.includes(event.transition);
|
|
3286
|
-
return merge(
|
|
3287
|
-
welcome$.pipe(take(1)),
|
|
3288
|
-
mutationAndReconnect$.pipe(filter$1(isRelevantEvent), debounceTime(options.throttleTime || 1e3))
|
|
3289
|
-
).pipe(
|
|
3290
|
-
// will cancel any in-flight request when a new one comes in
|
|
3291
|
-
// but ensures we always get the latest data
|
|
3292
|
-
switchMap(() => fetchOnce$)
|
|
3293
|
-
);
|
|
3294
|
-
};
|
|
3295
3639
|
function sortReleases(releases = []) {
|
|
3296
3640
|
return [...releases].sort((a, b) => {
|
|
3297
3641
|
if (a.metadata.releaseType === "undecided" && b.metadata.releaseType !== "undecided")
|
|
@@ -3310,7 +3654,7 @@ function sortReleases(releases = []) {
|
|
|
3310
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;
|
|
3311
3655
|
});
|
|
3312
3656
|
}
|
|
3313
|
-
const ARCHIVED_RELEASE_STATES = ["archived", "published"], releasesStore = {
|
|
3657
|
+
const ARCHIVED_RELEASE_STATES = ["archived", "published"], STABLE_EMPTY_RELEASES = [], releasesStore = {
|
|
3314
3658
|
name: "Releases",
|
|
3315
3659
|
getInitialState: () => ({
|
|
3316
3660
|
activeReleases: void 0
|
|
@@ -3324,43 +3668,26 @@ const ARCHIVED_RELEASE_STATES = ["archived", "published"], releasesStore = {
|
|
|
3324
3668
|
createStateSourceAction({
|
|
3325
3669
|
selector: ({ state }, _) => state.activeReleases
|
|
3326
3670
|
})
|
|
3327
|
-
), RELEASES_QUERY = "releases::all()",
|
|
3671
|
+
), RELEASES_QUERY = "releases::all()", subscribeToReleases = ({
|
|
3328
3672
|
instance,
|
|
3329
3673
|
state,
|
|
3330
3674
|
key: { projectId, dataset }
|
|
3331
|
-
}) =>
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
delay: (error, retryCount) => (console.error("[releases] Error in subscription:", error, "Retry count:", retryCount), timer(Math.min(1e3 * Math.pow(2, retryCount), 1e4)))
|
|
3348
|
-
}),
|
|
3349
|
-
catchError$1((error) => (state.set("setError", { error }), EMPTY))
|
|
3350
|
-
)
|
|
3351
|
-
)
|
|
3352
|
-
)
|
|
3353
|
-
).subscribe({
|
|
3354
|
-
next: (releases) => {
|
|
3355
|
-
state.set("setActiveReleases", {
|
|
3356
|
-
activeReleases: sortReleases(releases ?? []).filter((release) => !ARCHIVED_RELEASE_STATES.includes(release.state)).reverse()
|
|
3357
|
-
});
|
|
3358
|
-
}
|
|
3359
|
-
});
|
|
3360
|
-
function isReleasePerspective(perspective) {
|
|
3361
|
-
return typeof perspective == "object" && perspective !== null && "releaseName" in perspective;
|
|
3362
|
-
}
|
|
3363
|
-
const DEFAULT_PERSPECTIVE = "drafts", optionsCache = /* @__PURE__ */ new Map(), selectInstancePerspective = (context, _) => context.instance.config.perspective, selectActiveReleases = (context) => context.state.activeReleases, selectOptions = (_context, options) => options, memoizedOptionsSelector = createSelector(
|
|
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(
|
|
3364
3691
|
[selectActiveReleases, selectOptions],
|
|
3365
3692
|
(activeReleases, options) => {
|
|
3366
3693
|
if (!options || !activeReleases) return options;
|
|
@@ -3371,25 +3698,25 @@ const DEFAULT_PERSPECTIVE = "drafts", optionsCache = /* @__PURE__ */ new Map(),
|
|
|
3371
3698
|
let cachedOptions = nestedCache.get(optionsKey);
|
|
3372
3699
|
return cachedOptions || (cachedOptions = options, nestedCache.set(optionsKey, cachedOptions)), cachedOptions;
|
|
3373
3700
|
}
|
|
3374
|
-
),
|
|
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(
|
|
3375
3717
|
releasesStore,
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
[selectInstancePerspective, selectActiveReleases, memoizedOptionsSelector],
|
|
3379
|
-
(instancePerspective, activeReleases, memoizedOptions) => {
|
|
3380
|
-
const perspective = memoizedOptions?.perspective ?? instancePerspective ?? DEFAULT_PERSPECTIVE;
|
|
3381
|
-
if (!isReleasePerspective(perspective)) return perspective;
|
|
3382
|
-
if (!activeReleases || activeReleases.length === 0) return;
|
|
3383
|
-
const releaseNames = sortReleases(activeReleases).map((release) => release.name), index = releaseNames.findIndex((name) => name === perspective.releaseName);
|
|
3384
|
-
if (index < 0)
|
|
3385
|
-
throw new Error(`Release "${perspective.releaseName}" not found in active releases`);
|
|
3386
|
-
return ["drafts", ...releaseNames.slice(0, index + 1)].filter(
|
|
3387
|
-
(name) => !perspective.excludedPerspectives?.includes(name)
|
|
3388
|
-
);
|
|
3389
|
-
}
|
|
3390
|
-
)
|
|
3391
|
-
})
|
|
3392
|
-
), QUERY_STATE_CLEAR_DELAY = 1e3, QUERY_STORE_API_VERSION = "v2025-05-06", QUERY_STORE_DEFAULT_PERSPECTIVE = "drafts", setQueryError = (key, error) => (prev) => {
|
|
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) => {
|
|
3393
3720
|
const prevQuery = prev.queries[key];
|
|
3394
3721
|
return prevQuery ? { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, error } } } : prev;
|
|
3395
3722
|
}, setQueryData = (key, result, syncTags) => (prev) => {
|
|
@@ -3463,17 +3790,21 @@ const queryStore = {
|
|
|
3463
3790
|
source,
|
|
3464
3791
|
perspective: perspectiveFromOptions,
|
|
3465
3792
|
...restOptions
|
|
3466
|
-
} = parseQueryKey(group$.key), perspective$ = getPerspectiveState(instance, {
|
|
3793
|
+
} = parseQueryKey(group$.key), perspective$ = isReleasePerspective(perspectiveFromOptions) ? getPerspectiveState(instance, {
|
|
3467
3794
|
perspective: perspectiveFromOptions
|
|
3468
|
-
}).observable.pipe(filter(Boolean)), client$ = getClientState(instance, {
|
|
3795
|
+
}).observable.pipe(filter(Boolean)) : of(perspectiveFromOptions ?? QUERY_STORE_DEFAULT_PERSPECTIVE), client$ = getClientState(instance, {
|
|
3469
3796
|
apiVersion: QUERY_STORE_API_VERSION,
|
|
3470
3797
|
projectId,
|
|
3471
3798
|
dataset,
|
|
3472
3799
|
source
|
|
3473
3800
|
}).observable;
|
|
3474
|
-
return combineLatest(
|
|
3801
|
+
return combineLatest({
|
|
3802
|
+
lastLiveEventId: lastLiveEventId$,
|
|
3803
|
+
client: client$,
|
|
3804
|
+
perspective: perspective$
|
|
3805
|
+
}).pipe(
|
|
3475
3806
|
switchMap(
|
|
3476
|
-
(
|
|
3807
|
+
({ lastLiveEventId, client, perspective }) => client.observable.fetch(query, params, {
|
|
3477
3808
|
...restOptions,
|
|
3478
3809
|
perspective,
|
|
3479
3810
|
filterResponse: !1,
|
|
@@ -3492,10 +3823,13 @@ const queryStore = {
|
|
|
3492
3823
|
)
|
|
3493
3824
|
).subscribe({ error: errorHandler(state) }), listenToLiveClientAndSetLastLiveEventIds = ({
|
|
3494
3825
|
state,
|
|
3495
|
-
instance
|
|
3826
|
+
instance,
|
|
3827
|
+
key: { source }
|
|
3496
3828
|
}) => {
|
|
3497
3829
|
const liveMessages$ = getClientState(instance, {
|
|
3498
|
-
apiVersion: QUERY_STORE_API_VERSION
|
|
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 } : {}
|
|
3499
3833
|
}).observable.pipe(
|
|
3500
3834
|
switchMap(
|
|
3501
3835
|
(client) => defer(
|
|
@@ -3685,7 +4019,7 @@ const BATCH_DEBOUNCE_TIME$1 = 50, isSetEqual$1 = (a, b) => a.size === b.size &&
|
|
|
3685
4019
|
}) => state.observable.pipe(
|
|
3686
4020
|
map(({ subscriptions }) => new Set(Object.keys(subscriptions))),
|
|
3687
4021
|
distinctUntilChanged(isSetEqual$1),
|
|
3688
|
-
debounceTime
|
|
4022
|
+
debounceTime(BATCH_DEBOUNCE_TIME$1),
|
|
3689
4023
|
startWith$1(/* @__PURE__ */ new Set()),
|
|
3690
4024
|
pairwise$1(),
|
|
3691
4025
|
tap$1(([prevIds, currIds]) => {
|
|
@@ -3784,7 +4118,7 @@ const _getPreviewState = bindActionByDataset(
|
|
|
3784
4118
|
), resolvePreview = bindActionByDataset(
|
|
3785
4119
|
previewStore,
|
|
3786
4120
|
({ instance }, docHandle) => firstValueFrom(getPreviewState(instance, docHandle).observable.pipe(filter((i) => !!i.data)))
|
|
3787
|
-
), PROJECTION_TAG = "projection",
|
|
4121
|
+
), PROJECTION_TAG = "projection", PROJECTION_STATE_CLEAR_DELAY = 1e3, STABLE_EMPTY_PROJECTION = {
|
|
3788
4122
|
data: null,
|
|
3789
4123
|
isPending: !1
|
|
3790
4124
|
};
|
|
@@ -3808,20 +4142,21 @@ function createProjectionQuery(documentIds, documentProjections) {
|
|
|
3808
4142
|
return obj.documentIds.add(documentId), acc[projectionHash] = obj, acc;
|
|
3809
4143
|
}, {}), query = `[${Object.entries(projections).map(([projectionHash, { projection }]) => `...*[_id in $__ids_${projectionHash}]{_id,_type,_updatedAt,"__projectionHash":"${projectionHash}","result":{...${projection}}}`).join(",")}]`, params = Object.fromEntries(
|
|
3810
4144
|
Object.entries(projections).map(([projectionHash, value]) => {
|
|
3811
|
-
const idsInProjection = Array.from(value.documentIds).flatMap((id) =>
|
|
3812
|
-
getPublishedId(id),
|
|
3813
|
-
getDraftId(id)
|
|
3814
|
-
]);
|
|
4145
|
+
const idsInProjection = Array.from(value.documentIds).flatMap((id) => DocumentId(id));
|
|
3815
4146
|
return [`__ids_${projectionHash}`, Array.from(idsInProjection)];
|
|
3816
4147
|
})
|
|
3817
4148
|
);
|
|
3818
4149
|
return { query, params };
|
|
3819
4150
|
}
|
|
3820
|
-
function processProjectionQuery({
|
|
4151
|
+
function processProjectionQuery({
|
|
4152
|
+
ids,
|
|
4153
|
+
results,
|
|
4154
|
+
documentStatuses
|
|
4155
|
+
}) {
|
|
3821
4156
|
const groupedResults = {};
|
|
3822
4157
|
for (const result of results) {
|
|
3823
|
-
const originalId = getPublishedId(result._id), hash = result.__projectionHash
|
|
3824
|
-
ids.has(originalId) && (groupedResults[originalId] || (groupedResults[originalId] = {}), groupedResults[originalId][hash] || (groupedResults[originalId][hash] =
|
|
4158
|
+
const originalId = getPublishedId(result._id), hash = result.__projectionHash;
|
|
4159
|
+
ids.has(originalId) && (groupedResults[originalId] || (groupedResults[originalId] = {}), groupedResults[originalId][hash] || (groupedResults[originalId][hash] = void 0), groupedResults[originalId][hash] = result);
|
|
3825
4160
|
}
|
|
3826
4161
|
const finalValues = {};
|
|
3827
4162
|
for (const originalId of ids) {
|
|
@@ -3829,27 +4164,40 @@ function processProjectionQuery({ ids, results }) {
|
|
|
3829
4164
|
const projectionsForDoc = groupedResults[originalId];
|
|
3830
4165
|
if (projectionsForDoc)
|
|
3831
4166
|
for (const hash in projectionsForDoc) {
|
|
3832
|
-
const
|
|
4167
|
+
const projectionResultData = projectionsForDoc[hash]?.result;
|
|
3833
4168
|
if (!projectionResultData) {
|
|
3834
4169
|
finalValues[originalId][hash] = { data: null, isPending: !1 };
|
|
3835
4170
|
continue;
|
|
3836
4171
|
}
|
|
3837
|
-
const
|
|
3838
|
-
...draft?._updatedAt && { lastEditedDraftAt: draft._updatedAt },
|
|
3839
|
-
...published?._updatedAt && { lastEditedPublishedAt: published._updatedAt }
|
|
3840
|
-
};
|
|
4172
|
+
const statusFromStore = documentStatuses?.[originalId];
|
|
3841
4173
|
finalValues[originalId][hash] = {
|
|
3842
|
-
data: { ...projectionResultData, _status },
|
|
4174
|
+
data: { ...projectionResultData, _status: statusFromStore },
|
|
3843
4175
|
isPending: !1
|
|
3844
4176
|
};
|
|
3845
4177
|
}
|
|
3846
4178
|
}
|
|
3847
4179
|
return finalValues;
|
|
3848
4180
|
}
|
|
4181
|
+
function buildStatusQueryIds(documentIds, perspective) {
|
|
4182
|
+
const ids = [], releaseName = isReleasePerspective(perspective) ? perspective.releaseName : null;
|
|
4183
|
+
for (const id of documentIds) {
|
|
4184
|
+
const publishedId = getPublishedId$2(DocumentId(id)), draftId = getDraftId$1(publishedId);
|
|
4185
|
+
ids.push(draftId, publishedId), releaseName && ids.push(getVersionId(publishedId, releaseName));
|
|
4186
|
+
}
|
|
4187
|
+
return ids;
|
|
4188
|
+
}
|
|
4189
|
+
function processStatusQueryResults(results) {
|
|
4190
|
+
const documentStatuses = {};
|
|
4191
|
+
for (const result of results) {
|
|
4192
|
+
const id = DocumentId(result._id), updatedAt = result._updatedAt, publishedId = getPublishedId$2(id), statusData = documentStatuses[publishedId] ?? {};
|
|
4193
|
+
isDraftId(id) ? statusData.lastEditedDraftAt = updatedAt : isVersionId(id) ? statusData.lastEditedVersionAt = updatedAt : isPublishedId(id) && (statusData.lastEditedPublishedAt = updatedAt), documentStatuses[publishedId] = statusData;
|
|
4194
|
+
}
|
|
4195
|
+
return documentStatuses;
|
|
4196
|
+
}
|
|
3849
4197
|
const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Array.from(a).every((i) => b.has(i)), subscribeToStateAndFetchBatches = ({
|
|
3850
4198
|
state,
|
|
3851
4199
|
instance,
|
|
3852
|
-
key: {
|
|
4200
|
+
key: { source, perspective }
|
|
3853
4201
|
}) => {
|
|
3854
4202
|
const documentProjections$ = state.observable.pipe(
|
|
3855
4203
|
map((s) => s.documentProjections),
|
|
@@ -3858,7 +4206,7 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
|
|
|
3858
4206
|
map(({ subscriptions }) => new Set(Object.keys(subscriptions))),
|
|
3859
4207
|
distinctUntilChanged(isSetEqual)
|
|
3860
4208
|
), pendingUpdateSubscription = activeDocumentIds$.pipe(
|
|
3861
|
-
debounceTime
|
|
4209
|
+
debounceTime(BATCH_DEBOUNCE_TIME),
|
|
3862
4210
|
startWith$1(/* @__PURE__ */ new Set()),
|
|
3863
4211
|
pairwise$1(),
|
|
3864
4212
|
tap$1(([prevIds, currIds]) => {
|
|
@@ -3882,42 +4230,82 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
|
|
|
3882
4230
|
});
|
|
3883
4231
|
})
|
|
3884
4232
|
).subscribe(), queryExecutionSubscription = combineLatest([activeDocumentIds$, documentProjections$]).pipe(
|
|
3885
|
-
debounceTime
|
|
4233
|
+
debounceTime(BATCH_DEBOUNCE_TIME),
|
|
3886
4234
|
distinctUntilChanged(isEqual)
|
|
3887
4235
|
).pipe(
|
|
3888
4236
|
switchMap(([ids, documentProjections]) => {
|
|
3889
4237
|
if (!ids.size) return EMPTY;
|
|
3890
|
-
const { query, params } = createProjectionQuery(ids, documentProjections), controller = new AbortController()
|
|
3891
|
-
return new Observable((observer) => {
|
|
4238
|
+
const { query, params } = createProjectionQuery(ids, documentProjections), controller = new AbortController(), statusQueryIds = buildStatusQueryIds(ids, perspective), statusQuery = "*[_id in $statusIds]{_id, _updatedAt}", statusParams = { statusIds: statusQueryIds }, projectionQuery$ = new Observable((observer) => {
|
|
3892
4239
|
const { getCurrent, observable } = getQueryState(instance, {
|
|
3893
4240
|
query,
|
|
3894
4241
|
params,
|
|
3895
|
-
projectId,
|
|
3896
|
-
dataset,
|
|
3897
4242
|
tag: PROJECTION_TAG,
|
|
3898
|
-
perspective
|
|
4243
|
+
perspective,
|
|
4244
|
+
// temporary guard here until we're ready for everything to be queried via global API
|
|
4245
|
+
...source && !isDatasetSource(source) ? { source } : {}
|
|
3899
4246
|
}), subscription = defer(() => getCurrent() === void 0 ? from(
|
|
3900
4247
|
resolveQuery(instance, {
|
|
3901
4248
|
query,
|
|
3902
4249
|
params,
|
|
3903
|
-
projectId,
|
|
3904
|
-
dataset,
|
|
3905
4250
|
tag: PROJECTION_TAG,
|
|
3906
|
-
|
|
3907
|
-
|
|
4251
|
+
signal: controller.signal,
|
|
4252
|
+
perspective,
|
|
4253
|
+
// temporary guard here until we're ready for everything to be queried via global API in v3
|
|
4254
|
+
...source && !isDatasetSource(source) ? { source } : {}
|
|
3908
4255
|
})
|
|
3909
4256
|
).pipe(switchMap(() => observable)) : observable).pipe(filter((result) => result !== void 0)).subscribe(observer);
|
|
3910
4257
|
return () => {
|
|
3911
4258
|
controller.signal.aborted || controller.abort(), subscription.unsubscribe();
|
|
3912
4259
|
};
|
|
3913
|
-
})
|
|
4260
|
+
}), statusQuery$ = new Observable((observer) => {
|
|
4261
|
+
const { getCurrent, observable } = getQueryState(instance, {
|
|
4262
|
+
query: statusQuery,
|
|
4263
|
+
params: statusParams,
|
|
4264
|
+
tag: PROJECTION_TAG,
|
|
4265
|
+
perspective: "raw",
|
|
4266
|
+
// temporary guard here until we're ready for everything to be queried via global API
|
|
4267
|
+
...source && !isDatasetSource(source) ? { source } : {}
|
|
4268
|
+
}), subscription = defer(() => getCurrent() === void 0 ? from(
|
|
4269
|
+
resolveQuery(instance, {
|
|
4270
|
+
query: statusQuery,
|
|
4271
|
+
params: statusParams,
|
|
4272
|
+
tag: PROJECTION_TAG,
|
|
4273
|
+
signal: controller.signal,
|
|
4274
|
+
perspective: "raw",
|
|
4275
|
+
// temporary guard here until we're ready for everything to be queried via global API
|
|
4276
|
+
...source && !isDatasetSource(source) ? { source } : {}
|
|
4277
|
+
})
|
|
4278
|
+
).pipe(switchMap(() => observable)) : observable).pipe(filter((result) => result !== void 0)).subscribe(observer);
|
|
4279
|
+
return () => {
|
|
4280
|
+
subscription.unsubscribe();
|
|
4281
|
+
};
|
|
4282
|
+
});
|
|
4283
|
+
return combineLatest([projectionQuery$, statusQuery$]).pipe(
|
|
4284
|
+
filter(
|
|
4285
|
+
(pair) => pair[0] !== void 0 && pair[1] !== void 0
|
|
4286
|
+
),
|
|
4287
|
+
map(([projection, status]) => ({
|
|
4288
|
+
data: projection,
|
|
4289
|
+
ids,
|
|
4290
|
+
statusResults: status
|
|
4291
|
+
}))
|
|
4292
|
+
);
|
|
3914
4293
|
}),
|
|
3915
|
-
map(
|
|
3916
|
-
|
|
4294
|
+
map(({ ids, data, statusResults }) => {
|
|
4295
|
+
const documentStatuses = processStatusQueryResults(statusResults);
|
|
4296
|
+
state.set("updateStatuses", (prev) => ({
|
|
4297
|
+
documentStatuses: {
|
|
4298
|
+
...prev.documentStatuses,
|
|
4299
|
+
...documentStatuses
|
|
4300
|
+
}
|
|
4301
|
+
}));
|
|
4302
|
+
const currentState = state.get();
|
|
4303
|
+
return processProjectionQuery({
|
|
3917
4304
|
ids,
|
|
3918
|
-
results: data
|
|
3919
|
-
|
|
3920
|
-
|
|
4305
|
+
results: data,
|
|
4306
|
+
documentStatuses: currentState.documentStatuses
|
|
4307
|
+
});
|
|
4308
|
+
})
|
|
3921
4309
|
).subscribe({
|
|
3922
4310
|
next: (processedValues) => {
|
|
3923
4311
|
state.set("updateResult", (prev) => {
|
|
@@ -3943,7 +4331,8 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
|
|
|
3943
4331
|
return {
|
|
3944
4332
|
values: {},
|
|
3945
4333
|
documentProjections: {},
|
|
3946
|
-
subscriptions: {}
|
|
4334
|
+
subscriptions: {},
|
|
4335
|
+
documentStatuses: {}
|
|
3947
4336
|
};
|
|
3948
4337
|
},
|
|
3949
4338
|
initialize(context) {
|
|
@@ -3954,15 +4343,15 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
|
|
|
3954
4343
|
function getProjectionState(...args) {
|
|
3955
4344
|
return _getProjectionState(...args);
|
|
3956
4345
|
}
|
|
3957
|
-
const _getProjectionState =
|
|
4346
|
+
const _getProjectionState = bindActionBySourceAndPerspective(
|
|
3958
4347
|
projectionStore,
|
|
3959
4348
|
createStateSourceAction({
|
|
3960
4349
|
selector: ({ state }, options) => {
|
|
3961
|
-
const documentId = getPublishedId(options.documentId), projectionHash = hashString(options.projection);
|
|
4350
|
+
const documentId = getPublishedId$2(DocumentId(options.documentId)), projectionHash = hashString(options.projection);
|
|
3962
4351
|
return state.values[documentId]?.[projectionHash] ?? STABLE_EMPTY_PROJECTION;
|
|
3963
4352
|
},
|
|
3964
4353
|
onSubscribe: ({ state }, options) => {
|
|
3965
|
-
const { projection, ...docHandle } = options, subscriptionId = insecureRandomId(), documentId = getPublishedId(docHandle.documentId), validProjection = validateProjection(projection), projectionHash = hashString(validProjection);
|
|
4354
|
+
const { projection, ...docHandle } = options, subscriptionId = insecureRandomId(), documentId = getPublishedId$2(DocumentId(docHandle.documentId)), validProjection = validateProjection(projection), projectionHash = hashString(validProjection);
|
|
3966
4355
|
return state.set("addSubscription", (prev) => ({
|
|
3967
4356
|
documentProjections: {
|
|
3968
4357
|
...prev.documentProjections,
|
|
@@ -4014,7 +4403,7 @@ const _getProjectionState = bindActionByDataset(
|
|
|
4014
4403
|
function resolveProjection(...args) {
|
|
4015
4404
|
return _resolveProjection(...args);
|
|
4016
4405
|
}
|
|
4017
|
-
const _resolveProjection =
|
|
4406
|
+
const _resolveProjection = bindActionBySourceAndPerspective(
|
|
4018
4407
|
projectionStore,
|
|
4019
4408
|
({ instance }, options) => firstValueFrom(
|
|
4020
4409
|
getProjectionState(instance, options).observable.pipe(
|
|
@@ -4122,7 +4511,7 @@ function getCorsErrorProjectId(error) {
|
|
|
4122
4511
|
const projMatch = (error.message || "").match(/manage\/project\/([^/?#]+)/);
|
|
4123
4512
|
return projMatch ? projMatch[1] : null;
|
|
4124
4513
|
}
|
|
4125
|
-
var version = "2.
|
|
4514
|
+
var version = "2.7.0";
|
|
4126
4515
|
const CORE_SDK_VERSION = getEnv("PKG_VERSION") || `${version}-development`;
|
|
4127
4516
|
export {
|
|
4128
4517
|
AuthStateType,
|
|
@@ -4133,7 +4522,7 @@ export {
|
|
|
4133
4522
|
agentTransform,
|
|
4134
4523
|
agentTranslate,
|
|
4135
4524
|
applyDocumentActions,
|
|
4136
|
-
|
|
4525
|
+
configureLogging,
|
|
4137
4526
|
createDatasetHandle,
|
|
4138
4527
|
createDocument,
|
|
4139
4528
|
createDocumentHandle,
|
|
@@ -4141,7 +4530,6 @@ export {
|
|
|
4141
4530
|
createGroqSearchFilter,
|
|
4142
4531
|
createProjectHandle,
|
|
4143
4532
|
createSanityInstance,
|
|
4144
|
-
datasetSource,
|
|
4145
4533
|
defineIntent,
|
|
4146
4534
|
deleteDocument,
|
|
4147
4535
|
destroyController,
|
|
@@ -4183,12 +4571,15 @@ export {
|
|
|
4183
4571
|
getUsersKey,
|
|
4184
4572
|
getUsersState,
|
|
4185
4573
|
handleAuthCallback,
|
|
4574
|
+
isCanvasSource,
|
|
4575
|
+
isDatasetSource,
|
|
4576
|
+
isMediaLibrarySource,
|
|
4186
4577
|
isProjectUserNotFoundClientError,
|
|
4578
|
+
isStudioConfig,
|
|
4187
4579
|
joinPaths,
|
|
4188
4580
|
jsonMatch2 as jsonMatch,
|
|
4189
4581
|
loadMoreUsers,
|
|
4190
4582
|
logout,
|
|
4191
|
-
mediaLibrarySource,
|
|
4192
4583
|
observeOrganizationVerificationState,
|
|
4193
4584
|
parseQueryKey,
|
|
4194
4585
|
parseUsersKey,
|