@sanity/sdk 2.1.0 → 2.1.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.
- package/dist/index.d.ts +1705 -2163
- package/dist/index.js +497 -187
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/_exports/index.ts +22 -1
- package/src/auth/authStore.ts +1 -0
- package/src/auth/refreshStampedToken.test.ts +225 -6
- package/src/auth/refreshStampedToken.ts +95 -30
- package/src/presence/bifurTransport.test.ts +257 -0
- package/src/presence/bifurTransport.ts +108 -0
- package/src/presence/presenceStore.test.ts +247 -0
- package/src/presence/presenceStore.ts +163 -0
- package/src/presence/types.ts +70 -0
- package/src/query/queryStore.test.ts +4 -1
- package/src/releases/releasesStore.test.ts +5 -2
- package/src/users/reducers.ts +9 -3
- package/src/users/types.ts +17 -0
- package/src/users/usersConstants.ts +1 -0
- package/src/users/usersStore.test.ts +129 -9
- package/src/users/usersStore.ts +132 -4
- package/src/utils/defineIntent.test.ts +477 -0
- package/src/utils/defineIntent.ts +244 -0
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createClient } from "@sanity/client";
|
|
2
|
-
import { Observable, share, map, distinctUntilChanged, skip, filter, exhaustMap, timer,
|
|
2
|
+
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, retry, debounceTime as debounceTime$1 } from "rxjs";
|
|
3
3
|
import { devtools } from "zustand/middleware";
|
|
4
4
|
import { createStore } from "zustand/vanilla";
|
|
5
5
|
import { pick, omit, isEqual, isObject } from "lodash-es";
|
|
@@ -15,6 +15,7 @@ import { applyPatches, parsePatch } from "@sanity/diff-match-patch";
|
|
|
15
15
|
import { isKeySegment, isKeyedObject } from "@sanity/types";
|
|
16
16
|
import { createDocumentLoaderFromClient } from "@sanity/mutate/_unstable_store";
|
|
17
17
|
import { SDK_CHANNEL_NAME, SDK_NODE_NAME } from "@sanity/message-protocol";
|
|
18
|
+
import { fromUrl } from "@sanity/bifur-client";
|
|
18
19
|
var AuthStateType = /* @__PURE__ */ ((AuthStateType2) => (AuthStateType2.LOGGED_IN = "logged-in", AuthStateType2.LOGGING_IN = "logging-in", AuthStateType2.ERROR = "error", AuthStateType2.LOGGED_OUT = "logged-out", AuthStateType2))(AuthStateType || {});
|
|
19
20
|
function getPublishedId(id) {
|
|
20
21
|
const draftsPrefix = "drafts.";
|
|
@@ -86,8 +87,8 @@ function createStoreState(initialState, devToolsOptions) {
|
|
|
86
87
|
})
|
|
87
88
|
};
|
|
88
89
|
}
|
|
89
|
-
function createStoreInstance(instance, { name, getInitialState, initialize }) {
|
|
90
|
-
const state = createStoreState(
|
|
90
|
+
function createStoreInstance(instance, { name, getInitialState: getInitialState2, initialize }) {
|
|
91
|
+
const state = createStoreState(getInitialState2(instance), {
|
|
91
92
|
enabled: !!getEnv("DEV"),
|
|
92
93
|
name: `${name}-${instance.config.projectId}.${instance.config.dataset}`
|
|
93
94
|
}), dispose = initialize?.({ state, instance }), disposed = { current: !1 };
|
|
@@ -168,8 +169,8 @@ function createStateSourceAction(options) {
|
|
|
168
169
|
const DEFAULT_BASE = "http://localhost", AUTH_CODE_PARAM = "sid", DEFAULT_API_VERSION$1 = "2021-06-07", REQUEST_TAG_PREFIX = "sanity.sdk.auth", REFRESH_INTERVAL = 12 * 60 * 60 * 1e3, LOCK_NAME = "sanity-token-refresh-lock";
|
|
169
170
|
function getLastRefreshTime(storageArea, storageKey) {
|
|
170
171
|
try {
|
|
171
|
-
const data = storageArea?.getItem(`${storageKey}_last_refresh`);
|
|
172
|
-
return
|
|
172
|
+
const data = storageArea?.getItem(`${storageKey}_last_refresh`), parsed = data ? parseInt(data, 10) : 0;
|
|
173
|
+
return isNaN(parsed) ? 0 : parsed;
|
|
173
174
|
} catch {
|
|
174
175
|
return 0;
|
|
175
176
|
}
|
|
@@ -227,6 +228,9 @@ async function acquireTokenRefreshLock(refreshFn, storageArea, storageKey) {
|
|
|
227
228
|
return console.error("Failed to request token refresh lock:", error), !1;
|
|
228
229
|
}
|
|
229
230
|
}
|
|
231
|
+
function shouldRefreshToken(lastRefresh) {
|
|
232
|
+
return lastRefresh ? Date.now() - lastRefresh >= REFRESH_INTERVAL : !0;
|
|
233
|
+
}
|
|
230
234
|
const refreshStampedToken = ({ state }) => {
|
|
231
235
|
const { clientFactory, apiHost, storageArea, storageKey } = state.get().options;
|
|
232
236
|
return state.observable.pipe(
|
|
@@ -256,26 +260,69 @@ const refreshStampedToken = ({ state }) => {
|
|
|
256
260
|
authState: prev.authState.type === AuthStateType.LOGGED_IN ? { ...prev.authState, token: response.token } : prev.authState
|
|
257
261
|
})), storageArea?.setItem(storageKey, JSON.stringify({ token: response.token }));
|
|
258
262
|
};
|
|
259
|
-
return storeState.dashboardContext ?
|
|
260
|
-
|
|
263
|
+
return storeState.dashboardContext ? new Observable((subscriber) => {
|
|
264
|
+
const visibilityHandler = () => {
|
|
265
|
+
const currentState = state.get();
|
|
266
|
+
document.visibilityState === "visible" && currentState.authState.type === AuthStateType.LOGGED_IN && shouldRefreshToken(currentState.authState.lastTokenRefresh) && createTokenRefreshStream(
|
|
267
|
+
currentState.authState.token,
|
|
268
|
+
clientFactory,
|
|
269
|
+
apiHost
|
|
270
|
+
).subscribe({
|
|
271
|
+
next: (response) => {
|
|
272
|
+
state.set("setRefreshStampedToken", (prev) => ({
|
|
273
|
+
authState: prev.authState.type === AuthStateType.LOGGED_IN ? {
|
|
274
|
+
...prev.authState,
|
|
275
|
+
token: response.token,
|
|
276
|
+
lastTokenRefresh: Date.now()
|
|
277
|
+
} : prev.authState
|
|
278
|
+
})), subscriber.next(response);
|
|
279
|
+
},
|
|
280
|
+
error: (error) => subscriber.error(error)
|
|
281
|
+
});
|
|
282
|
+
}, timerSubscription = timer(REFRESH_INTERVAL, REFRESH_INTERVAL).pipe(
|
|
283
|
+
filter(() => document.visibilityState === "visible"),
|
|
284
|
+
switchMap(() => {
|
|
285
|
+
const currentState = state.get().authState;
|
|
286
|
+
if (currentState.type !== AuthStateType.LOGGED_IN)
|
|
287
|
+
throw new Error("User logged out before refresh could complete");
|
|
288
|
+
return createTokenRefreshStream(currentState.token, clientFactory, apiHost);
|
|
289
|
+
})
|
|
290
|
+
).subscribe({
|
|
291
|
+
next: (response) => {
|
|
292
|
+
state.set("setRefreshStampedToken", (prev) => ({
|
|
293
|
+
authState: prev.authState.type === AuthStateType.LOGGED_IN ? {
|
|
294
|
+
...prev.authState,
|
|
295
|
+
token: response.token,
|
|
296
|
+
lastTokenRefresh: Date.now()
|
|
297
|
+
} : prev.authState
|
|
298
|
+
})), subscriber.next(response);
|
|
299
|
+
},
|
|
300
|
+
error: (error) => subscriber.error(error)
|
|
301
|
+
});
|
|
302
|
+
return document.addEventListener("visibilitychange", visibilityHandler), () => {
|
|
303
|
+
document.removeEventListener("visibilitychange", visibilityHandler), timerSubscription.unsubscribe();
|
|
304
|
+
};
|
|
305
|
+
}).pipe(
|
|
261
306
|
takeWhile(() => state.get().authState.type === AuthStateType.LOGGED_IN),
|
|
262
|
-
// Use switchMap here: if the timer ticks again, we *do* want the latest token request
|
|
263
|
-
switchMap(
|
|
264
|
-
() => createTokenRefreshStream(storeState.authState.token, clientFactory, apiHost)
|
|
265
|
-
),
|
|
266
|
-
// Map the successful response for the outer subscribe block
|
|
267
307
|
map((response) => ({ token: response.token }))
|
|
268
308
|
) : from(acquireTokenRefreshLock(performRefresh, storageArea, storageKey)).pipe(
|
|
269
309
|
filter((hasLock) => hasLock),
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
310
|
+
map(() => {
|
|
311
|
+
const currentState = state.get().authState;
|
|
312
|
+
if (currentState.type !== AuthStateType.LOGGED_IN)
|
|
313
|
+
throw new Error("User logged out before refresh could complete");
|
|
314
|
+
return { token: currentState.token };
|
|
315
|
+
})
|
|
273
316
|
);
|
|
274
317
|
})
|
|
275
318
|
).subscribe({
|
|
276
319
|
next: (response) => {
|
|
277
320
|
state.set("setRefreshStampedToken", (prev) => ({
|
|
278
|
-
authState: prev.authState.type === AuthStateType.LOGGED_IN ? {
|
|
321
|
+
authState: prev.authState.type === AuthStateType.LOGGED_IN ? {
|
|
322
|
+
...prev.authState,
|
|
323
|
+
token: response.token,
|
|
324
|
+
lastTokenRefresh: Date.now()
|
|
325
|
+
} : prev.authState
|
|
279
326
|
})), storageArea?.setItem(storageKey, JSON.stringify({ token: response.token }));
|
|
280
327
|
},
|
|
281
328
|
error: (error) => {
|
|
@@ -1291,7 +1338,7 @@ function processMutations({
|
|
|
1291
1338
|
throw new Error(
|
|
1292
1339
|
`Cannot create document with \`_id\` \`${id}\` because another document with the same ID already exists.`
|
|
1293
1340
|
);
|
|
1294
|
-
const
|
|
1341
|
+
const document2 = {
|
|
1295
1342
|
// > `_createdAt` and `_updatedAt` may be submitted and will override
|
|
1296
1343
|
// > the default which is of course the current time. This can be used
|
|
1297
1344
|
// > to reconstruct a data-set with its timestamp structure intact.
|
|
@@ -1304,11 +1351,11 @@ function processMutations({
|
|
|
1304
1351
|
_rev: transactionId,
|
|
1305
1352
|
_id: id
|
|
1306
1353
|
};
|
|
1307
|
-
dataset[id] =
|
|
1354
|
+
dataset[id] = document2;
|
|
1308
1355
|
continue;
|
|
1309
1356
|
}
|
|
1310
1357
|
if ("createOrReplace" in mutation) {
|
|
1311
|
-
const id = getId(mutation.createOrReplace._id), prev = dataset[id],
|
|
1358
|
+
const id = getId(mutation.createOrReplace._id), prev = dataset[id], document2 = {
|
|
1312
1359
|
...mutation.createOrReplace,
|
|
1313
1360
|
// otherwise, if the mutation provided, a `_createdAt` time, use it,
|
|
1314
1361
|
// otherwise default to now
|
|
@@ -1335,13 +1382,13 @@ function processMutations({
|
|
|
1335
1382
|
_rev: transactionId,
|
|
1336
1383
|
_id: id
|
|
1337
1384
|
};
|
|
1338
|
-
dataset[id] =
|
|
1385
|
+
dataset[id] = document2;
|
|
1339
1386
|
continue;
|
|
1340
1387
|
}
|
|
1341
1388
|
if ("createIfNotExists" in mutation) {
|
|
1342
1389
|
const id = getId(mutation.createIfNotExists._id);
|
|
1343
1390
|
if (dataset[id]) continue;
|
|
1344
|
-
const
|
|
1391
|
+
const document2 = {
|
|
1345
1392
|
// same logic as `create`:
|
|
1346
1393
|
// prefer the user's `_createdAt` and `_updatedAt`
|
|
1347
1394
|
_createdAt: now,
|
|
@@ -1350,7 +1397,7 @@ function processMutations({
|
|
|
1350
1397
|
_rev: transactionId,
|
|
1351
1398
|
_id: id
|
|
1352
1399
|
};
|
|
1353
|
-
dataset[id] =
|
|
1400
|
+
dataset[id] = document2;
|
|
1354
1401
|
continue;
|
|
1355
1402
|
}
|
|
1356
1403
|
if ("delete" in mutation) {
|
|
@@ -1467,7 +1514,7 @@ const listen$1 = ({ state }, documentId) => {
|
|
|
1467
1514
|
const { sharedListener, fetchDocument } = state.get();
|
|
1468
1515
|
return sharedListener.events.pipe(
|
|
1469
1516
|
concatMap((e3) => e3.type === "welcome" ? fetchDocument(documentId).pipe(
|
|
1470
|
-
map((
|
|
1517
|
+
map((document2) => ({ type: "sync", document: document2 }))
|
|
1471
1518
|
) : e3.type === "mutation" && e3.documentId === documentId ? of(e3) : EMPTY),
|
|
1472
1519
|
sortListenerEvents(),
|
|
1473
1520
|
withLatestFrom(
|
|
@@ -1486,7 +1533,7 @@ const listen$1 = ({ state }, documentId) => {
|
|
|
1486
1533
|
revision: next.document?._rev,
|
|
1487
1534
|
timestamp: next.document?._updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
1488
1535
|
};
|
|
1489
|
-
const [
|
|
1536
|
+
const [document2] = Object.values(
|
|
1490
1537
|
processMutations({
|
|
1491
1538
|
documents: { [documentId]: documentState.remote },
|
|
1492
1539
|
mutations: next.mutations,
|
|
@@ -1497,7 +1544,7 @@ const listen$1 = ({ state }, documentId) => {
|
|
|
1497
1544
|
return {
|
|
1498
1545
|
type: "mutation",
|
|
1499
1546
|
documentId,
|
|
1500
|
-
document:
|
|
1547
|
+
document: document2 ?? null,
|
|
1501
1548
|
revision: transactionId,
|
|
1502
1549
|
timestamp,
|
|
1503
1550
|
...previousRev && { previousRev }
|
|
@@ -3279,8 +3326,8 @@ const documentsCache = new MultiKeyWeakMap(), actionsCache = /* @__PURE__ */ new
|
|
|
3279
3326
|
return nestedCache.get(actionsKey) || (nestedCache.set(actionsKey, normalizedActions), normalizedActions);
|
|
3280
3327
|
}
|
|
3281
3328
|
);
|
|
3282
|
-
function checkGrant$1(grantExpr,
|
|
3283
|
-
return C(grantExpr, { params: { document } }).get();
|
|
3329
|
+
function checkGrant$1(grantExpr, document2) {
|
|
3330
|
+
return C(grantExpr, { params: { document: document2 } }).get();
|
|
3284
3331
|
}
|
|
3285
3332
|
const enNarrowConjunction = new Intl.ListFormat("en", { style: "narrow", type: "conjunction" });
|
|
3286
3333
|
function calculatePermissions(...args) {
|
|
@@ -3343,8 +3390,8 @@ const _calculatePermissions = createSelector(
|
|
|
3343
3390
|
};
|
|
3344
3391
|
}
|
|
3345
3392
|
);
|
|
3346
|
-
function checkGrant(grantExpr,
|
|
3347
|
-
return C(grantExpr, { params: { document } }).get();
|
|
3393
|
+
function checkGrant(grantExpr, document2) {
|
|
3394
|
+
return C(grantExpr, { params: { document: document2 } }).get();
|
|
3348
3395
|
}
|
|
3349
3396
|
class ActionError extends Error {
|
|
3350
3397
|
documentId;
|
|
@@ -3782,7 +3829,7 @@ function revertOutgoingTransaction(prev) {
|
|
|
3782
3829
|
)
|
|
3783
3830
|
};
|
|
3784
3831
|
}
|
|
3785
|
-
function applyRemoteDocument(prev, { document, documentId, previousRev, revision, timestamp, type }, events) {
|
|
3832
|
+
function applyRemoteDocument(prev, { document: document2, documentId, previousRev, revision, timestamp, type }, events) {
|
|
3786
3833
|
if (!prev.grants) return prev;
|
|
3787
3834
|
const prevDocState = prev.documentStates[documentId];
|
|
3788
3835
|
if (!prevDocState) return prev;
|
|
@@ -3797,13 +3844,13 @@ function applyRemoteDocument(prev, { document, documentId, previousRev, revision
|
|
|
3797
3844
|
...prev.documentStates,
|
|
3798
3845
|
[documentId]: {
|
|
3799
3846
|
...prevDocState,
|
|
3800
|
-
remote:
|
|
3847
|
+
remote: document2,
|
|
3801
3848
|
remoteRev: revision,
|
|
3802
3849
|
unverifiedRevisions
|
|
3803
3850
|
}
|
|
3804
3851
|
}
|
|
3805
3852
|
};
|
|
3806
|
-
let working = { ...prev.applied.at(0)?.previous, [documentId]:
|
|
3853
|
+
let working = { ...prev.applied.at(0)?.previous, [documentId]: document2 };
|
|
3807
3854
|
const nextApplied = [];
|
|
3808
3855
|
for (const curr of prev.applied)
|
|
3809
3856
|
try {
|
|
@@ -3829,7 +3876,7 @@ function applyRemoteDocument(prev, { document, documentId, previousRev, revision
|
|
|
3829
3876
|
...prev.documentStates,
|
|
3830
3877
|
[documentId]: {
|
|
3831
3878
|
...prevDocState,
|
|
3832
|
-
remote:
|
|
3879
|
+
remote: document2,
|
|
3833
3880
|
remoteRev: revision,
|
|
3834
3881
|
local: working[documentId],
|
|
3835
3882
|
unverifiedRevisions
|
|
@@ -4005,9 +4052,9 @@ const _getDocumentState = bindActionByDataset(
|
|
|
4005
4052
|
if (error) throw error;
|
|
4006
4053
|
const draftId = getDraftId(documentId), publishedId = getPublishedId$1(documentId), draft = documentStates[draftId]?.local, published = documentStates[publishedId]?.local;
|
|
4007
4054
|
if (draft === void 0 || published === void 0) return;
|
|
4008
|
-
const
|
|
4009
|
-
if (!path) return
|
|
4010
|
-
const result = jsonMatch(
|
|
4055
|
+
const document2 = draft ?? published;
|
|
4056
|
+
if (!path) return document2;
|
|
4057
|
+
const result = jsonMatch(document2, path).next();
|
|
4011
4058
|
if (result.done) return;
|
|
4012
4059
|
const { value } = result.value;
|
|
4013
4060
|
return value;
|
|
@@ -4291,7 +4338,356 @@ const favorites = createFetcherStore({
|
|
|
4291
4338
|
})
|
|
4292
4339
|
);
|
|
4293
4340
|
}
|
|
4294
|
-
}), getFavoritesState = favorites.getState, resolveFavoritesState = favorites.resolveState,
|
|
4341
|
+
}), getFavoritesState = favorites.getState, resolveFavoritesState = favorites.resolveState, API_VERSION$1 = "vX", PROJECT_API_VERSION = "2025-07-18", USERS_STATE_CLEAR_DELAY = 5e3, DEFAULT_USERS_BATCH_SIZE = 100, getUsersKey = (instance, {
|
|
4342
|
+
resourceType,
|
|
4343
|
+
organizationId,
|
|
4344
|
+
batchSize = DEFAULT_USERS_BATCH_SIZE,
|
|
4345
|
+
projectId = instance.config.projectId,
|
|
4346
|
+
userId
|
|
4347
|
+
} = {}) => JSON.stringify({
|
|
4348
|
+
resourceType,
|
|
4349
|
+
organizationId,
|
|
4350
|
+
batchSize,
|
|
4351
|
+
projectId,
|
|
4352
|
+
userId
|
|
4353
|
+
}), parseUsersKey = (key) => JSON.parse(key), addSubscription = (subscriptionId, key) => (prev) => {
|
|
4354
|
+
const group = prev.users[key], subscriptions = [...group?.subscriptions ?? [], subscriptionId];
|
|
4355
|
+
return { ...prev, users: { ...prev.users, [key]: { ...group, subscriptions } } };
|
|
4356
|
+
}, removeSubscription = (subscriptionId, key) => (prev) => {
|
|
4357
|
+
const group = prev.users[key];
|
|
4358
|
+
if (!group) return prev;
|
|
4359
|
+
const subscriptions = group.subscriptions.filter((id) => id !== subscriptionId);
|
|
4360
|
+
return subscriptions.length ? { ...prev, users: { ...prev.users, [key]: { ...group, subscriptions } } } : { ...prev, users: omit(prev.users, key) };
|
|
4361
|
+
}, setUsersData = (key, { data, nextCursor, totalCount }) => (prev) => {
|
|
4362
|
+
const group = prev.users[key];
|
|
4363
|
+
if (!group) return prev;
|
|
4364
|
+
const users = [...group.users ?? [], ...data];
|
|
4365
|
+
return { ...prev, users: { ...prev.users, [key]: { ...group, users, totalCount, nextCursor } } };
|
|
4366
|
+
}, updateLastLoadMoreRequest = (timestamp, key) => (prev) => {
|
|
4367
|
+
const group = prev.users[key];
|
|
4368
|
+
return group ? { ...prev, users: { ...prev.users, [key]: { ...group, lastLoadMoreRequest: timestamp } } } : prev;
|
|
4369
|
+
}, setUsersError = (key, error) => (prev) => {
|
|
4370
|
+
const group = prev.users[key];
|
|
4371
|
+
return group ? { ...prev, users: { ...prev.users, [key]: { ...group, error } } } : prev;
|
|
4372
|
+
}, cancelRequest = (key) => (prev) => {
|
|
4373
|
+
const group = prev.users[key];
|
|
4374
|
+
return !group || group.subscriptions.length ? prev : { ...prev, users: omit(prev.users, key) };
|
|
4375
|
+
}, initializeRequest = (key) => (prev) => prev.users[key] ? prev : { ...prev, users: { ...prev.users, [key]: { subscriptions: [] } } }, usersStore = {
|
|
4376
|
+
name: "UsersStore",
|
|
4377
|
+
getInitialState: () => ({ users: {} }),
|
|
4378
|
+
initialize: (context) => {
|
|
4379
|
+
const subscription = listenForLoadMoreAndFetch(context);
|
|
4380
|
+
return () => subscription.unsubscribe();
|
|
4381
|
+
}
|
|
4382
|
+
}, errorHandler$1 = (state) => (error) => state.set("setError", { error }), listenForLoadMoreAndFetch = ({ state, instance }) => state.observable.pipe(
|
|
4383
|
+
map((s2) => new Set(Object.keys(s2.users))),
|
|
4384
|
+
distinctUntilChanged((curr, next) => curr.size !== next.size ? !1 : Array.from(next).every((i2) => curr.has(i2))),
|
|
4385
|
+
startWith$1(/* @__PURE__ */ new Set()),
|
|
4386
|
+
pairwise$1(),
|
|
4387
|
+
mergeMap$1(([curr, next]) => {
|
|
4388
|
+
const added = Array.from(next).filter((i2) => !curr.has(i2)), removed = Array.from(curr).filter((i2) => !next.has(i2));
|
|
4389
|
+
return [
|
|
4390
|
+
...added.map((key) => ({ key, added: !0 })),
|
|
4391
|
+
...removed.map((key) => ({ key, added: !1 }))
|
|
4392
|
+
];
|
|
4393
|
+
}),
|
|
4394
|
+
groupBy$1((i2) => i2.key),
|
|
4395
|
+
mergeMap$1(
|
|
4396
|
+
(group$) => group$.pipe(
|
|
4397
|
+
switchMap((e3) => {
|
|
4398
|
+
if (!e3.added) return EMPTY;
|
|
4399
|
+
const { userId, batchSize, ...options } = parseUsersKey(group$.key);
|
|
4400
|
+
if (userId) {
|
|
4401
|
+
if (userId.startsWith("p"))
|
|
4402
|
+
return getClient(instance, {
|
|
4403
|
+
apiVersion: PROJECT_API_VERSION,
|
|
4404
|
+
// this is a global store, so we need to use the projectId from the options when we're fetching
|
|
4405
|
+
// users from a project subdomain
|
|
4406
|
+
projectId: options.projectId,
|
|
4407
|
+
useProjectHostname: !0
|
|
4408
|
+
}).observable.request({
|
|
4409
|
+
method: "GET",
|
|
4410
|
+
uri: `/users/${userId}`
|
|
4411
|
+
}).pipe(
|
|
4412
|
+
map((user) => ({
|
|
4413
|
+
data: [{
|
|
4414
|
+
sanityUserId: user.sanityUserId,
|
|
4415
|
+
profile: {
|
|
4416
|
+
id: user.id,
|
|
4417
|
+
displayName: user.displayName,
|
|
4418
|
+
familyName: user.familyName ?? void 0,
|
|
4419
|
+
givenName: user.givenName ?? void 0,
|
|
4420
|
+
middleName: user.middleName ?? void 0,
|
|
4421
|
+
imageUrl: user.imageUrl ?? void 0,
|
|
4422
|
+
createdAt: user.createdAt,
|
|
4423
|
+
updatedAt: user.updatedAt,
|
|
4424
|
+
isCurrentUser: user.isCurrentUser,
|
|
4425
|
+
email: user.email,
|
|
4426
|
+
provider: user.provider
|
|
4427
|
+
},
|
|
4428
|
+
memberships: []
|
|
4429
|
+
}],
|
|
4430
|
+
totalCount: 1,
|
|
4431
|
+
nextCursor: null
|
|
4432
|
+
})),
|
|
4433
|
+
catchError$1((error) => (state.set("setUsersError", setUsersError(group$.key, error)), EMPTY)),
|
|
4434
|
+
tap$1(
|
|
4435
|
+
(response) => state.set("setUsersData", setUsersData(group$.key, response))
|
|
4436
|
+
)
|
|
4437
|
+
);
|
|
4438
|
+
const scope = userId.startsWith("g") ? "global" : void 0, client = getClient(instance, {
|
|
4439
|
+
scope,
|
|
4440
|
+
apiVersion: API_VERSION$1
|
|
4441
|
+
}), resourceType2 = options.resourceType || "project", resourceId = resourceType2 === "organization" ? options.organizationId : options.projectId;
|
|
4442
|
+
return resourceId ? client.observable.request({
|
|
4443
|
+
method: "GET",
|
|
4444
|
+
uri: `access/${resourceType2}/${resourceId}/users/${userId}`
|
|
4445
|
+
}).pipe(
|
|
4446
|
+
map((response) => "sanityUserId" in response ? {
|
|
4447
|
+
data: [response],
|
|
4448
|
+
totalCount: 1,
|
|
4449
|
+
nextCursor: null
|
|
4450
|
+
} : response),
|
|
4451
|
+
catchError$1((error) => (state.set("setUsersError", setUsersError(group$.key, error)), EMPTY)),
|
|
4452
|
+
tap$1((response) => state.set("setUsersData", setUsersData(group$.key, response)))
|
|
4453
|
+
) : throwError(() => new Error("An organizationId or a projectId is required"));
|
|
4454
|
+
}
|
|
4455
|
+
const projectId = options.projectId, resourceType = options.resourceType ?? (options.organizationId ? "organization" : projectId ? "project" : "organization"), organizationId$ = options.organizationId ? of(options.organizationId) : getDashboardOrganizationId$1(instance).observable.pipe(
|
|
4456
|
+
filter((i2) => typeof i2 == "string")
|
|
4457
|
+
), resource$ = resourceType === "project" ? projectId ? of({ type: "project", id: projectId }) : throwError(() => new Error("Project ID required for this API.")) : organizationId$.pipe(map((id) => ({ type: "organization", id }))), client$ = getClientState(instance, {
|
|
4458
|
+
scope: "global",
|
|
4459
|
+
apiVersion: API_VERSION$1
|
|
4460
|
+
}).observable, loadMore$ = state.observable.pipe(
|
|
4461
|
+
map((s2) => s2.users[group$.key]?.lastLoadMoreRequest),
|
|
4462
|
+
distinctUntilChanged()
|
|
4463
|
+
), cursor$ = state.observable.pipe(
|
|
4464
|
+
map((s2) => s2.users[group$.key]?.nextCursor),
|
|
4465
|
+
distinctUntilChanged(),
|
|
4466
|
+
filter((cursor) => cursor !== null)
|
|
4467
|
+
);
|
|
4468
|
+
return combineLatest([resource$, client$, loadMore$]).pipe(
|
|
4469
|
+
withLatestFrom(cursor$),
|
|
4470
|
+
switchMap(
|
|
4471
|
+
([[resource, client], cursor]) => client.observable.request({
|
|
4472
|
+
method: "GET",
|
|
4473
|
+
uri: `access/${resource.type}/${resource.id}/users`,
|
|
4474
|
+
query: cursor ? { nextCursor: cursor, limit: batchSize.toString() } : { limit: batchSize.toString() }
|
|
4475
|
+
})
|
|
4476
|
+
),
|
|
4477
|
+
catchError$1((error) => (state.set("setUsersError", setUsersError(group$.key, error)), EMPTY)),
|
|
4478
|
+
tap$1((response) => state.set("setUsersData", setUsersData(group$.key, response)))
|
|
4479
|
+
);
|
|
4480
|
+
})
|
|
4481
|
+
)
|
|
4482
|
+
)
|
|
4483
|
+
).subscribe({ error: errorHandler$1(state) }), getUsersState = bindActionGlobally(
|
|
4484
|
+
usersStore,
|
|
4485
|
+
createStateSourceAction({
|
|
4486
|
+
selector: createSelector(
|
|
4487
|
+
[
|
|
4488
|
+
({ instance, state }, options) => state.error ?? state.users[getUsersKey(instance, options)]?.error,
|
|
4489
|
+
({ instance, state }, options) => state.users[getUsersKey(instance, options)]?.users,
|
|
4490
|
+
({ instance, state }, options) => state.users[getUsersKey(instance, options)]?.totalCount,
|
|
4491
|
+
({ instance, state }, options) => state.users[getUsersKey(instance, options)]?.nextCursor
|
|
4492
|
+
],
|
|
4493
|
+
(error, data, totalCount, nextCursor) => {
|
|
4494
|
+
if (error) throw error;
|
|
4495
|
+
if (!(data === void 0 || totalCount === void 0 || nextCursor === void 0))
|
|
4496
|
+
return { data, totalCount, hasMore: nextCursor !== null };
|
|
4497
|
+
}
|
|
4498
|
+
),
|
|
4499
|
+
onSubscribe: ({ instance, state }, options) => {
|
|
4500
|
+
const subscriptionId = insecureRandomId(), key = getUsersKey(instance, options);
|
|
4501
|
+
return state.set("addSubscription", addSubscription(subscriptionId, key)), () => {
|
|
4502
|
+
setTimeout(
|
|
4503
|
+
() => state.set("removeSubscription", removeSubscription(subscriptionId, key)),
|
|
4504
|
+
USERS_STATE_CLEAR_DELAY
|
|
4505
|
+
);
|
|
4506
|
+
};
|
|
4507
|
+
}
|
|
4508
|
+
})
|
|
4509
|
+
), resolveUsers = bindActionGlobally(
|
|
4510
|
+
usersStore,
|
|
4511
|
+
async ({ state, instance }, { signal, ...options }) => {
|
|
4512
|
+
const key = getUsersKey(instance, options), { getCurrent } = getUsersState(instance, options), aborted$ = signal ? new Observable((observer) => {
|
|
4513
|
+
const cleanup = () => {
|
|
4514
|
+
signal.removeEventListener("abort", listener);
|
|
4515
|
+
}, listener = () => {
|
|
4516
|
+
observer.error(new DOMException("The operation was aborted.", "AbortError")), observer.complete(), cleanup();
|
|
4517
|
+
};
|
|
4518
|
+
return signal.addEventListener("abort", listener), cleanup;
|
|
4519
|
+
}).pipe(
|
|
4520
|
+
catchError$1((error) => {
|
|
4521
|
+
throw error instanceof Error && error.name === "AbortError" && state.set("cancelRequest", cancelRequest(key)), error;
|
|
4522
|
+
})
|
|
4523
|
+
) : NEVER;
|
|
4524
|
+
state.set("initializeRequest", initializeRequest(key));
|
|
4525
|
+
const resolved$ = state.observable.pipe(
|
|
4526
|
+
map(getCurrent),
|
|
4527
|
+
first$1((i2) => i2 !== void 0)
|
|
4528
|
+
);
|
|
4529
|
+
return firstValueFrom(race([resolved$, aborted$]));
|
|
4530
|
+
}
|
|
4531
|
+
), loadMoreUsers = bindActionGlobally(
|
|
4532
|
+
usersStore,
|
|
4533
|
+
async ({ state, instance }, options) => {
|
|
4534
|
+
const key = getUsersKey(instance, options), users = getUsersState(instance, options), usersState = users.getCurrent();
|
|
4535
|
+
if (!usersState)
|
|
4536
|
+
throw new Error("Users not loaded for specified resource. Please call resolveUsers first.");
|
|
4537
|
+
if (!usersState.hasMore)
|
|
4538
|
+
throw new Error("No more users available to load for this resource.");
|
|
4539
|
+
const promise = firstValueFrom(
|
|
4540
|
+
users.observable.pipe(
|
|
4541
|
+
filter((i2) => i2 !== void 0),
|
|
4542
|
+
skip(1)
|
|
4543
|
+
)
|
|
4544
|
+
), timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
4545
|
+
return state.set("updateLastLoadMoreRequest", updateLastLoadMoreRequest(timestamp, key)), await promise;
|
|
4546
|
+
}
|
|
4547
|
+
), getUserState = bindActionGlobally(
|
|
4548
|
+
usersStore,
|
|
4549
|
+
({ instance }, { userId, ...options }) => getUsersState(instance, { userId, ...options }).observable.pipe(
|
|
4550
|
+
map((res) => res?.data[0]),
|
|
4551
|
+
distinctUntilChanged((a2, b2) => a2?.profile.updatedAt === b2?.profile.updatedAt)
|
|
4552
|
+
)
|
|
4553
|
+
), resolveUser = bindActionGlobally(
|
|
4554
|
+
usersStore,
|
|
4555
|
+
async ({ instance }, { signal, ...options }) => (await resolveUsers(instance, {
|
|
4556
|
+
signal,
|
|
4557
|
+
...options
|
|
4558
|
+
}))?.data[0]
|
|
4559
|
+
);
|
|
4560
|
+
function getBifurClient(client, token$) {
|
|
4561
|
+
const bifurVersionedClient = client.withConfig({ apiVersion: "2022-06-30" }), { dataset, url: baseUrl, requestTagPrefix = "sanity.studio" } = bifurVersionedClient.config(), urlWithTag = `${`${baseUrl.replace(/\/+$/, "")}/socket/${dataset}`.replace(/^http/, "ws")}?tag=${requestTagPrefix}`;
|
|
4562
|
+
return fromUrl(urlWithTag, { token$ });
|
|
4563
|
+
}
|
|
4564
|
+
const handleIncomingMessage = (event) => {
|
|
4565
|
+
switch (event.type) {
|
|
4566
|
+
case "rollCall":
|
|
4567
|
+
return {
|
|
4568
|
+
type: "rollCall",
|
|
4569
|
+
userId: event.i,
|
|
4570
|
+
sessionId: event.session
|
|
4571
|
+
};
|
|
4572
|
+
case "state": {
|
|
4573
|
+
const { sessionId, locations } = event.m;
|
|
4574
|
+
return {
|
|
4575
|
+
type: "state",
|
|
4576
|
+
userId: event.i,
|
|
4577
|
+
sessionId,
|
|
4578
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4579
|
+
locations
|
|
4580
|
+
};
|
|
4581
|
+
}
|
|
4582
|
+
case "disconnect":
|
|
4583
|
+
return {
|
|
4584
|
+
type: "disconnect",
|
|
4585
|
+
userId: event.i,
|
|
4586
|
+
sessionId: event.m.session,
|
|
4587
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4588
|
+
};
|
|
4589
|
+
default:
|
|
4590
|
+
throw new Error(`Got unknown presence event: ${JSON.stringify(event)}`);
|
|
4591
|
+
}
|
|
4592
|
+
}, createBifurTransport = (options) => {
|
|
4593
|
+
const { client, token$, sessionId } = options, bifur = getBifurClient(client, token$), incomingEvents$ = bifur.listen("presence").pipe(map$1(handleIncomingMessage)), dispatchMessage = (message) => {
|
|
4594
|
+
switch (message.type) {
|
|
4595
|
+
case "rollCall":
|
|
4596
|
+
return bifur.request("presence_rollcall", { session: sessionId });
|
|
4597
|
+
case "state":
|
|
4598
|
+
return bifur.request("presence_announce", {
|
|
4599
|
+
data: { locations: message.locations, sessionId }
|
|
4600
|
+
});
|
|
4601
|
+
case "disconnect":
|
|
4602
|
+
return bifur.request("presence_disconnect", { session: sessionId });
|
|
4603
|
+
default:
|
|
4604
|
+
return EMPTY;
|
|
4605
|
+
}
|
|
4606
|
+
};
|
|
4607
|
+
return typeof window < "u" && fromEvent(window, "beforeunload").pipe(switchMap$1(() => dispatchMessage({ type: "disconnect" }))).subscribe(), [incomingEvents$.pipe(share$1()), dispatchMessage];
|
|
4608
|
+
}, getInitialState = () => ({
|
|
4609
|
+
locations: /* @__PURE__ */ new Map(),
|
|
4610
|
+
users: {}
|
|
4611
|
+
}), presenceStore = {
|
|
4612
|
+
name: "presence",
|
|
4613
|
+
getInitialState,
|
|
4614
|
+
initialize: (context) => {
|
|
4615
|
+
const { instance, state } = context, sessionId = crypto.randomUUID(), client = getClient(instance, {
|
|
4616
|
+
apiVersion: "2022-06-30"
|
|
4617
|
+
}), token$ = getTokenState(instance).observable.pipe(distinctUntilChanged()), [incomingEvents$, dispatch] = createBifurTransport({
|
|
4618
|
+
client,
|
|
4619
|
+
token$,
|
|
4620
|
+
sessionId
|
|
4621
|
+
}), subscription = new Subscription();
|
|
4622
|
+
return subscription.add(
|
|
4623
|
+
incomingEvents$.subscribe((event) => {
|
|
4624
|
+
"sessionId" in event && event.sessionId === sessionId || (event.type === "state" ? state.set("presence/state", (prevState) => {
|
|
4625
|
+
const newLocations = new Map(prevState.locations);
|
|
4626
|
+
return newLocations.set(event.sessionId, {
|
|
4627
|
+
userId: event.userId,
|
|
4628
|
+
locations: event.locations
|
|
4629
|
+
}), {
|
|
4630
|
+
...prevState,
|
|
4631
|
+
locations: newLocations
|
|
4632
|
+
};
|
|
4633
|
+
}) : event.type === "disconnect" && state.set("presence/disconnect", (prevState) => {
|
|
4634
|
+
const newLocations = new Map(prevState.locations);
|
|
4635
|
+
return newLocations.delete(event.sessionId), { ...prevState, locations: newLocations };
|
|
4636
|
+
}));
|
|
4637
|
+
})
|
|
4638
|
+
), dispatch({ type: "rollCall" }).subscribe(), () => {
|
|
4639
|
+
dispatch({ type: "disconnect" }).subscribe(), subscription.unsubscribe();
|
|
4640
|
+
};
|
|
4641
|
+
}
|
|
4642
|
+
}, selectLocations = (state) => state.locations, selectUsers = (state) => state.users, selectPresence = createSelector(
|
|
4643
|
+
selectLocations,
|
|
4644
|
+
selectUsers,
|
|
4645
|
+
(locations, users) => Array.from(locations.entries()).map(([sessionId, { userId, locations: locs }]) => ({
|
|
4646
|
+
user: users[userId] || {
|
|
4647
|
+
id: userId,
|
|
4648
|
+
displayName: "Unknown user",
|
|
4649
|
+
name: "Unknown user",
|
|
4650
|
+
email: ""
|
|
4651
|
+
},
|
|
4652
|
+
sessionId,
|
|
4653
|
+
locations: locs
|
|
4654
|
+
}))
|
|
4655
|
+
), getPresence = bindActionByDataset(
|
|
4656
|
+
presenceStore,
|
|
4657
|
+
createStateSourceAction({
|
|
4658
|
+
selector: (context) => selectPresence(context.state),
|
|
4659
|
+
onSubscribe: (context) => {
|
|
4660
|
+
const subscription = context.state.observable.pipe(
|
|
4661
|
+
map(
|
|
4662
|
+
(state) => Array.from(state.locations.values()).map((l2) => l2.userId).filter((id) => !!id)
|
|
4663
|
+
),
|
|
4664
|
+
distinctUntilChanged((a2, b2) => a2.length === b2.length && a2.every((v2, i2) => v2 === b2[i2]))
|
|
4665
|
+
).pipe(
|
|
4666
|
+
switchMap((userIds) => {
|
|
4667
|
+
if (userIds.length === 0)
|
|
4668
|
+
return of([]);
|
|
4669
|
+
const userObservables = userIds.map(
|
|
4670
|
+
(userId) => getUserState(context.instance, {
|
|
4671
|
+
userId,
|
|
4672
|
+
resourceType: "project",
|
|
4673
|
+
projectId: context.instance.config.projectId
|
|
4674
|
+
}).pipe(filter((v2) => !!v2))
|
|
4675
|
+
);
|
|
4676
|
+
return combineLatest(userObservables);
|
|
4677
|
+
})
|
|
4678
|
+
).subscribe((users) => {
|
|
4679
|
+
users && context.state.set("presence/users", (prevState) => ({
|
|
4680
|
+
...prevState,
|
|
4681
|
+
users: {
|
|
4682
|
+
...prevState.users,
|
|
4683
|
+
...users.reduce((acc, user) => (user && (acc[user.profile.id] = user), acc), {})
|
|
4684
|
+
}
|
|
4685
|
+
}));
|
|
4686
|
+
});
|
|
4687
|
+
return () => subscription.unsubscribe();
|
|
4688
|
+
}
|
|
4689
|
+
})
|
|
4690
|
+
), fetch = (client, query, params, options) => defer(
|
|
4295
4691
|
() => client.observable.fetch(query, params, {
|
|
4296
4692
|
tag: options.tag,
|
|
4297
4693
|
filterResponse: !0
|
|
@@ -4452,7 +4848,7 @@ const DEFAULT_PERSPECTIVE = "drafts", optionsCache = /* @__PURE__ */ new Map(),
|
|
|
4452
4848
|
subscription.unsubscribe();
|
|
4453
4849
|
};
|
|
4454
4850
|
}
|
|
4455
|
-
}, errorHandler
|
|
4851
|
+
}, errorHandler = (state) => (error) => state.set("setError", { error }), listenForNewSubscribersAndFetch = ({ state, instance }) => state.observable.pipe(
|
|
4456
4852
|
map((s2) => new Set(Object.keys(s2.queries))),
|
|
4457
4853
|
distinctUntilChanged((curr, next) => curr.size !== next.size ? !1 : Array.from(next).every((i2) => curr.has(i2))),
|
|
4458
4854
|
startWith$1(/* @__PURE__ */ new Set()),
|
|
@@ -4506,7 +4902,7 @@ const DEFAULT_PERSPECTIVE = "drafts", optionsCache = /* @__PURE__ */ new Map(),
|
|
|
4506
4902
|
})
|
|
4507
4903
|
)
|
|
4508
4904
|
)
|
|
4509
|
-
).subscribe({ error: errorHandler
|
|
4905
|
+
).subscribe({ error: errorHandler(state) }), listenToLiveClientAndSetLastLiveEventIds = ({
|
|
4510
4906
|
state,
|
|
4511
4907
|
instance
|
|
4512
4908
|
}) => {
|
|
@@ -4535,7 +4931,7 @@ const DEFAULT_PERSPECTIVE = "drafts", optionsCache = /* @__PURE__ */ new Map(),
|
|
|
4535
4931
|
})
|
|
4536
4932
|
);
|
|
4537
4933
|
})
|
|
4538
|
-
).subscribe({ error: errorHandler
|
|
4934
|
+
).subscribe({ error: errorHandler(state) });
|
|
4539
4935
|
};
|
|
4540
4936
|
function getQueryState(...args) {
|
|
4541
4937
|
return _getQueryState(...args);
|
|
@@ -5020,159 +5416,16 @@ const _resolveProjection = bindActionByDataset(
|
|
|
5020
5416
|
filter((state) => !!state?.data)
|
|
5021
5417
|
)
|
|
5022
5418
|
)
|
|
5023
|
-
), API_VERSION
|
|
5419
|
+
), API_VERSION = "v2025-02-19", projects = createFetcherStore({
|
|
5024
5420
|
name: "Projects",
|
|
5025
5421
|
getKey: () => "projects",
|
|
5026
5422
|
fetcher: (instance) => () => getClientState(instance, {
|
|
5027
|
-
apiVersion: API_VERSION
|
|
5423
|
+
apiVersion: API_VERSION,
|
|
5028
5424
|
scope: "global"
|
|
5029
5425
|
}).observable.pipe(
|
|
5030
5426
|
switchMap((client) => client.observable.projects.list({ includeMembers: !1 }))
|
|
5031
5427
|
)
|
|
5032
|
-
}), getProjectsState = projects.getState, resolveProjects = projects.resolveState,
|
|
5033
|
-
resourceType,
|
|
5034
|
-
organizationId,
|
|
5035
|
-
batchSize = DEFAULT_USERS_BATCH_SIZE,
|
|
5036
|
-
projectId = instance.config.projectId
|
|
5037
|
-
} = {}) => JSON.stringify({ resourceType, organizationId, batchSize, projectId }), parseUsersKey = (key) => JSON.parse(key), addSubscription = (subscriptionId, key) => (prev) => {
|
|
5038
|
-
const group = prev.users[key], subscriptions = [...group?.subscriptions ?? [], subscriptionId];
|
|
5039
|
-
return { ...prev, users: { ...prev.users, [key]: { ...group, subscriptions } } };
|
|
5040
|
-
}, removeSubscription = (subscriptionId, key) => (prev) => {
|
|
5041
|
-
const group = prev.users[key];
|
|
5042
|
-
if (!group) return prev;
|
|
5043
|
-
const subscriptions = group.subscriptions.filter((id) => id !== subscriptionId);
|
|
5044
|
-
return subscriptions.length ? { ...prev, users: { ...prev.users, [key]: { ...group, subscriptions } } } : { ...prev, users: omit(prev.users, key) };
|
|
5045
|
-
}, setUsersData = (key, { data, nextCursor, totalCount }) => (prev) => {
|
|
5046
|
-
const group = prev.users[key];
|
|
5047
|
-
if (!group) return prev;
|
|
5048
|
-
const users = [...group.users ?? [], ...data];
|
|
5049
|
-
return { ...prev, users: { ...prev.users, [key]: { ...group, users, totalCount, nextCursor } } };
|
|
5050
|
-
}, updateLastLoadMoreRequest = (timestamp, key) => (prev) => {
|
|
5051
|
-
const group = prev.users[key];
|
|
5052
|
-
return group ? { ...prev, users: { ...prev.users, [key]: { ...group, lastLoadMoreRequest: timestamp } } } : prev;
|
|
5053
|
-
}, setUsersError = (key, error) => (prev) => {
|
|
5054
|
-
const group = prev.users[key];
|
|
5055
|
-
return group ? { ...prev, users: { ...prev.users, [key]: { ...group, error } } } : prev;
|
|
5056
|
-
}, cancelRequest = (key) => (prev) => {
|
|
5057
|
-
const group = prev.users[key];
|
|
5058
|
-
return !group || group.subscriptions.length ? prev : { ...prev, users: omit(prev.users, key) };
|
|
5059
|
-
}, initializeRequest = (key) => (prev) => prev.users[key] ? prev : { ...prev, users: { ...prev.users, [key]: { subscriptions: [] } } }, usersStore = {
|
|
5060
|
-
name: "UsersStore",
|
|
5061
|
-
getInitialState: () => ({ users: {} }),
|
|
5062
|
-
initialize: (context) => {
|
|
5063
|
-
const subscription = listenForLoadMoreAndFetch(context);
|
|
5064
|
-
return () => subscription.unsubscribe();
|
|
5065
|
-
}
|
|
5066
|
-
}, errorHandler = (state) => (error) => state.set("setError", { error }), listenForLoadMoreAndFetch = ({ state, instance }) => state.observable.pipe(
|
|
5067
|
-
map((s2) => new Set(Object.keys(s2.users))),
|
|
5068
|
-
distinctUntilChanged((curr, next) => curr.size !== next.size ? !1 : Array.from(next).every((i2) => curr.has(i2))),
|
|
5069
|
-
startWith$1(/* @__PURE__ */ new Set()),
|
|
5070
|
-
pairwise$1(),
|
|
5071
|
-
mergeMap$1(([curr, next]) => {
|
|
5072
|
-
const added = Array.from(next).filter((i2) => !curr.has(i2)), removed = Array.from(curr).filter((i2) => !next.has(i2));
|
|
5073
|
-
return [
|
|
5074
|
-
...added.map((key) => ({ key, added: !0 })),
|
|
5075
|
-
...removed.map((key) => ({ key, added: !1 }))
|
|
5076
|
-
];
|
|
5077
|
-
}),
|
|
5078
|
-
groupBy$1((i2) => i2.key),
|
|
5079
|
-
mergeMap$1(
|
|
5080
|
-
(group$) => group$.pipe(
|
|
5081
|
-
switchMap((e3) => {
|
|
5082
|
-
if (!e3.added) return EMPTY;
|
|
5083
|
-
const { batchSize, ...options } = parseUsersKey(group$.key), projectId = options.projectId ?? instance.config.projectId, resourceType = options.resourceType ?? (options.organizationId ? "organization" : projectId ? "project" : "organization"), organizationId$ = options.organizationId ? of(options.organizationId) : getDashboardOrganizationId$1(instance).observable.pipe(
|
|
5084
|
-
filter((i2) => typeof i2 == "string")
|
|
5085
|
-
), resource$ = resourceType === "project" ? projectId ? of({ type: "project", id: projectId }) : throwError(() => new Error("Project ID required for this API.")) : organizationId$.pipe(map((id) => ({ type: "organization", id }))), client$ = getClientState(instance, {
|
|
5086
|
-
scope: "global",
|
|
5087
|
-
apiVersion: API_VERSION
|
|
5088
|
-
}).observable, loadMore$ = state.observable.pipe(
|
|
5089
|
-
map((s2) => s2.users[group$.key]?.lastLoadMoreRequest),
|
|
5090
|
-
distinctUntilChanged()
|
|
5091
|
-
), cursor$ = state.observable.pipe(
|
|
5092
|
-
map((s2) => s2.users[group$.key]?.nextCursor),
|
|
5093
|
-
distinctUntilChanged(),
|
|
5094
|
-
filter((cursor) => cursor !== null)
|
|
5095
|
-
);
|
|
5096
|
-
return combineLatest([resource$, client$, loadMore$]).pipe(
|
|
5097
|
-
withLatestFrom(cursor$),
|
|
5098
|
-
switchMap(
|
|
5099
|
-
([[resource, client], cursor]) => client.observable.request({
|
|
5100
|
-
method: "GET",
|
|
5101
|
-
uri: `access/${resource.type}/${resource.id}/users`,
|
|
5102
|
-
query: cursor ? { nextCursor: cursor, limit: batchSize.toString() } : { limit: batchSize.toString() }
|
|
5103
|
-
})
|
|
5104
|
-
),
|
|
5105
|
-
catchError$1((error) => (state.set("setUsersError", setUsersError(group$.key, error)), EMPTY)),
|
|
5106
|
-
tap$1((response) => state.set("setUsersData", setUsersData(group$.key, response)))
|
|
5107
|
-
);
|
|
5108
|
-
})
|
|
5109
|
-
)
|
|
5110
|
-
)
|
|
5111
|
-
).subscribe({ error: errorHandler(state) }), getUsersState = bindActionGlobally(
|
|
5112
|
-
usersStore,
|
|
5113
|
-
createStateSourceAction({
|
|
5114
|
-
selector: createSelector(
|
|
5115
|
-
[
|
|
5116
|
-
({ instance, state }, options) => state.error ?? state.users[getUsersKey(instance, options)]?.error,
|
|
5117
|
-
({ instance, state }, options) => state.users[getUsersKey(instance, options)]?.users,
|
|
5118
|
-
({ instance, state }, options) => state.users[getUsersKey(instance, options)]?.totalCount,
|
|
5119
|
-
({ instance, state }, options) => state.users[getUsersKey(instance, options)]?.nextCursor
|
|
5120
|
-
],
|
|
5121
|
-
(error, data, totalCount, nextCursor) => {
|
|
5122
|
-
if (error) throw error;
|
|
5123
|
-
if (!(data === void 0 || totalCount === void 0 || nextCursor === void 0))
|
|
5124
|
-
return { data, totalCount, hasMore: nextCursor !== null };
|
|
5125
|
-
}
|
|
5126
|
-
),
|
|
5127
|
-
onSubscribe: ({ instance, state }, options) => {
|
|
5128
|
-
const subscriptionId = insecureRandomId(), key = getUsersKey(instance, options);
|
|
5129
|
-
return state.set("addSubscription", addSubscription(subscriptionId, key)), () => {
|
|
5130
|
-
setTimeout(
|
|
5131
|
-
() => state.set("removeSubscription", removeSubscription(subscriptionId, key)),
|
|
5132
|
-
USERS_STATE_CLEAR_DELAY
|
|
5133
|
-
);
|
|
5134
|
-
};
|
|
5135
|
-
}
|
|
5136
|
-
})
|
|
5137
|
-
), resolveUsers = bindActionGlobally(
|
|
5138
|
-
usersStore,
|
|
5139
|
-
async ({ state, instance }, { signal, ...options }) => {
|
|
5140
|
-
const key = getUsersKey(instance, options), { getCurrent } = getUsersState(instance, options), aborted$ = signal ? new Observable((observer) => {
|
|
5141
|
-
const cleanup = () => {
|
|
5142
|
-
signal.removeEventListener("abort", listener);
|
|
5143
|
-
}, listener = () => {
|
|
5144
|
-
observer.error(new DOMException("The operation was aborted.", "AbortError")), observer.complete(), cleanup();
|
|
5145
|
-
};
|
|
5146
|
-
return signal.addEventListener("abort", listener), cleanup;
|
|
5147
|
-
}).pipe(
|
|
5148
|
-
catchError$1((error) => {
|
|
5149
|
-
throw error instanceof Error && error.name === "AbortError" && state.set("cancelRequest", cancelRequest(key)), error;
|
|
5150
|
-
})
|
|
5151
|
-
) : NEVER;
|
|
5152
|
-
state.set("initializeRequest", initializeRequest(key));
|
|
5153
|
-
const resolved$ = state.observable.pipe(
|
|
5154
|
-
map(getCurrent),
|
|
5155
|
-
first$1((i2) => i2 !== void 0)
|
|
5156
|
-
);
|
|
5157
|
-
return firstValueFrom(race([resolved$, aborted$]));
|
|
5158
|
-
}
|
|
5159
|
-
), loadMoreUsers = bindActionGlobally(
|
|
5160
|
-
usersStore,
|
|
5161
|
-
async ({ state, instance }, options) => {
|
|
5162
|
-
const key = getUsersKey(instance, options), users = getUsersState(instance, options), usersState = users.getCurrent();
|
|
5163
|
-
if (!usersState)
|
|
5164
|
-
throw new Error("Users not loaded for specified resource. Please call resolveUsers first.");
|
|
5165
|
-
if (!usersState.hasMore)
|
|
5166
|
-
throw new Error("No more users available to load for this resource.");
|
|
5167
|
-
const promise = firstValueFrom(
|
|
5168
|
-
users.observable.pipe(
|
|
5169
|
-
filter((i2) => i2 !== void 0),
|
|
5170
|
-
skip(1)
|
|
5171
|
-
)
|
|
5172
|
-
), timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
5173
|
-
return state.set("updateLastLoadMoreRequest", updateLastLoadMoreRequest(timestamp, key)), await promise;
|
|
5174
|
-
}
|
|
5175
|
-
), WILDCARD_TOKEN = "*", NEGATION_TOKEN = "-", TOKEN_REGEX = /(?:[^\s"]+|"[^"]*")+/g;
|
|
5428
|
+
}), getProjectsState = projects.getState, resolveProjects = projects.resolveState, WILDCARD_TOKEN = "*", NEGATION_TOKEN = "-", TOKEN_REGEX = /(?:[^\s"]+|"[^"]*")+/g;
|
|
5176
5429
|
function isNegationToken(token) {
|
|
5177
5430
|
return typeof token < "u" && token.trim().startsWith(NEGATION_TOKEN);
|
|
5178
5431
|
}
|
|
@@ -5195,7 +5448,60 @@ function createGroqSearchFilter(query) {
|
|
|
5195
5448
|
`${finalIncrementalToken}${WILDCARD_TOKEN}`
|
|
5196
5449
|
), `[@] match text::query("${processedTokens.join(" ").replace(/"/g, '\\"')}")`;
|
|
5197
5450
|
}
|
|
5198
|
-
|
|
5451
|
+
function defineIntent(intent) {
|
|
5452
|
+
if (!intent.id)
|
|
5453
|
+
throw new Error("Intent must have an id");
|
|
5454
|
+
if (!intent.action)
|
|
5455
|
+
throw new Error("Intent must have an action");
|
|
5456
|
+
if (!intent.title)
|
|
5457
|
+
throw new Error("Intent must have a title");
|
|
5458
|
+
if (!Array.isArray(intent.filters))
|
|
5459
|
+
throw new Error("Intent must have a filters array");
|
|
5460
|
+
if (intent.filters.length === 0)
|
|
5461
|
+
throw new Error(
|
|
5462
|
+
"Intent must have at least one filter. If you want to match everything, use {types: ['*']}"
|
|
5463
|
+
);
|
|
5464
|
+
return intent.filters.forEach((filter2, index) => {
|
|
5465
|
+
validateFilter(filter2, index);
|
|
5466
|
+
}), intent;
|
|
5467
|
+
}
|
|
5468
|
+
function validateFilter(filter2, index) {
|
|
5469
|
+
const filterContext = `Filter at index ${index}`;
|
|
5470
|
+
if (!filter2 || typeof filter2 != "object")
|
|
5471
|
+
throw new Error(`${filterContext} must be an object`);
|
|
5472
|
+
if (filter2.types === void 0)
|
|
5473
|
+
throw new Error(
|
|
5474
|
+
`${filterContext} must have a types property. Use ['*'] to match all document types.`
|
|
5475
|
+
);
|
|
5476
|
+
if (filter2.projectId !== void 0) {
|
|
5477
|
+
if (typeof filter2.projectId != "string")
|
|
5478
|
+
throw new Error(`${filterContext}: projectId must be a string`);
|
|
5479
|
+
if (filter2.projectId.trim() === "")
|
|
5480
|
+
throw new Error(`${filterContext}: projectId cannot be empty`);
|
|
5481
|
+
}
|
|
5482
|
+
if (filter2.dataset !== void 0) {
|
|
5483
|
+
if (typeof filter2.dataset != "string")
|
|
5484
|
+
throw new Error(`${filterContext}: dataset must be a string`);
|
|
5485
|
+
if (filter2.dataset.trim() === "")
|
|
5486
|
+
throw new Error(`${filterContext}: dataset cannot be empty`);
|
|
5487
|
+
if (filter2.projectId === void 0)
|
|
5488
|
+
throw new Error(`${filterContext}: dataset cannot be specified without projectId`);
|
|
5489
|
+
}
|
|
5490
|
+
if (!Array.isArray(filter2.types))
|
|
5491
|
+
throw new Error(`${filterContext}: types must be an array`);
|
|
5492
|
+
if (filter2.types.length === 0)
|
|
5493
|
+
throw new Error(`${filterContext}: types array cannot be empty`);
|
|
5494
|
+
if (filter2.types.forEach((type, typeIndex) => {
|
|
5495
|
+
if (typeof type != "string")
|
|
5496
|
+
throw new Error(`${filterContext}: types[${typeIndex}] must be a string`);
|
|
5497
|
+
if (type.trim() === "")
|
|
5498
|
+
throw new Error(`${filterContext}: types[${typeIndex}] cannot be empty`);
|
|
5499
|
+
}), filter2.types.includes("*") && filter2.types.length > 1)
|
|
5500
|
+
throw new Error(
|
|
5501
|
+
`${filterContext}: when using wildcard '*', it must be the only type in the array`
|
|
5502
|
+
);
|
|
5503
|
+
}
|
|
5504
|
+
var version = "2.1.1";
|
|
5199
5505
|
const CORE_SDK_VERSION = getEnv("PKG_VERSION") || `${version}-development`;
|
|
5200
5506
|
export {
|
|
5201
5507
|
AuthStateType,
|
|
@@ -5208,6 +5514,7 @@ export {
|
|
|
5208
5514
|
createGroqSearchFilter,
|
|
5209
5515
|
createProjectHandle,
|
|
5210
5516
|
createSanityInstance,
|
|
5517
|
+
defineIntent,
|
|
5211
5518
|
deleteDocument,
|
|
5212
5519
|
destroyController,
|
|
5213
5520
|
discardDocument,
|
|
@@ -5232,6 +5539,7 @@ export {
|
|
|
5232
5539
|
getPathDepth,
|
|
5233
5540
|
getPermissionsState,
|
|
5234
5541
|
getPerspectiveState,
|
|
5542
|
+
getPresence,
|
|
5235
5543
|
getPreviewState,
|
|
5236
5544
|
getProjectState,
|
|
5237
5545
|
getProjectionState,
|
|
@@ -5239,6 +5547,7 @@ export {
|
|
|
5239
5547
|
getQueryKey,
|
|
5240
5548
|
getQueryState,
|
|
5241
5549
|
getTokenState,
|
|
5550
|
+
getUserState,
|
|
5242
5551
|
getUsersKey,
|
|
5243
5552
|
getUsersState,
|
|
5244
5553
|
handleAuthCallback,
|
|
@@ -5261,6 +5570,7 @@ export {
|
|
|
5261
5570
|
resolveProjection,
|
|
5262
5571
|
resolveProjects,
|
|
5263
5572
|
resolveQuery,
|
|
5573
|
+
resolveUser,
|
|
5264
5574
|
resolveUsers,
|
|
5265
5575
|
setAuthToken,
|
|
5266
5576
|
slicePath2 as slicePath,
|