@sanity/sdk 0.0.0-chore-react-18-compat.1 → 0.0.0-chore-react-18-compat.3
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 +441 -322
- package/dist/index.js +1685 -1481
- package/dist/index.js.map +1 -1
- package/package.json +13 -15
- package/src/_exports/index.ts +32 -30
- package/src/auth/authStore.test.ts +149 -104
- package/src/auth/authStore.ts +51 -100
- package/src/auth/handleAuthCallback.test.ts +67 -34
- package/src/auth/handleAuthCallback.ts +8 -7
- package/src/auth/logout.test.ts +61 -29
- package/src/auth/logout.ts +26 -28
- package/src/auth/refreshStampedToken.test.ts +197 -91
- package/src/auth/refreshStampedToken.ts +170 -59
- package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +5 -5
- package/src/auth/subscribeToStateAndFetchCurrentUser.ts +45 -47
- package/src/auth/subscribeToStorageEventsAndSetToken.test.ts +4 -5
- package/src/auth/subscribeToStorageEventsAndSetToken.ts +22 -24
- package/src/client/clientStore.test.ts +131 -67
- package/src/client/clientStore.ts +117 -116
- package/src/comlink/controller/actions/destroyController.test.ts +38 -13
- package/src/comlink/controller/actions/destroyController.ts +11 -15
- package/src/comlink/controller/actions/getOrCreateChannel.test.ts +56 -27
- package/src/comlink/controller/actions/getOrCreateChannel.ts +37 -35
- package/src/comlink/controller/actions/getOrCreateController.test.ts +27 -16
- package/src/comlink/controller/actions/getOrCreateController.ts +23 -22
- package/src/comlink/controller/actions/releaseChannel.test.ts +37 -13
- package/src/comlink/controller/actions/releaseChannel.ts +22 -21
- package/src/comlink/controller/comlinkControllerStore.test.ts +65 -36
- package/src/comlink/controller/comlinkControllerStore.ts +44 -5
- package/src/comlink/node/actions/getOrCreateNode.test.ts +31 -15
- package/src/comlink/node/actions/getOrCreateNode.ts +30 -29
- package/src/comlink/node/actions/releaseNode.test.ts +75 -55
- package/src/comlink/node/actions/releaseNode.ts +19 -21
- package/src/comlink/node/comlinkNodeStore.test.ts +6 -11
- package/src/comlink/node/comlinkNodeStore.ts +22 -5
- package/src/config/authConfig.ts +79 -0
- package/src/config/sanityConfig.ts +48 -0
- package/src/datasets/datasets.test.ts +2 -2
- package/src/datasets/datasets.ts +18 -5
- package/src/document/actions.test.ts +22 -10
- package/src/document/actions.ts +44 -56
- package/src/document/applyDocumentActions.test.ts +96 -36
- package/src/document/applyDocumentActions.ts +140 -99
- package/src/document/documentStore.test.ts +103 -155
- package/src/document/documentStore.ts +247 -238
- package/src/document/listen.ts +56 -55
- package/src/document/patchOperations.ts +0 -43
- package/src/document/permissions.test.ts +25 -12
- package/src/document/permissions.ts +11 -4
- package/src/document/processActions.test.ts +41 -8
- package/src/document/reducers.test.ts +87 -16
- package/src/document/reducers.ts +2 -2
- package/src/document/sharedListener.test.ts +34 -16
- package/src/document/sharedListener.ts +33 -11
- package/src/preview/getPreviewState.test.ts +40 -39
- package/src/preview/getPreviewState.ts +68 -56
- package/src/preview/previewConstants.ts +43 -0
- package/src/preview/previewQuery.test.ts +1 -1
- package/src/preview/previewQuery.ts +4 -5
- package/src/preview/previewStore.test.ts +13 -58
- package/src/preview/previewStore.ts +7 -21
- package/src/preview/resolvePreview.test.ts +33 -104
- package/src/preview/resolvePreview.ts +11 -21
- package/src/preview/subscribeToStateAndFetchBatches.test.ts +96 -97
- package/src/preview/subscribeToStateAndFetchBatches.ts +85 -81
- package/src/preview/util.ts +1 -0
- package/src/project/project.test.ts +3 -3
- package/src/project/project.ts +28 -5
- package/src/projection/getProjectionState.test.ts +188 -72
- package/src/projection/getProjectionState.ts +92 -62
- package/src/projection/projectionQuery.test.ts +114 -12
- package/src/projection/projectionQuery.ts +75 -32
- package/src/projection/projectionStore.test.ts +13 -51
- package/src/projection/projectionStore.ts +6 -43
- package/src/projection/resolveProjection.test.ts +32 -127
- package/src/projection/resolveProjection.ts +16 -28
- package/src/projection/subscribeToStateAndFetchBatches.test.ts +203 -116
- package/src/projection/subscribeToStateAndFetchBatches.ts +140 -85
- package/src/projection/types.ts +50 -0
- package/src/projection/util.ts +3 -1
- package/src/projects/projects.test.ts +13 -4
- package/src/projects/projects.ts +6 -1
- package/src/query/queryStore.test.ts +10 -47
- package/src/query/queryStore.ts +151 -133
- package/src/query/queryStoreConstants.ts +2 -0
- package/src/store/createActionBinder.test.ts +153 -0
- package/src/store/createActionBinder.ts +176 -0
- package/src/store/createSanityInstance.test.ts +84 -0
- package/src/store/createSanityInstance.ts +124 -0
- package/src/store/createStateSourceAction.test.ts +196 -0
- package/src/store/createStateSourceAction.ts +260 -0
- package/src/store/createStoreInstance.test.ts +81 -0
- package/src/store/createStoreInstance.ts +80 -0
- package/src/store/createStoreState.test.ts +85 -0
- package/src/store/createStoreState.ts +92 -0
- package/src/store/defineStore.test.ts +18 -0
- package/src/store/defineStore.ts +81 -0
- package/src/users/reducers.test.ts +318 -0
- package/src/users/reducers.ts +88 -0
- package/src/users/types.ts +46 -4
- package/src/users/usersConstants.ts +4 -0
- package/src/users/usersStore.test.ts +350 -223
- package/src/users/usersStore.ts +285 -149
- package/src/utils/createFetcherStore.test.ts +6 -7
- package/src/utils/createFetcherStore.ts +150 -153
- package/src/utils/createGroqSearchFilter.test.ts +75 -0
- package/src/utils/createGroqSearchFilter.ts +85 -0
- package/src/{common/util.test.ts → utils/hashString.test.ts} +1 -1
- package/dist/index.cjs +0 -4888
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -2121
- package/src/auth/fetchLoginUrls.test.ts +0 -163
- package/src/auth/fetchLoginUrls.ts +0 -74
- package/src/common/createLiveEventSubscriber.test.ts +0 -121
- package/src/common/createLiveEventSubscriber.ts +0 -55
- package/src/common/types.ts +0 -4
- package/src/instance/identity.test.ts +0 -46
- package/src/instance/identity.ts +0 -29
- package/src/instance/sanityInstance.test.ts +0 -77
- package/src/instance/sanityInstance.ts +0 -57
- package/src/instance/types.ts +0 -37
- package/src/preview/getPreviewProjection.ts +0 -45
- package/src/resources/README.md +0 -370
- package/src/resources/createAction.test.ts +0 -101
- package/src/resources/createAction.ts +0 -44
- package/src/resources/createResource.test.ts +0 -112
- package/src/resources/createResource.ts +0 -102
- package/src/resources/createStateSourceAction.test.ts +0 -114
- package/src/resources/createStateSourceAction.ts +0 -83
- package/src/resources/createStore.test.ts +0 -67
- package/src/resources/createStore.ts +0 -46
- package/src/store/createStore.test.ts +0 -108
- package/src/store/createStore.ts +0 -106
- /package/src/{common/util.ts → utils/hashString.ts} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,17 +1,63 @@
|
|
|
1
1
|
import { createClient } from "@sanity/client";
|
|
2
|
-
import { Observable, share, map, distinctUntilChanged, skip, filter, switchMap,
|
|
2
|
+
import { Observable, share, map, distinctUntilChanged, skip, filter, switchMap, timer, from, takeWhile, firstValueFrom, fromEvent, EMPTY, defer, asapScheduler, concatMap, of, 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, combineLatest, debounceTime, Subscription } from "rxjs";
|
|
3
3
|
import { devtools } from "zustand/middleware";
|
|
4
|
-
import { createStore
|
|
5
|
-
import {
|
|
6
|
-
import { isEqual, omit, isObject, noop } from "lodash-es";
|
|
4
|
+
import { createStore } from "zustand/vanilla";
|
|
5
|
+
import { pick, isEqual, omit, isObject } from "lodash-es";
|
|
7
6
|
import { createController, createNode } from "@sanity/comlink";
|
|
8
7
|
import { first, switchMap as switchMap$1, groupBy, mergeMap, startWith, pairwise, filter as filter$1, map as map$1, delay, tap, catchError, scan } from "rxjs/operators";
|
|
9
8
|
import { SanityEncoder } from "@sanity/mutate";
|
|
10
9
|
import { getPublishedId as getPublishedId$1 } from "@sanity/client/csm";
|
|
10
|
+
import { createSelector } from "reselect";
|
|
11
11
|
import { applyPatches, parsePatch, makePatches, stringifyPatches } from "@sanity/diff-match-patch";
|
|
12
12
|
import { isKeySegment, isKeyedObject } from "@sanity/types";
|
|
13
13
|
import { createDocumentLoaderFromClient } from "@sanity/mutate/_unstable_store";
|
|
14
14
|
var AuthStateType = /* @__PURE__ */ ((AuthStateType2) => (AuthStateType2.LOGGED_IN = "logged-in", AuthStateType2.LOGGING_IN = "logging-in", AuthStateType2.ERROR = "error", AuthStateType2.LOGGED_OUT = "logged-out", AuthStateType2))(AuthStateType || {});
|
|
15
|
+
function getPublishedId(id) {
|
|
16
|
+
const draftsPrefix = "drafts.";
|
|
17
|
+
return id.startsWith(draftsPrefix) ? id.slice(draftsPrefix.length) : id;
|
|
18
|
+
}
|
|
19
|
+
function getDraftId(id) {
|
|
20
|
+
const draftsPrefix = "drafts.";
|
|
21
|
+
return id.startsWith(draftsPrefix) ? id : `${draftsPrefix}${id}`;
|
|
22
|
+
}
|
|
23
|
+
function insecureRandomId() {
|
|
24
|
+
return Array.from({ length: 16 }, () => Math.floor(Math.random() * 16).toString(16)).join("");
|
|
25
|
+
}
|
|
26
|
+
function createSanityInstance(config = {}) {
|
|
27
|
+
const instanceId = crypto.randomUUID(), disposeListeners = /* @__PURE__ */ new Map(), disposed = { current: !1 }, instance = {
|
|
28
|
+
instanceId,
|
|
29
|
+
config,
|
|
30
|
+
isDisposed: () => disposed.current,
|
|
31
|
+
dispose: () => {
|
|
32
|
+
disposed.current || (disposed.current = !0, disposeListeners.forEach((listener) => listener()), disposeListeners.clear());
|
|
33
|
+
},
|
|
34
|
+
onDispose: (cb) => {
|
|
35
|
+
const listenerId = insecureRandomId();
|
|
36
|
+
return disposeListeners.set(listenerId, cb), () => {
|
|
37
|
+
disposeListeners.delete(listenerId);
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
getParent: () => {
|
|
41
|
+
},
|
|
42
|
+
createChild: (next) => Object.assign(
|
|
43
|
+
createSanityInstance({
|
|
44
|
+
...config,
|
|
45
|
+
...next,
|
|
46
|
+
...config.auth === next.auth ? config.auth : config.auth && next.auth && { auth: { ...config.auth, ...next.auth } }
|
|
47
|
+
}),
|
|
48
|
+
{ getParent: () => instance }
|
|
49
|
+
),
|
|
50
|
+
match: (targetConfig) => {
|
|
51
|
+
if (Object.entries(pick(targetConfig, "auth", "projectId", "dataset")).every(
|
|
52
|
+
([key, value]) => config[key] === value
|
|
53
|
+
))
|
|
54
|
+
return instance;
|
|
55
|
+
const parent = instance.getParent();
|
|
56
|
+
if (parent) return parent.match(targetConfig);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
return instance;
|
|
60
|
+
}
|
|
15
61
|
function getEnv(key) {
|
|
16
62
|
if (typeof import.meta < "u" && import.meta.env)
|
|
17
63
|
return import.meta.env[key];
|
|
@@ -20,68 +66,78 @@ function getEnv(key) {
|
|
|
20
66
|
if (typeof window < "u" && window.ENV)
|
|
21
67
|
return window.ENV?.[key];
|
|
22
68
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const store = createStore$1()(devtools(() => initialState, devToolsOptions));
|
|
69
|
+
function createStoreState(initialState, devToolsOptions) {
|
|
70
|
+
const store = createStore()(devtools(() => initialState, devToolsOptions));
|
|
26
71
|
return {
|
|
27
72
|
get: store.getState,
|
|
28
73
|
set: (actionKey, updatedState) => {
|
|
29
|
-
store.getState()
|
|
74
|
+
const currentState = store.getState(), nextState = typeof updatedState == "function" ? updatedState(currentState) : updatedState;
|
|
75
|
+
currentState !== nextState && store.setState(nextState, !1, actionKey);
|
|
30
76
|
},
|
|
31
77
|
observable: new Observable((observer) => {
|
|
32
78
|
const emit = () => observer.next(store.getState());
|
|
33
|
-
|
|
79
|
+
emit();
|
|
80
|
+
const unsubscribe = store.subscribe(emit);
|
|
81
|
+
return () => unsubscribe();
|
|
34
82
|
})
|
|
35
83
|
};
|
|
36
84
|
}
|
|
37
|
-
function
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}), dispose =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const initializedResources = resourceCache.get(instance.identity), cached = initializedResources.get(fullName);
|
|
49
|
-
if (cached) return cached;
|
|
50
|
-
const result = initializeResource(instance, resource);
|
|
51
|
-
return initializedResources.set(fullName, result), result;
|
|
52
|
-
}
|
|
53
|
-
function disposeResources(identity) {
|
|
54
|
-
const resources = resourceCache.get(identity);
|
|
55
|
-
if (resources)
|
|
56
|
-
for (const resource of resources.values())
|
|
57
|
-
resource.dispose();
|
|
58
|
-
}
|
|
59
|
-
function createAction(resource, actionDefinition) {
|
|
60
|
-
return (dependencies, ...args) => {
|
|
61
|
-
const instance = "state" in dependencies ? dependencies.instance : dependencies, { state } = "state" in dependencies ? dependencies : getOrCreateResource(dependencies, resource), actionContext = { instance, state };
|
|
62
|
-
return actionDefinition(actionContext).bind(actionContext)(...args);
|
|
85
|
+
function createStoreInstance(instance, { name, getInitialState, initialize }) {
|
|
86
|
+
const state = createStoreState(getInitialState(instance), {
|
|
87
|
+
enabled: !!getEnv("DEV"),
|
|
88
|
+
name: `${name}-${instance.config.projectId}.${instance.config.dataset}`
|
|
89
|
+
}), dispose = initialize?.({ state, instance }), disposed = { current: !1 };
|
|
90
|
+
return {
|
|
91
|
+
state,
|
|
92
|
+
dispose: () => {
|
|
93
|
+
disposed.current || (disposed.current = !0, dispose?.());
|
|
94
|
+
},
|
|
95
|
+
isDisposed: () => disposed.current
|
|
63
96
|
};
|
|
64
97
|
}
|
|
65
|
-
function
|
|
66
|
-
|
|
98
|
+
function createActionBinder(keyFn) {
|
|
99
|
+
const instanceRegistry = /* @__PURE__ */ new Map(), storeRegistry = /* @__PURE__ */ new Map();
|
|
100
|
+
return function(storeDefinition, action) {
|
|
101
|
+
return function(instance, ...params) {
|
|
102
|
+
const keySuffix = keyFn(instance.config), compositeKey = storeDefinition.name + (keySuffix ? `:${keySuffix}` : "");
|
|
103
|
+
let instances = instanceRegistry.get(compositeKey);
|
|
104
|
+
instances || (instances = /* @__PURE__ */ new Set(), instanceRegistry.set(compositeKey, instances)), instances.has(instance.instanceId) || (instances.add(instance.instanceId), instance.onDispose(() => {
|
|
105
|
+
instances.delete(instance.instanceId), instances.size === 0 && (storeRegistry.get(compositeKey)?.dispose(), storeRegistry.delete(compositeKey), instanceRegistry.delete(compositeKey));
|
|
106
|
+
}));
|
|
107
|
+
let storeInstance = storeRegistry.get(compositeKey);
|
|
108
|
+
return storeInstance || (storeInstance = createStoreInstance(instance, storeDefinition), storeRegistry.set(compositeKey, storeInstance)), action({ instance, state: storeInstance.state }, ...params);
|
|
109
|
+
};
|
|
110
|
+
};
|
|
67
111
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
112
|
+
const bindActionByDataset = createActionBinder(({ projectId, dataset }) => {
|
|
113
|
+
if (!projectId || !dataset)
|
|
114
|
+
throw new Error("This API requires a project ID and dataset configured.");
|
|
115
|
+
return `${projectId}.${dataset}`;
|
|
116
|
+
}), bindActionGlobally = createActionBinder(() => "global");
|
|
117
|
+
function createStateSourceAction(options) {
|
|
118
|
+
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();
|
|
119
|
+
function stateSourceAction(context, ...params) {
|
|
120
|
+
const { state, instance } = context, getCurrent = () => {
|
|
121
|
+
const currentState = state.get();
|
|
122
|
+
if (typeof currentState != "object" || currentState === null)
|
|
123
|
+
throw new Error(
|
|
124
|
+
`Expected store state to be an object but got "${typeof currentState}" instead`
|
|
125
|
+
);
|
|
126
|
+
let instanceCache = selectorContextCache.get(currentState);
|
|
127
|
+
instanceCache || (instanceCache = /* @__PURE__ */ new WeakMap(), selectorContextCache.set(currentState, instanceCache));
|
|
128
|
+
let selectorContext = instanceCache.get(instance);
|
|
129
|
+
return selectorContext || (selectorContext = { state: currentState, instance }, instanceCache.set(instance, selectorContext)), selector(selectorContext, ...params);
|
|
130
|
+
}, subscribe = (onStoreChanged) => {
|
|
131
|
+
const cleanup = subscribeHandler?.(context, ...params), subscription = state.observable.pipe(
|
|
132
|
+
// Derive value from current state
|
|
73
133
|
map(getCurrent),
|
|
134
|
+
// Filter unchanged values using custom equality check
|
|
74
135
|
distinctUntilChanged(isEqual2),
|
|
75
|
-
//
|
|
76
|
-
// value changes. `distinctUntilChanged` will always emit the first
|
|
77
|
-
// the first value so we skip this emission
|
|
136
|
+
// Skip initial emission since we only want changes
|
|
78
137
|
skip(1)
|
|
79
138
|
).subscribe({
|
|
80
139
|
next: () => onStoreChanged?.(),
|
|
81
|
-
//
|
|
82
|
-
// invoke onStoreChanged on error as well. this will cause the
|
|
83
|
-
// observable code path below to emit an error because the selector
|
|
84
|
-
// will throw and that will be used to emit an .error on the observer
|
|
140
|
+
// Propagate selector errors to both subscription types
|
|
85
141
|
error: () => onStoreChanged?.()
|
|
86
142
|
});
|
|
87
143
|
return () => {
|
|
@@ -102,96 +158,144 @@ function createStateSourceAction(resource, options) {
|
|
|
102
158
|
subscribe,
|
|
103
159
|
observable
|
|
104
160
|
};
|
|
105
|
-
}
|
|
161
|
+
}
|
|
162
|
+
return stateSourceAction;
|
|
106
163
|
}
|
|
107
|
-
const DEFAULT_BASE = "http://localhost", AUTH_CODE_PARAM = "sid", DEFAULT_API_VERSION$1 = "2021-06-07", REQUEST_TAG_PREFIX = "sanity.sdk.auth",
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
distinctUntilChanged(),
|
|
115
|
-
filter((authState) => authState.token.includes("-st")),
|
|
116
|
-
// Ensure we only try to refresh stamped tokens
|
|
117
|
-
switchMap(
|
|
118
|
-
(authState) => interval(10 * 60 * 1e3).pipe(
|
|
119
|
-
takeWhile(() => state.get().authState.type === AuthStateType.LOGGED_IN),
|
|
120
|
-
map(() => authState.token),
|
|
121
|
-
distinctUntilChanged(),
|
|
122
|
-
map(
|
|
123
|
-
(token) => clientFactory({
|
|
124
|
-
apiVersion: DEFAULT_API_VERSION$1,
|
|
125
|
-
requestTagPrefix: "sdk.token-refresh",
|
|
126
|
-
useProjectHostname: !1,
|
|
127
|
-
token,
|
|
128
|
-
ignoreBrowserTokenWarning: !0,
|
|
129
|
-
...apiHost && { apiHost }
|
|
130
|
-
})
|
|
131
|
-
),
|
|
132
|
-
switchMap(
|
|
133
|
-
(client) => client.observable.request({
|
|
134
|
-
uri: "auth/refresh-token",
|
|
135
|
-
method: "POST",
|
|
136
|
-
body: {
|
|
137
|
-
token: authState.token
|
|
138
|
-
}
|
|
139
|
-
})
|
|
140
|
-
)
|
|
141
|
-
)
|
|
142
|
-
)
|
|
143
|
-
);
|
|
144
|
-
return function() {
|
|
145
|
-
return refreshToken$.subscribe({
|
|
146
|
-
next: (response) => {
|
|
147
|
-
state.set("setRefreshStampedToken", (prev) => ({
|
|
148
|
-
authState: prev.authState.type === AuthStateType.LOGGED_IN ? { ...prev.authState, token: response.token } : prev.authState
|
|
149
|
-
})), storageArea?.setItem(storageKey, JSON.stringify({ token: response.token }));
|
|
150
|
-
},
|
|
151
|
-
error: (error) => {
|
|
152
|
-
state.set("setRefreshStampedTokenError", { authState: { type: AuthStateType.ERROR, error } });
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
};
|
|
164
|
+
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";
|
|
165
|
+
function getLastRefreshTime(storageArea, storageKey) {
|
|
166
|
+
try {
|
|
167
|
+
const data = storageArea?.getItem(`${storageKey}_last_refresh`);
|
|
168
|
+
return data ? parseInt(data, 10) : 0;
|
|
169
|
+
} catch {
|
|
170
|
+
return 0;
|
|
156
171
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
(authState) => authState.type === AuthStateType.LOGGED_IN && !authState.currentUser
|
|
163
|
-
),
|
|
164
|
-
map((authState) => authState.token),
|
|
165
|
-
distinctUntilChanged()
|
|
166
|
-
).pipe(
|
|
167
|
-
map(
|
|
168
|
-
(token) => clientFactory({
|
|
169
|
-
apiVersion: DEFAULT_API_VERSION$1,
|
|
170
|
-
requestTagPrefix: REQUEST_TAG_PREFIX,
|
|
171
|
-
token,
|
|
172
|
-
ignoreBrowserTokenWarning: !0,
|
|
173
|
-
useProjectHostname: !1,
|
|
174
|
-
...apiHost && { apiHost }
|
|
175
|
-
})
|
|
176
|
-
),
|
|
177
|
-
switchMap(
|
|
178
|
-
(client) => client.observable.request({ uri: "/users/me", method: "GET" })
|
|
179
|
-
)
|
|
180
|
-
);
|
|
181
|
-
return function() {
|
|
182
|
-
return currentUser$.subscribe({
|
|
183
|
-
next: (currentUser) => {
|
|
184
|
-
state.set("setCurrentUser", (prev) => ({
|
|
185
|
-
authState: prev.authState.type === AuthStateType.LOGGED_IN ? { ...prev.authState, currentUser } : prev.authState
|
|
186
|
-
}));
|
|
187
|
-
},
|
|
188
|
-
error: (error) => {
|
|
189
|
-
state.set("setError", { authState: { type: AuthStateType.ERROR, error } });
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
};
|
|
172
|
+
}
|
|
173
|
+
function setLastRefreshTime(storageArea, storageKey) {
|
|
174
|
+
try {
|
|
175
|
+
storageArea?.setItem(`${storageKey}_last_refresh`, Date.now().toString());
|
|
176
|
+
} catch {
|
|
193
177
|
}
|
|
194
|
-
|
|
178
|
+
}
|
|
179
|
+
function getNextRefreshDelay(storageArea, storageKey) {
|
|
180
|
+
const lastRefresh = getLastRefreshTime(storageArea, storageKey);
|
|
181
|
+
if (!lastRefresh) return 0;
|
|
182
|
+
const now = Date.now(), nextRefreshTime = lastRefresh + REFRESH_INTERVAL;
|
|
183
|
+
return Math.max(0, nextRefreshTime - now);
|
|
184
|
+
}
|
|
185
|
+
function createTokenRefreshStream(token, clientFactory, apiHost) {
|
|
186
|
+
return new Observable((subscriber) => {
|
|
187
|
+
const subscription = clientFactory({
|
|
188
|
+
apiVersion: DEFAULT_API_VERSION$1,
|
|
189
|
+
requestTagPrefix: "sdk.token-refresh",
|
|
190
|
+
useProjectHostname: !1,
|
|
191
|
+
token,
|
|
192
|
+
ignoreBrowserTokenWarning: !0,
|
|
193
|
+
...apiHost && { apiHost }
|
|
194
|
+
}).observable.request({
|
|
195
|
+
uri: "auth/refresh-token",
|
|
196
|
+
method: "POST",
|
|
197
|
+
body: {
|
|
198
|
+
token
|
|
199
|
+
}
|
|
200
|
+
}).subscribe(subscriber);
|
|
201
|
+
return () => subscription.unsubscribe();
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
async function acquireTokenRefreshLock(refreshFn, storageArea, storageKey) {
|
|
205
|
+
if (!navigator.locks)
|
|
206
|
+
return !0;
|
|
207
|
+
try {
|
|
208
|
+
return await navigator.locks.request(LOCK_NAME, { mode: "exclusive" }, async (lock) => {
|
|
209
|
+
if (!lock) return !1;
|
|
210
|
+
for (; ; ) {
|
|
211
|
+
const delay2 = getNextRefreshDelay(storageArea, storageKey);
|
|
212
|
+
delay2 > 0 && await new Promise((resolve) => setTimeout(resolve, delay2)), await refreshFn(), setLastRefreshTime(storageArea, storageKey), await new Promise((resolve) => setTimeout(resolve, REFRESH_INTERVAL));
|
|
213
|
+
}
|
|
214
|
+
}) === !0;
|
|
215
|
+
} catch {
|
|
216
|
+
return !1;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const refreshStampedToken = ({ state }) => {
|
|
220
|
+
const { clientFactory, apiHost, storageArea, storageKey } = state.get().options;
|
|
221
|
+
return state.observable.pipe(
|
|
222
|
+
map((storeState) => ({
|
|
223
|
+
authState: storeState.authState,
|
|
224
|
+
dashboardContext: storeState.dashboardContext
|
|
225
|
+
})),
|
|
226
|
+
filter(
|
|
227
|
+
(storeState) => storeState.authState.type === AuthStateType.LOGGED_IN
|
|
228
|
+
),
|
|
229
|
+
distinctUntilChanged(),
|
|
230
|
+
filter((storeState) => storeState.authState.token.includes("-st")),
|
|
231
|
+
// Ensure we only try to refresh stamped tokens
|
|
232
|
+
switchMap((storeState) => {
|
|
233
|
+
const performRefresh = async () => {
|
|
234
|
+
const response = await firstValueFrom(
|
|
235
|
+
createTokenRefreshStream(storeState.authState.token, clientFactory, apiHost)
|
|
236
|
+
);
|
|
237
|
+
state.set("setRefreshStampedToken", (prev) => ({
|
|
238
|
+
authState: prev.authState.type === AuthStateType.LOGGED_IN ? { ...prev.authState, token: response.token } : prev.authState
|
|
239
|
+
})), storageArea?.setItem(storageKey, JSON.stringify({ token: response.token }));
|
|
240
|
+
};
|
|
241
|
+
return storeState.dashboardContext ? timer(0, REFRESH_INTERVAL).pipe(
|
|
242
|
+
takeWhile(() => storeState.authState.type === AuthStateType.LOGGED_IN),
|
|
243
|
+
switchMap(
|
|
244
|
+
() => createTokenRefreshStream(storeState.authState.token, clientFactory, apiHost)
|
|
245
|
+
)
|
|
246
|
+
) : from(acquireTokenRefreshLock(performRefresh, storageArea, storageKey)).pipe(
|
|
247
|
+
filter((hasLock) => hasLock),
|
|
248
|
+
// This observable will never emit after the first value
|
|
249
|
+
// because acquireTokenRefreshLock handles the refresh loop internally
|
|
250
|
+
map(() => ({ token: storeState.authState.token }))
|
|
251
|
+
);
|
|
252
|
+
})
|
|
253
|
+
).subscribe({
|
|
254
|
+
next: (response) => {
|
|
255
|
+
state.set("setRefreshStampedToken", (prev) => ({
|
|
256
|
+
authState: prev.authState.type === AuthStateType.LOGGED_IN ? { ...prev.authState, token: response.token } : prev.authState
|
|
257
|
+
})), storageArea?.setItem(storageKey, JSON.stringify({ token: response.token }));
|
|
258
|
+
},
|
|
259
|
+
error: (error) => {
|
|
260
|
+
state.set("setRefreshStampedTokenError", { authState: { type: AuthStateType.ERROR, error } });
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
}, subscribeToStateAndFetchCurrentUser = ({
|
|
264
|
+
state
|
|
265
|
+
}) => {
|
|
266
|
+
const { clientFactory, apiHost } = state.get().options;
|
|
267
|
+
return state.observable.pipe(
|
|
268
|
+
map(({ authState }) => authState),
|
|
269
|
+
filter(
|
|
270
|
+
(authState) => authState.type === AuthStateType.LOGGED_IN && !authState.currentUser
|
|
271
|
+
),
|
|
272
|
+
map((authState) => authState.token),
|
|
273
|
+
distinctUntilChanged()
|
|
274
|
+
).pipe(
|
|
275
|
+
map(
|
|
276
|
+
(token) => clientFactory({
|
|
277
|
+
apiVersion: DEFAULT_API_VERSION$1,
|
|
278
|
+
requestTagPrefix: REQUEST_TAG_PREFIX,
|
|
279
|
+
token,
|
|
280
|
+
ignoreBrowserTokenWarning: !0,
|
|
281
|
+
useProjectHostname: !1,
|
|
282
|
+
...apiHost && { apiHost }
|
|
283
|
+
})
|
|
284
|
+
),
|
|
285
|
+
switchMap(
|
|
286
|
+
(client) => client.observable.request({ uri: "/users/me", method: "GET" })
|
|
287
|
+
)
|
|
288
|
+
).subscribe({
|
|
289
|
+
next: (currentUser) => {
|
|
290
|
+
state.set("setCurrentUser", (prev) => ({
|
|
291
|
+
authState: prev.authState.type === AuthStateType.LOGGED_IN ? { ...prev.authState, currentUser } : prev.authState
|
|
292
|
+
}));
|
|
293
|
+
},
|
|
294
|
+
error: (error) => {
|
|
295
|
+
state.set("setError", { authState: { type: AuthStateType.ERROR, error } });
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
};
|
|
195
299
|
function getAuthCode(callbackUrl, locationHref) {
|
|
196
300
|
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, authCode = new URLSearchParams(loc.hash.slice(1)).get(AUTH_CODE_PARAM) || new URLSearchParams(loc.search).get(AUTH_CODE_PARAM);
|
|
197
301
|
return authCode && callbackLocationMatches ? authCode : null;
|
|
@@ -226,24 +330,22 @@ function getDefaultLocation() {
|
|
|
226
330
|
return DEFAULT_BASE;
|
|
227
331
|
}
|
|
228
332
|
}
|
|
229
|
-
const subscribeToStorageEventsAndSetToken =
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
)
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
);
|
|
333
|
+
const subscribeToStorageEventsAndSetToken = ({
|
|
334
|
+
state
|
|
335
|
+
}) => {
|
|
336
|
+
const { storageArea, storageKey } = state.get().options;
|
|
337
|
+
return defer(getStorageEvents).pipe(
|
|
338
|
+
filter(
|
|
339
|
+
(e3) => e3.storageArea === storageArea && e3.key === storageKey
|
|
340
|
+
),
|
|
341
|
+
map(() => getTokenFromStorage(storageArea, storageKey)),
|
|
342
|
+
distinctUntilChanged()
|
|
343
|
+
).subscribe((token) => {
|
|
344
|
+
state.set("updateTokenFromStorageEvent", {
|
|
345
|
+
authState: token ? { type: AuthStateType.LOGGED_IN, token, currentUser: null } : { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
};
|
|
247
349
|
let tokenRefresherRunning = !1;
|
|
248
350
|
const authStore = {
|
|
249
351
|
name: "Auth",
|
|
@@ -257,12 +359,20 @@ const authStore = {
|
|
|
257
359
|
initialLocationHref = getDefaultLocation(),
|
|
258
360
|
storageArea = getDefaultStorage()
|
|
259
361
|
} = instance.config.auth ?? {}, storageKey = "__sanity_auth_token";
|
|
362
|
+
let loginDomain = "https://www.sanity.io";
|
|
363
|
+
try {
|
|
364
|
+
apiHost && new URL(apiHost).hostname.endsWith(".sanity.work") && (loginDomain = "https://www.sanity.work");
|
|
365
|
+
} catch {
|
|
366
|
+
}
|
|
367
|
+
const loginUrl = new URL("/login", loginDomain);
|
|
368
|
+
loginUrl.searchParams.set("origin", initialLocationHref), loginUrl.searchParams.set("type", "stampedToken"), loginUrl.searchParams.set("withSid", "true");
|
|
260
369
|
let authState;
|
|
261
370
|
const token = getTokenFromStorage(storageArea, storageKey);
|
|
262
371
|
return providedToken ? authState = { type: AuthStateType.LOGGED_IN, token: providedToken, currentUser: null } : getAuthCode(callbackUrl, initialLocationHref) ? authState = { type: AuthStateType.LOGGING_IN, isExchangingToken: !1 } : token ? authState = { type: AuthStateType.LOGGED_IN, token, currentUser: null } : authState = { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }, {
|
|
263
372
|
authState,
|
|
264
373
|
options: {
|
|
265
374
|
apiHost,
|
|
375
|
+
loginUrl: loginUrl.toString(),
|
|
266
376
|
callbackUrl,
|
|
267
377
|
customProviders,
|
|
268
378
|
providedToken,
|
|
@@ -273,61 +383,36 @@ const authStore = {
|
|
|
273
383
|
}
|
|
274
384
|
};
|
|
275
385
|
},
|
|
276
|
-
initialize() {
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
return tokenRefresherRunning || (tokenRefresherRunning = !0, refreshStampedTokenSubscription = refreshStampedToken(this)), () => {
|
|
282
|
-
stateSubscription.unsubscribe(), storageEventsSubscription?.unsubscribe(), refreshStampedTokenSubscription?.unsubscribe();
|
|
386
|
+
initialize(context) {
|
|
387
|
+
const subscriptions = [];
|
|
388
|
+
return subscriptions.push(subscribeToStateAndFetchCurrentUser(context)), context.state.get().options?.storageArea && subscriptions.push(subscribeToStorageEventsAndSetToken(context)), tokenRefresherRunning || (tokenRefresherRunning = !0, subscriptions.push(refreshStampedToken(context))), () => {
|
|
389
|
+
for (const subscription of subscriptions)
|
|
390
|
+
subscription.unsubscribe();
|
|
283
391
|
};
|
|
284
392
|
}
|
|
285
|
-
}, getCurrentUserState =
|
|
393
|
+
}, getCurrentUserState = bindActionGlobally(
|
|
286
394
|
authStore,
|
|
287
|
-
(
|
|
288
|
-
)
|
|
395
|
+
createStateSourceAction(
|
|
396
|
+
({ state: { authState } }) => authState.type === AuthStateType.LOGGED_IN ? authState.currentUser : null
|
|
397
|
+
)
|
|
398
|
+
), getTokenState = bindActionGlobally(
|
|
289
399
|
authStore,
|
|
290
|
-
(
|
|
291
|
-
)
|
|
400
|
+
createStateSourceAction(
|
|
401
|
+
({ state: { authState } }) => authState.type === AuthStateType.LOGGED_IN ? authState.token : null
|
|
402
|
+
)
|
|
403
|
+
), getLoginUrlState = bindActionGlobally(
|
|
292
404
|
authStore,
|
|
293
|
-
({
|
|
294
|
-
), getAuthState =
|
|
405
|
+
createStateSourceAction(({ state: { options } }) => options.loginUrl)
|
|
406
|
+
), getAuthState = bindActionGlobally(
|
|
295
407
|
authStore,
|
|
296
|
-
({
|
|
297
|
-
),
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
return async function() {
|
|
305
|
-
const cachedProviders = state.get().providers;
|
|
306
|
-
if (cachedProviders) return cachedProviders;
|
|
307
|
-
const { providers: defaultProviders } = await client.request({
|
|
308
|
-
uri: "/auth/providers",
|
|
309
|
-
tag: "fetch-providers"
|
|
310
|
-
});
|
|
311
|
-
let providers;
|
|
312
|
-
if (typeof customProviders == "function")
|
|
313
|
-
providers = await customProviders(defaultProviders);
|
|
314
|
-
else if (!customProviders?.length)
|
|
315
|
-
providers = defaultProviders;
|
|
316
|
-
else {
|
|
317
|
-
const customProviderUrls = new Set(customProviders.map((p2) => p2.url));
|
|
318
|
-
providers = defaultProviders.filter((official) => !customProviderUrls.has(official.url)).concat(customProviders);
|
|
319
|
-
}
|
|
320
|
-
const configuredProviders = providers.map((provider) => {
|
|
321
|
-
const url = new URL(provider.url), origin = new URL(
|
|
322
|
-
callbackUrl ? new URL(callbackUrl, new URL(getDefaultLocation()).origin).toString() : getDefaultLocation()
|
|
323
|
-
), hashParams = new URLSearchParams(origin.hash.slice(1));
|
|
324
|
-
return hashParams.delete("sid"), origin.hash = hashParams.toString(), origin.searchParams.delete("sid"), origin.searchParams.delete("url"), origin.searchParams.delete("error"), url.searchParams.set("origin", origin.toString()), url.searchParams.set("withSid", "true"), url.searchParams.set("type", "stampedToken"), { ...provider, url: url.toString() };
|
|
325
|
-
});
|
|
326
|
-
return state.set("fetchedLoginUrls", { providers: configuredProviders }), configuredProviders;
|
|
327
|
-
};
|
|
328
|
-
}), handleAuthCallback = createAction(authStore, ({ state }) => {
|
|
329
|
-
const { providedToken, callbackUrl, clientFactory, apiHost, storageArea, storageKey } = state.get().options;
|
|
330
|
-
return async function(locationHref = getDefaultLocation()) {
|
|
408
|
+
createStateSourceAction(({ state: { authState } }) => authState)
|
|
409
|
+
), getDashboardOrganizationId = bindActionGlobally(
|
|
410
|
+
authStore,
|
|
411
|
+
createStateSourceAction(({ state: { dashboardContext } }) => dashboardContext?.orgId)
|
|
412
|
+
), handleAuthCallback = bindActionGlobally(
|
|
413
|
+
authStore,
|
|
414
|
+
async ({ state }, locationHref = getDefaultLocation()) => {
|
|
415
|
+
const { providedToken, callbackUrl, clientFactory, apiHost, storageArea, storageKey } = state.get().options;
|
|
331
416
|
if (providedToken) return !1;
|
|
332
417
|
const { authState } = state.get();
|
|
333
418
|
if (authState.type === AuthStateType.LOGGING_IN && authState.isExchangingToken) return !1;
|
|
@@ -364,35 +449,403 @@ const authStore = {
|
|
|
364
449
|
} catch (error) {
|
|
365
450
|
return state.set("exchangeSessionForTokenError", { authState: { type: AuthStateType.ERROR, error } }), !1;
|
|
366
451
|
}
|
|
452
|
+
}
|
|
453
|
+
), logout = bindActionGlobally(authStore, async ({ state }) => {
|
|
454
|
+
const { clientFactory, apiHost, providedToken, storageArea, storageKey } = state.get().options;
|
|
455
|
+
if (providedToken) return;
|
|
456
|
+
const { authState } = state.get();
|
|
457
|
+
if (authState.type === AuthStateType.LOGGED_OUT && authState.isDestroyingSession) return;
|
|
458
|
+
const token = authState.type === AuthStateType.LOGGED_IN && authState.token;
|
|
459
|
+
try {
|
|
460
|
+
token && (state.set("loggingOut", {
|
|
461
|
+
authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !0 }
|
|
462
|
+
}), await clientFactory({
|
|
463
|
+
token,
|
|
464
|
+
requestTagPrefix: REQUEST_TAG_PREFIX,
|
|
465
|
+
apiVersion: DEFAULT_API_VERSION$1,
|
|
466
|
+
...apiHost && { apiHost },
|
|
467
|
+
useProjectHostname: !1
|
|
468
|
+
}).request({ uri: "/auth/logout", method: "POST" }));
|
|
469
|
+
} finally {
|
|
470
|
+
state.set("logoutSuccess", {
|
|
471
|
+
authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }
|
|
472
|
+
}), storageArea?.removeItem(storageKey);
|
|
473
|
+
}
|
|
474
|
+
}), DEFAULT_API_VERSION = "2024-11-12", DEFAULT_REQUEST_TAG_PREFIX = "sanity.sdk", allowedKeys = Object.keys({
|
|
475
|
+
apiHost: null,
|
|
476
|
+
useCdn: null,
|
|
477
|
+
token: null,
|
|
478
|
+
perspective: null,
|
|
479
|
+
proxy: null,
|
|
480
|
+
withCredentials: null,
|
|
481
|
+
timeout: null,
|
|
482
|
+
maxRetries: null,
|
|
483
|
+
dataset: null,
|
|
484
|
+
projectId: null,
|
|
485
|
+
scope: null,
|
|
486
|
+
apiVersion: null,
|
|
487
|
+
requestTagPrefix: null,
|
|
488
|
+
useProjectHostname: null
|
|
489
|
+
}), DEFAULT_CLIENT_CONFIG = {
|
|
490
|
+
apiVersion: DEFAULT_API_VERSION,
|
|
491
|
+
useCdn: !1,
|
|
492
|
+
ignoreBrowserTokenWarning: !0,
|
|
493
|
+
allowReconfigure: !1,
|
|
494
|
+
requestTagPrefix: DEFAULT_REQUEST_TAG_PREFIX
|
|
495
|
+
}, clientStore = {
|
|
496
|
+
name: "clientStore",
|
|
497
|
+
getInitialState: (instance) => ({
|
|
498
|
+
clients: {},
|
|
499
|
+
token: getTokenState(instance).getCurrent()
|
|
500
|
+
}),
|
|
501
|
+
initialize(context) {
|
|
502
|
+
const subscription = listenToToken(context);
|
|
503
|
+
return () => subscription.unsubscribe();
|
|
504
|
+
}
|
|
505
|
+
}, listenToToken = ({ instance, state }) => getTokenState(instance).observable.subscribe((token) => {
|
|
506
|
+
state.set("setTokenAndResetClients", { token, clients: {} });
|
|
507
|
+
}), getClientConfigKey = (options) => JSON.stringify(pick(options, ...allowedKeys)), getClient = bindActionGlobally(
|
|
508
|
+
clientStore,
|
|
509
|
+
({ state, instance }, options) => {
|
|
510
|
+
const disallowedKeys = Object.keys(options).filter((key2) => !allowedKeys.includes(key2));
|
|
511
|
+
if (disallowedKeys.length > 0) {
|
|
512
|
+
const listFormatter = new Intl.ListFormat("en", { style: "long", type: "conjunction" });
|
|
513
|
+
throw new Error(
|
|
514
|
+
`The client options provided contains unsupported properties: ${listFormatter.format(disallowedKeys)}. Allowed keys are: ${listFormatter.format(allowedKeys)}.`
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
const { token, clients } = state.get(), projectId = options.projectId ?? instance.config.projectId, dataset = options.dataset ?? instance.config.dataset, apiHost = options.apiHost ?? instance.config.auth?.apiHost, effectiveOptions = {
|
|
518
|
+
...DEFAULT_CLIENT_CONFIG,
|
|
519
|
+
...(options.scope === "global" || !projectId) && { useProjectHostname: !1 },
|
|
520
|
+
...token && { token },
|
|
521
|
+
...options,
|
|
522
|
+
...projectId && { projectId },
|
|
523
|
+
...dataset && { dataset },
|
|
524
|
+
...apiHost && { apiHost }
|
|
525
|
+
}, key = getClientConfigKey(effectiveOptions);
|
|
526
|
+
if (clients[key]) return clients[key];
|
|
527
|
+
const client = createClient(effectiveOptions);
|
|
528
|
+
return state.set("addClient", (prev) => ({ clients: { ...prev.clients, [key]: client } })), client;
|
|
529
|
+
}
|
|
530
|
+
), getClientState = bindActionGlobally(
|
|
531
|
+
clientStore,
|
|
532
|
+
createStateSourceAction(({ instance }, options) => getClient(instance, options))
|
|
533
|
+
), destroyController$1 = ({ state }) => {
|
|
534
|
+
const { controller } = state.get();
|
|
535
|
+
controller && (controller.destroy(), state.set("destroyController", {
|
|
536
|
+
controller: null,
|
|
537
|
+
channels: /* @__PURE__ */ new Map()
|
|
538
|
+
}));
|
|
539
|
+
}, getOrCreateChannel$1 = ({ state }, options) => {
|
|
540
|
+
const controller = state.get().controller;
|
|
541
|
+
if (!controller)
|
|
542
|
+
throw new Error("Controller must be initialized before using or creating channels");
|
|
543
|
+
const channels = state.get().channels, existing = channels.get(options.name);
|
|
544
|
+
if (existing) {
|
|
545
|
+
if (!isEqual(existing.options, options))
|
|
546
|
+
throw new Error(`Channel "${options.name}" already exists with different options`);
|
|
547
|
+
return state.set("incrementChannelRefCount", {
|
|
548
|
+
channels: new Map(channels).set(options.name, {
|
|
549
|
+
...existing,
|
|
550
|
+
refCount: existing.refCount + 1
|
|
551
|
+
})
|
|
552
|
+
}), existing.channel.start(), existing.channel;
|
|
553
|
+
}
|
|
554
|
+
const channel = controller.createChannel(options);
|
|
555
|
+
return channel.start(), state.set("createChannel", {
|
|
556
|
+
channels: new Map(channels).set(options.name, {
|
|
557
|
+
channel,
|
|
558
|
+
options,
|
|
559
|
+
refCount: 1
|
|
560
|
+
})
|
|
561
|
+
}), channel;
|
|
562
|
+
}, getOrCreateController$1 = ({ state, instance }, targetOrigin) => {
|
|
563
|
+
const { controller, controllerOrigin } = state.get();
|
|
564
|
+
if (controller && controllerOrigin === targetOrigin)
|
|
565
|
+
return controller;
|
|
566
|
+
controller && destroyController$1({ state });
|
|
567
|
+
const newController = createController({ targetOrigin });
|
|
568
|
+
return state.set("initializeController", {
|
|
569
|
+
controllerOrigin: targetOrigin,
|
|
570
|
+
controller: newController
|
|
571
|
+
}), newController;
|
|
572
|
+
}, releaseChannel$1 = ({ state }, name) => {
|
|
573
|
+
const channels = state.get().channels, channelEntry = channels.get(name);
|
|
574
|
+
if (channelEntry) {
|
|
575
|
+
const newRefCount = channelEntry.refCount === 0 ? 0 : channelEntry.refCount - 1;
|
|
576
|
+
newRefCount === 0 ? (channelEntry.channel.stop(), channels.delete(name), state.set("releaseChannel", { channels: new Map(channels) })) : state.set("releaseChannel", {
|
|
577
|
+
channels: new Map(channels).set(name, {
|
|
578
|
+
...channelEntry,
|
|
579
|
+
refCount: newRefCount
|
|
580
|
+
})
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
}, comlinkControllerStore = {
|
|
584
|
+
name: "connectionStore",
|
|
585
|
+
getInitialState: () => ({
|
|
586
|
+
controller: null,
|
|
587
|
+
controllerOrigin: null,
|
|
588
|
+
channels: /* @__PURE__ */ new Map()
|
|
589
|
+
}),
|
|
590
|
+
initialize({ instance }) {
|
|
591
|
+
return () => {
|
|
592
|
+
destroyController(instance);
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
}, destroyController = bindActionGlobally(
|
|
596
|
+
comlinkControllerStore,
|
|
597
|
+
destroyController$1
|
|
598
|
+
), getOrCreateChannel = bindActionGlobally(
|
|
599
|
+
comlinkControllerStore,
|
|
600
|
+
getOrCreateChannel$1
|
|
601
|
+
), getOrCreateController = bindActionGlobally(
|
|
602
|
+
comlinkControllerStore,
|
|
603
|
+
getOrCreateController$1
|
|
604
|
+
), releaseChannel = bindActionGlobally(comlinkControllerStore, releaseChannel$1), getOrCreateNode$1 = ({ state }, options) => {
|
|
605
|
+
const nodes = state.get().nodes, existing = nodes.get(options.name);
|
|
606
|
+
if (existing) {
|
|
607
|
+
if (!isEqual(existing.options, options))
|
|
608
|
+
throw new Error(`Node "${options.name}" already exists with different options`);
|
|
609
|
+
return state.set("incrementNodeRefCount", {
|
|
610
|
+
nodes: new Map(nodes).set(options.name, {
|
|
611
|
+
...existing,
|
|
612
|
+
refCount: existing.refCount + 1
|
|
613
|
+
})
|
|
614
|
+
}), existing.node.start(), existing.node;
|
|
615
|
+
}
|
|
616
|
+
const node = createNode(options);
|
|
617
|
+
return node.start(), nodes.set(options.name, { node, options, refCount: 1 }), state.set("createNode", { nodes }), node;
|
|
618
|
+
}, releaseNode$1 = ({ state }, name) => {
|
|
619
|
+
const nodes = state.get().nodes, nodeEntry = nodes.get(name);
|
|
620
|
+
if (nodeEntry) {
|
|
621
|
+
const newRefCount = nodeEntry.refCount === 0 ? 0 : nodeEntry.refCount - 1;
|
|
622
|
+
newRefCount === 0 ? (nodeEntry.node.stop(), nodes.delete(name), state.set("releaseNode", { nodes: new Map(nodes) })) : state.set("releaseNode", {
|
|
623
|
+
nodes: new Map(nodes).set(name, {
|
|
624
|
+
...nodeEntry,
|
|
625
|
+
refCount: newRefCount
|
|
626
|
+
})
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
}, comlinkNodeStore = {
|
|
630
|
+
name: "nodeStore",
|
|
631
|
+
getInitialState: () => ({
|
|
632
|
+
nodes: /* @__PURE__ */ new Map()
|
|
633
|
+
}),
|
|
634
|
+
initialize({ state }) {
|
|
635
|
+
return () => {
|
|
636
|
+
state.get().nodes.forEach(({ node }) => {
|
|
637
|
+
node.stop();
|
|
638
|
+
});
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
}, releaseNode = bindActionGlobally(comlinkNodeStore, releaseNode$1), getOrCreateNode = bindActionGlobally(comlinkNodeStore, getOrCreateNode$1);
|
|
642
|
+
function createFetcherStore({
|
|
643
|
+
name,
|
|
644
|
+
fetcher: getObservable,
|
|
645
|
+
getKey,
|
|
646
|
+
fetchThrottleInternal = 1e3,
|
|
647
|
+
stateExpirationDelay = 5e3
|
|
648
|
+
}) {
|
|
649
|
+
const store = {
|
|
650
|
+
name,
|
|
651
|
+
getInitialState: () => ({
|
|
652
|
+
stateByParams: {}
|
|
653
|
+
}),
|
|
654
|
+
initialize: (context) => {
|
|
655
|
+
const subscription = subscribeToSubscriptionsAndFetch(context);
|
|
656
|
+
return () => subscription.unsubscribe();
|
|
657
|
+
}
|
|
658
|
+
}, subscribeToSubscriptionsAndFetch = ({
|
|
659
|
+
state
|
|
660
|
+
}) => state.observable.pipe(
|
|
661
|
+
// Map the state to an array of [serialized, entry] pairs.
|
|
662
|
+
switchMap$1((s2) => {
|
|
663
|
+
const entries = Object.entries(s2.stateByParams);
|
|
664
|
+
return entries.length > 0 ? from(entries) : EMPTY;
|
|
665
|
+
}),
|
|
666
|
+
// Group by the serialized key.
|
|
667
|
+
groupBy(([key]) => key),
|
|
668
|
+
mergeMap(
|
|
669
|
+
(group$) => group$.pipe(
|
|
670
|
+
// Emit an initial value for pairwise comparisons.
|
|
671
|
+
startWith([group$.key, void 0]),
|
|
672
|
+
pairwise(),
|
|
673
|
+
// Trigger only when the subscriptions array grows.
|
|
674
|
+
filter$1(([[, prevEntry], [, currEntry]]) => {
|
|
675
|
+
const prevSubs = prevEntry?.subscriptions ?? [];
|
|
676
|
+
return (currEntry?.subscriptions ?? []).length > prevSubs.length;
|
|
677
|
+
}),
|
|
678
|
+
map$1(([, [, currEntry]]) => currEntry),
|
|
679
|
+
// Only trigger if we haven't fetched recently.
|
|
680
|
+
filter$1((entry) => {
|
|
681
|
+
const lastFetch = entry?.lastFetchInitiatedAt;
|
|
682
|
+
return lastFetch ? Date.now() - new Date(lastFetch).getTime() >= fetchThrottleInternal : !0;
|
|
683
|
+
}),
|
|
684
|
+
switchMap$1((entry) => entry ? (state.set("setLastFetchInitiatedAt", (prev) => ({
|
|
685
|
+
stateByParams: {
|
|
686
|
+
...prev.stateByParams,
|
|
687
|
+
[entry.key]: {
|
|
688
|
+
...entry,
|
|
689
|
+
...prev.stateByParams[entry.key],
|
|
690
|
+
lastFetchInitiatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
})), getObservable(entry.instance)(...entry.params).pipe(
|
|
694
|
+
// the `createStateSourceAction` util requires the update
|
|
695
|
+
// to
|
|
696
|
+
delay(0, asapScheduler),
|
|
697
|
+
tap(
|
|
698
|
+
(data) => state.set("setData", (prev) => ({
|
|
699
|
+
stateByParams: {
|
|
700
|
+
...prev.stateByParams,
|
|
701
|
+
[entry.key]: {
|
|
702
|
+
...omit(entry, "error"),
|
|
703
|
+
...omit(prev.stateByParams[entry.key], "error"),
|
|
704
|
+
data
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}))
|
|
708
|
+
),
|
|
709
|
+
catchError((error) => (state.set("setError", (prev) => ({
|
|
710
|
+
stateByParams: {
|
|
711
|
+
...prev.stateByParams,
|
|
712
|
+
[entry.key]: {
|
|
713
|
+
...entry,
|
|
714
|
+
...prev.stateByParams[entry.key],
|
|
715
|
+
error
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
})), EMPTY))
|
|
719
|
+
)) : EMPTY)
|
|
720
|
+
)
|
|
721
|
+
)
|
|
722
|
+
).subscribe({
|
|
723
|
+
error: (error) => state.set("setError", { error })
|
|
724
|
+
}), getState = bindActionGlobally(
|
|
725
|
+
store,
|
|
726
|
+
createStateSourceAction({
|
|
727
|
+
selector: ({
|
|
728
|
+
instance,
|
|
729
|
+
state: { stateByParams, error }
|
|
730
|
+
}, ...params) => {
|
|
731
|
+
if (error) throw error;
|
|
732
|
+
const key = getKey(instance, ...params), entry = stateByParams[key];
|
|
733
|
+
if (entry?.error) throw entry.error;
|
|
734
|
+
return entry?.data;
|
|
735
|
+
},
|
|
736
|
+
onSubscribe: ({ instance, state }, ...params) => {
|
|
737
|
+
const subscriptionId = insecureRandomId(), key = getKey(instance, ...params);
|
|
738
|
+
return state.set("addSubscription", (prev) => ({
|
|
739
|
+
stateByParams: {
|
|
740
|
+
...prev.stateByParams,
|
|
741
|
+
[key]: {
|
|
742
|
+
...prev.stateByParams[key],
|
|
743
|
+
instance,
|
|
744
|
+
key,
|
|
745
|
+
params: prev.stateByParams[key]?.params || params,
|
|
746
|
+
subscriptions: [...prev.stateByParams[key]?.subscriptions || [], subscriptionId]
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
})), () => {
|
|
750
|
+
setTimeout(() => {
|
|
751
|
+
state.set("removeSubscription", (prev) => {
|
|
752
|
+
const entry = prev.stateByParams[key];
|
|
753
|
+
if (!entry) return prev;
|
|
754
|
+
const newSubs = (entry.subscriptions || []).filter((id) => id !== subscriptionId);
|
|
755
|
+
return newSubs.length === 0 ? { stateByParams: omit(prev.stateByParams, key) } : {
|
|
756
|
+
stateByParams: {
|
|
757
|
+
...prev.stateByParams,
|
|
758
|
+
[key]: {
|
|
759
|
+
...entry,
|
|
760
|
+
subscriptions: newSubs
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
};
|
|
764
|
+
});
|
|
765
|
+
}, stateExpirationDelay);
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
})
|
|
769
|
+
), resolveState = bindActionGlobally(
|
|
770
|
+
store,
|
|
771
|
+
({ instance }, ...params) => firstValueFrom(getState(instance, ...params).observable.pipe(first((i2) => i2 !== void 0)))
|
|
772
|
+
);
|
|
773
|
+
return { getState, resolveState };
|
|
774
|
+
}
|
|
775
|
+
const API_VERSION$5 = "v2025-02-19", datasets = createFetcherStore({
|
|
776
|
+
name: "Datasets",
|
|
777
|
+
getKey: (instance, options) => {
|
|
778
|
+
const projectId = options?.projectId ?? instance.config.projectId;
|
|
779
|
+
if (!projectId)
|
|
780
|
+
throw new Error("A projectId is required to use the project API.");
|
|
781
|
+
return projectId;
|
|
782
|
+
},
|
|
783
|
+
fetcher: (instance) => (options) => getClientState(instance, {
|
|
784
|
+
apiVersion: API_VERSION$5,
|
|
785
|
+
// non-null assertion is fine because we check above
|
|
786
|
+
projectId: options?.projectId ?? instance.config.projectId,
|
|
787
|
+
useProjectHostname: !0
|
|
788
|
+
}).observable.pipe(switchMap((client) => client.observable.datasets.list()))
|
|
789
|
+
}), getDatasetsState = datasets.getState, resolveDatasets = datasets.resolveState, isSanityMutatePatch = (value) => !(typeof value != "object" || !value || !("type" in value) || typeof value.type != "string" || value.type !== "patch" || !("id" in value) || typeof value.id != "string" || !("patches" in value) || !Array.isArray(value.patches));
|
|
790
|
+
function createDocument(doc) {
|
|
791
|
+
return {
|
|
792
|
+
type: "document.create",
|
|
793
|
+
...doc,
|
|
794
|
+
...doc.documentId && { documentId: getPublishedId(doc.documentId) }
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
function deleteDocument(doc) {
|
|
798
|
+
return {
|
|
799
|
+
type: "document.delete",
|
|
800
|
+
...doc,
|
|
801
|
+
documentId: getPublishedId(doc.documentId)
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
function convertSanityMutatePatch(sanityPatchMutation) {
|
|
805
|
+
return SanityEncoder.encode(sanityPatchMutation).map((i2) => {
|
|
806
|
+
const copy = { ...i2.patch };
|
|
807
|
+
return "id" in copy && delete copy.id, copy;
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
function editDocument(doc, patches) {
|
|
811
|
+
if (isSanityMutatePatch(patches)) {
|
|
812
|
+
const converted = convertSanityMutatePatch(patches) ?? [];
|
|
813
|
+
return {
|
|
814
|
+
...doc,
|
|
815
|
+
type: "document.edit",
|
|
816
|
+
documentId: getPublishedId(doc.documentId),
|
|
817
|
+
patches: converted
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
return {
|
|
821
|
+
...doc,
|
|
822
|
+
type: "document.edit",
|
|
823
|
+
documentId: getPublishedId(doc.documentId),
|
|
824
|
+
...patches && { patches: Array.isArray(patches) ? patches : [patches] }
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
function publishDocument(doc) {
|
|
828
|
+
return {
|
|
829
|
+
type: "document.publish",
|
|
830
|
+
...doc,
|
|
831
|
+
documentId: getPublishedId(doc.documentId)
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
function unpublishDocument(doc) {
|
|
835
|
+
return {
|
|
836
|
+
type: "document.unpublish",
|
|
837
|
+
...doc,
|
|
838
|
+
documentId: getPublishedId(doc.documentId)
|
|
367
839
|
};
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
return
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
const token = authState.type === AuthStateType.LOGGED_IN && authState.token;
|
|
375
|
-
try {
|
|
376
|
-
token && (state.set("loggingOut", {
|
|
377
|
-
authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !0 }
|
|
378
|
-
}), await clientFactory({
|
|
379
|
-
token,
|
|
380
|
-
requestTagPrefix: REQUEST_TAG_PREFIX,
|
|
381
|
-
apiVersion: DEFAULT_API_VERSION$1,
|
|
382
|
-
...apiHost && { apiHost },
|
|
383
|
-
useProjectHostname: !1
|
|
384
|
-
}).request({ uri: "/auth/logout", method: "POST" }));
|
|
385
|
-
} finally {
|
|
386
|
-
state.set("logoutSuccess", {
|
|
387
|
-
authState: { type: AuthStateType.LOGGED_OUT, isDestroyingSession: !1 }
|
|
388
|
-
}), storageArea?.removeItem(storageKey);
|
|
389
|
-
}
|
|
840
|
+
}
|
|
841
|
+
function discardDocument(doc) {
|
|
842
|
+
return {
|
|
843
|
+
type: "document.discard",
|
|
844
|
+
...doc,
|
|
845
|
+
documentId: getPublishedId(doc.documentId)
|
|
390
846
|
};
|
|
391
|
-
});
|
|
392
|
-
function getResourceId(documentResourceId) {
|
|
393
|
-
if (documentResourceId)
|
|
394
|
-
return documentResourceId.split(":")[1];
|
|
395
847
|
}
|
|
848
|
+
const DOCUMENT_STATE_CLEAR_DELAY = 1e3, INITIAL_OUTGOING_THROTTLE_TIME = 1e3, API_VERSION$4 = "vX";
|
|
396
849
|
function parseBracketContent(content) {
|
|
397
850
|
const rangeMatch = content.match(/^(\d*):(\d*)$/);
|
|
398
851
|
if (rangeMatch) {
|
|
@@ -635,447 +1088,77 @@ function ifRevisionID(input, revisionId) {
|
|
|
635
1088
|
);
|
|
636
1089
|
return input;
|
|
637
1090
|
}
|
|
638
|
-
function isNonNullable(t2) {
|
|
639
|
-
return t2 != null;
|
|
640
|
-
}
|
|
641
|
-
const indexCache = /* @__PURE__ */ new WeakMap();
|
|
642
|
-
function getIndexForKey(input, key) {
|
|
643
|
-
if (!Array.isArray(input)) return;
|
|
644
|
-
const cached = indexCache.get(input);
|
|
645
|
-
if (cached) return cached[key];
|
|
646
|
-
const lookup = input.reduce((acc, next, index) => (typeof next?._key == "string" && (acc[next._key] = index), acc), {});
|
|
647
|
-
return indexCache.set(input, lookup), lookup[key];
|
|
648
|
-
}
|
|
649
|
-
function getDeep(input, path) {
|
|
650
|
-
const [currentSegment, ...restOfPath] = path;
|
|
651
|
-
if (currentSegment === void 0) return input;
|
|
652
|
-
if (typeof input != "object" || input === null) return;
|
|
653
|
-
let key;
|
|
654
|
-
if (isKeySegment(currentSegment) ? key = getIndexForKey(input, currentSegment._key) : (typeof currentSegment == "string" || typeof currentSegment == "number") && (key = currentSegment), key === void 0) return;
|
|
655
|
-
const nestedInput = typeof key == "number" && Array.isArray(input) ? input.at(key) : input[key];
|
|
656
|
-
return getDeep(nestedInput, restOfPath);
|
|
657
|
-
}
|
|
658
|
-
function setDeep(input, path, value) {
|
|
659
|
-
const [currentSegment, ...restOfPath] = path;
|
|
660
|
-
if (currentSegment === void 0) return value;
|
|
661
|
-
if (typeof input != "object" || input === null) {
|
|
662
|
-
if (typeof currentSegment == "string")
|
|
663
|
-
return { [currentSegment]: setDeep(null, restOfPath, value) };
|
|
664
|
-
let index;
|
|
665
|
-
if (isKeySegment(currentSegment))
|
|
666
|
-
index = 0;
|
|
667
|
-
else if (typeof currentSegment == "number" && currentSegment >= 0)
|
|
668
|
-
index = currentSegment;
|
|
669
|
-
else
|
|
670
|
-
return input;
|
|
671
|
-
return [
|
|
672
|
-
// fill until index
|
|
673
|
-
...Array.from({ length: index }).fill(null),
|
|
674
|
-
// then set deep here
|
|
675
|
-
setDeep(null, restOfPath, value)
|
|
676
|
-
];
|
|
677
|
-
}
|
|
678
|
-
if (Array.isArray(input)) {
|
|
679
|
-
let index;
|
|
680
|
-
return isKeySegment(currentSegment) ? index = getIndexForKey(input, currentSegment._key) : typeof currentSegment == "number" && (index = currentSegment < 0 ? input.length + currentSegment : currentSegment), index === void 0 ? input : index in input ? input.map(
|
|
681
|
-
(nestedInput, i2) => i2 === index ? setDeep(nestedInput, restOfPath, value) : nestedInput
|
|
682
|
-
) : [
|
|
683
|
-
...input,
|
|
684
|
-
...Array.from({ length: index - input.length }).fill(null),
|
|
685
|
-
setDeep(null, restOfPath, value)
|
|
686
|
-
];
|
|
687
|
-
}
|
|
688
|
-
return typeof currentSegment == "object" ? input : currentSegment in input ? Object.fromEntries(
|
|
689
|
-
Object.entries(input).map(
|
|
690
|
-
([key, nestedInput]) => key === currentSegment ? [key, setDeep(nestedInput, restOfPath, value)] : [key, nestedInput]
|
|
691
|
-
)
|
|
692
|
-
) : { ...input, [currentSegment]: setDeep(null, restOfPath, value) };
|
|
693
|
-
}
|
|
694
|
-
function unsetDeep(input, path) {
|
|
695
|
-
const [currentSegment, ...restOfPath] = path;
|
|
696
|
-
if (currentSegment === void 0 || typeof input != "object" || input === null) return input;
|
|
697
|
-
let _segment;
|
|
698
|
-
if (isKeySegment(currentSegment) ? _segment = getIndexForKey(input, currentSegment._key) : (typeof currentSegment == "string" || typeof currentSegment == "number") && (_segment = currentSegment), _segment === void 0) return input;
|
|
699
|
-
let segment = _segment;
|
|
700
|
-
return typeof segment == "number" && Array.isArray(input) && (segment = segment < 0 ? input.length + segment : segment), segment in input ? restOfPath.length ? Array.isArray(input) ? input.map(
|
|
701
|
-
(nestedInput, index) => index === segment ? unsetDeep(nestedInput, restOfPath) : nestedInput
|
|
702
|
-
) : Object.fromEntries(
|
|
703
|
-
Object.entries(input).map(
|
|
704
|
-
([key, value]) => key === segment ? [key, unsetDeep(value, restOfPath)] : [key, value]
|
|
705
|
-
)
|
|
706
|
-
) : Array.isArray(input) ? input.filter((_nestedInput, index) => index !== segment) : Object.fromEntries(Object.entries(input).filter(([key]) => key !== segment.toString())) : input;
|
|
707
|
-
}
|
|
708
|
-
const DEFAULT_API_VERSION = "2024-11-12", DEFAULT_REQUEST_TAG_PREFIX = "sanity.sdk", clientStore = {
|
|
709
|
-
name: "clientStore",
|
|
710
|
-
getInitialState: (instance) => {
|
|
711
|
-
const { identity, config } = instance, defaultClient = createClient({
|
|
712
|
-
projectId: identity.projectId,
|
|
713
|
-
dataset: identity.dataset,
|
|
714
|
-
token: config?.auth?.token,
|
|
715
|
-
useCdn: !1,
|
|
716
|
-
apiVersion: DEFAULT_API_VERSION,
|
|
717
|
-
requestTagPrefix: DEFAULT_REQUEST_TAG_PREFIX,
|
|
718
|
-
...config?.auth?.apiHost ? { apiHost: config.auth.apiHost } : {}
|
|
719
|
-
}), defaultGlobalClient = createClient({
|
|
720
|
-
token: config?.auth?.token,
|
|
721
|
-
useCdn: !1,
|
|
722
|
-
apiVersion: "vX",
|
|
723
|
-
// Many global APIs are only available under this version, we may need to support other versions in the future
|
|
724
|
-
useProjectHostname: !1,
|
|
725
|
-
requestTagPrefix: DEFAULT_REQUEST_TAG_PREFIX,
|
|
726
|
-
...config?.auth?.apiHost ? { apiHost: config.auth.apiHost } : {}
|
|
727
|
-
});
|
|
728
|
-
return {
|
|
729
|
-
defaultClient,
|
|
730
|
-
defaultGlobalClient
|
|
731
|
-
};
|
|
732
|
-
},
|
|
733
|
-
initialize() {
|
|
734
|
-
const authEventSubscription = subscribeToAuthEvents(this);
|
|
735
|
-
return () => {
|
|
736
|
-
authEventSubscription.unsubscribe();
|
|
737
|
-
};
|
|
738
|
-
}
|
|
739
|
-
}, receiveToken = (prev, token) => {
|
|
740
|
-
const newDefaultClient = prev.defaultClient.withConfig({
|
|
741
|
-
token
|
|
742
|
-
}), newGlobalClient = prev.defaultGlobalClient.withConfig({
|
|
743
|
-
token
|
|
744
|
-
});
|
|
745
|
-
return {
|
|
746
|
-
defaultClient: newDefaultClient,
|
|
747
|
-
defaultGlobalClient: newGlobalClient
|
|
748
|
-
};
|
|
749
|
-
}, subscribeToAuthEvents = createInternalAction(
|
|
750
|
-
({ instance, state }) => () => getTokenState(instance).observable.subscribe((newToken) => {
|
|
751
|
-
state.set("receiveToken", (prev) => receiveToken(prev, newToken ?? void 0));
|
|
752
|
-
})
|
|
753
|
-
), optionsCache = /* @__PURE__ */ new WeakMap(), defaultClientSelector = (state, options) => options?.scope === "global" ? state.defaultGlobalClient : state.defaultClient, memoizedOptionsSelector = createSelector(
|
|
754
|
-
[defaultClientSelector, (_state, options) => options],
|
|
755
|
-
(client, options) => {
|
|
756
|
-
let nestedCache = optionsCache.get(client);
|
|
757
|
-
nestedCache || (nestedCache = /* @__PURE__ */ new Map(), optionsCache.set(client, nestedCache));
|
|
758
|
-
const key = JSON.stringify(options);
|
|
759
|
-
return nestedCache.get(key) || (nestedCache.set(key, options), options);
|
|
760
|
-
}
|
|
761
|
-
), clientSelector = createSelector(
|
|
762
|
-
[defaultClientSelector, memoizedOptionsSelector],
|
|
763
|
-
(client, options) => client.withConfig(options)
|
|
764
|
-
), getClient = createAction(
|
|
765
|
-
clientStore,
|
|
766
|
-
({ state }) => (options) => clientSelector(state.get(), options)
|
|
767
|
-
), getClientState = createStateSourceAction(clientStore, clientSelector), comlinkControllerStore = {
|
|
768
|
-
name: "connectionStore",
|
|
769
|
-
getInitialState: () => ({
|
|
770
|
-
controller: null,
|
|
771
|
-
controllerOrigin: null,
|
|
772
|
-
channels: /* @__PURE__ */ new Map()
|
|
773
|
-
}),
|
|
774
|
-
initialize() {
|
|
775
|
-
return () => {
|
|
776
|
-
destroyController(this);
|
|
777
|
-
};
|
|
778
|
-
}
|
|
779
|
-
}, destroyController = createInternalAction(
|
|
780
|
-
({ state }) => () => {
|
|
781
|
-
const { controller } = state.get();
|
|
782
|
-
controller && (controller.destroy(), state.set("destroyController", {
|
|
783
|
-
controller: null,
|
|
784
|
-
channels: /* @__PURE__ */ new Map()
|
|
785
|
-
}));
|
|
786
|
-
}
|
|
787
|
-
), getOrCreateChannel = createAction(comlinkControllerStore, ({ state }) => (options) => {
|
|
788
|
-
const controller = state.get().controller;
|
|
789
|
-
if (!controller)
|
|
790
|
-
throw new Error("Controller must be initialized before using or creating channels");
|
|
791
|
-
const channels = state.get().channels, existing = channels.get(options.name);
|
|
792
|
-
if (existing) {
|
|
793
|
-
if (!isEqual(existing.options, options))
|
|
794
|
-
throw new Error(`Channel "${options.name}" already exists with different options`);
|
|
795
|
-
return state.set("incrementChannelRefCount", {
|
|
796
|
-
channels: new Map(channels).set(options.name, {
|
|
797
|
-
...existing,
|
|
798
|
-
refCount: existing.refCount + 1
|
|
799
|
-
})
|
|
800
|
-
}), existing.channel.start(), existing.channel;
|
|
801
|
-
}
|
|
802
|
-
const channel = controller.createChannel(options);
|
|
803
|
-
return channel.start(), state.set("createChannel", {
|
|
804
|
-
channels: new Map(channels).set(options.name, {
|
|
805
|
-
channel,
|
|
806
|
-
options,
|
|
807
|
-
refCount: 1
|
|
808
|
-
})
|
|
809
|
-
}), channel;
|
|
810
|
-
}), getOrCreateController = createAction(comlinkControllerStore, ({ state, instance }) => (targetOrigin) => {
|
|
811
|
-
const { controller, controllerOrigin } = state.get();
|
|
812
|
-
if (controller && controllerOrigin === targetOrigin)
|
|
813
|
-
return controller;
|
|
814
|
-
controller && destroyController({ state, instance });
|
|
815
|
-
const newController = createController({ targetOrigin });
|
|
816
|
-
return state.set("initializeController", {
|
|
817
|
-
controllerOrigin: targetOrigin,
|
|
818
|
-
controller: newController
|
|
819
|
-
}), newController;
|
|
820
|
-
}), releaseChannel = createAction(comlinkControllerStore, ({ state }) => (name) => {
|
|
821
|
-
const channels = state.get().channels, channelEntry = channels.get(name);
|
|
822
|
-
if (channelEntry) {
|
|
823
|
-
const newRefCount = channelEntry.refCount === 0 ? 0 : channelEntry.refCount - 1;
|
|
824
|
-
newRefCount === 0 ? (channelEntry.channel.stop(), channels.delete(name), state.set("releaseChannel", { channels: new Map(channels) })) : state.set("releaseChannel", {
|
|
825
|
-
channels: new Map(channels).set(name, {
|
|
826
|
-
...channelEntry,
|
|
827
|
-
refCount: newRefCount
|
|
828
|
-
})
|
|
829
|
-
});
|
|
830
|
-
}
|
|
831
|
-
}), comlinkNodeStore = {
|
|
832
|
-
name: "nodeStore",
|
|
833
|
-
getInitialState: () => ({
|
|
834
|
-
nodes: /* @__PURE__ */ new Map()
|
|
835
|
-
}),
|
|
836
|
-
initialize() {
|
|
837
|
-
return () => {
|
|
838
|
-
this.state.get().nodes.forEach(({ node }) => {
|
|
839
|
-
node.stop();
|
|
840
|
-
});
|
|
841
|
-
};
|
|
842
|
-
}
|
|
843
|
-
}, getOrCreateNode = createAction(comlinkNodeStore, ({ state }) => (options) => {
|
|
844
|
-
const nodes = state.get().nodes, existing = nodes.get(options.name);
|
|
845
|
-
if (existing) {
|
|
846
|
-
if (!isEqual(existing.options, options))
|
|
847
|
-
throw new Error(`Node "${options.name}" already exists with different options`);
|
|
848
|
-
return state.set("incrementNodeRefCount", {
|
|
849
|
-
nodes: new Map(nodes).set(options.name, {
|
|
850
|
-
...existing,
|
|
851
|
-
refCount: existing.refCount + 1
|
|
852
|
-
})
|
|
853
|
-
}), existing.node.start(), existing.node;
|
|
854
|
-
}
|
|
855
|
-
const node = createNode(options);
|
|
856
|
-
return node.start(), nodes.set(options.name, { node, options, refCount: 1 }), state.set("createNode", { nodes }), node;
|
|
857
|
-
}), releaseNode = createAction(comlinkNodeStore, ({ state }) => (name) => {
|
|
858
|
-
const nodes = state.get().nodes, nodeEntry = nodes.get(name);
|
|
859
|
-
if (nodeEntry) {
|
|
860
|
-
const newRefCount = nodeEntry.refCount === 0 ? 0 : nodeEntry.refCount - 1;
|
|
861
|
-
newRefCount === 0 ? (nodeEntry.node.stop(), nodes.delete(name), state.set("releaseNode", { nodes: new Map(nodes) })) : state.set("releaseNode", {
|
|
862
|
-
nodes: new Map(nodes).set(name, {
|
|
863
|
-
...nodeEntry,
|
|
864
|
-
refCount: newRefCount
|
|
865
|
-
})
|
|
866
|
-
});
|
|
867
|
-
}
|
|
868
|
-
});
|
|
869
|
-
function getPublishedId(id) {
|
|
870
|
-
const draftsPrefix = "drafts.";
|
|
871
|
-
return id.startsWith(draftsPrefix) ? id.slice(draftsPrefix.length) : id;
|
|
872
|
-
}
|
|
873
|
-
function getDraftId(id) {
|
|
874
|
-
const draftsPrefix = "drafts.";
|
|
875
|
-
return id.startsWith(draftsPrefix) ? id : `${draftsPrefix}${id}`;
|
|
876
|
-
}
|
|
877
|
-
function insecureRandomId() {
|
|
878
|
-
return Array.from({ length: 16 }, () => Math.floor(Math.random() * 16).toString(16)).join("");
|
|
879
|
-
}
|
|
880
|
-
function createFetcherStore({
|
|
881
|
-
name,
|
|
882
|
-
fetcher: getObservable,
|
|
883
|
-
getKey,
|
|
884
|
-
fetchThrottleInternal = 1e3,
|
|
885
|
-
stateExpirationDelay = 5e3
|
|
886
|
-
}) {
|
|
887
|
-
const store = {
|
|
888
|
-
name,
|
|
889
|
-
getInitialState: () => ({
|
|
890
|
-
stateByParams: {}
|
|
891
|
-
}),
|
|
892
|
-
initialize() {
|
|
893
|
-
const subscription = subscribeToSubscriptionsAndFetch(this);
|
|
894
|
-
return () => subscription.unsubscribe();
|
|
895
|
-
}
|
|
896
|
-
}, subscribeToSubscriptionsAndFetch = createInternalAction(
|
|
897
|
-
({ instance, state }) => function() {
|
|
898
|
-
const factoryFn = getObservable(instance);
|
|
899
|
-
return state.observable.pipe(
|
|
900
|
-
// Map the state to an array of [serialized, entry] pairs.
|
|
901
|
-
switchMap$1((s2) => {
|
|
902
|
-
const entries = Object.entries(s2.stateByParams);
|
|
903
|
-
return entries.length > 0 ? from(entries) : EMPTY;
|
|
904
|
-
}),
|
|
905
|
-
// Group by the serialized key.
|
|
906
|
-
groupBy(([key]) => key),
|
|
907
|
-
mergeMap(
|
|
908
|
-
(group$) => group$.pipe(
|
|
909
|
-
// Emit an initial value for pairwise comparisons.
|
|
910
|
-
startWith([
|
|
911
|
-
group$.key,
|
|
912
|
-
void 0
|
|
913
|
-
]),
|
|
914
|
-
pairwise(),
|
|
915
|
-
// Trigger only when the subscriptions array grows.
|
|
916
|
-
filter$1(([[, prevEntry], [, currEntry]]) => {
|
|
917
|
-
const prevSubs = prevEntry?.subscriptions ?? [];
|
|
918
|
-
return (currEntry?.subscriptions ?? []).length > prevSubs.length;
|
|
919
|
-
}),
|
|
920
|
-
map$1(([, [, currEntry]]) => currEntry),
|
|
921
|
-
// Only trigger if we haven't fetched recently.
|
|
922
|
-
filter$1((entry) => {
|
|
923
|
-
const lastFetch = entry?.lastFetchInitiatedAt;
|
|
924
|
-
return lastFetch ? Date.now() - new Date(lastFetch).getTime() >= fetchThrottleInternal : !0;
|
|
925
|
-
}),
|
|
926
|
-
switchMap$1((entry) => entry ? (state.set(
|
|
927
|
-
"setLastFetchInitiatedAt",
|
|
928
|
-
(prev) => ({
|
|
929
|
-
stateByParams: {
|
|
930
|
-
...prev.stateByParams,
|
|
931
|
-
[entry.key]: {
|
|
932
|
-
...entry,
|
|
933
|
-
...prev.stateByParams[entry.key],
|
|
934
|
-
lastFetchInitiatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
})
|
|
938
|
-
), factoryFn(...entry.params).pipe(
|
|
939
|
-
// the `createStateSourceAction` util requires the update
|
|
940
|
-
// to
|
|
941
|
-
delay(0, asapScheduler),
|
|
942
|
-
tap(
|
|
943
|
-
(data) => state.set("setData", (prev) => ({
|
|
944
|
-
stateByParams: {
|
|
945
|
-
...prev.stateByParams,
|
|
946
|
-
[entry.key]: {
|
|
947
|
-
...omit(entry, "error"),
|
|
948
|
-
...omit(prev.stateByParams[entry.key], "error"),
|
|
949
|
-
data
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
}))
|
|
953
|
-
),
|
|
954
|
-
catchError((error) => (state.set("setError", (prev) => ({
|
|
955
|
-
stateByParams: {
|
|
956
|
-
...prev.stateByParams,
|
|
957
|
-
[entry.key]: {
|
|
958
|
-
...entry,
|
|
959
|
-
...prev.stateByParams[entry.key],
|
|
960
|
-
error
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
})), EMPTY))
|
|
964
|
-
)) : EMPTY)
|
|
965
|
-
)
|
|
966
|
-
)
|
|
967
|
-
).subscribe({
|
|
968
|
-
error: (error) => state.set("setError", { error })
|
|
969
|
-
});
|
|
970
|
-
}
|
|
971
|
-
), getState2 = createStateSourceAction(store, {
|
|
972
|
-
selector: ({ stateByParams, error }, ...params) => {
|
|
973
|
-
if (error) throw error;
|
|
974
|
-
const key = getKey(...params), entry = stateByParams[key];
|
|
975
|
-
if (entry?.error) throw entry.error;
|
|
976
|
-
return entry?.data;
|
|
977
|
-
},
|
|
978
|
-
onSubscribe: ({ state }, ...params) => {
|
|
979
|
-
const subscriptionId = insecureRandomId(), key = getKey(...params);
|
|
980
|
-
return state.set("addSubscription", (prev) => ({
|
|
981
|
-
stateByParams: {
|
|
982
|
-
...prev.stateByParams,
|
|
983
|
-
[key]: {
|
|
984
|
-
...prev.stateByParams[key],
|
|
985
|
-
key,
|
|
986
|
-
params: prev.stateByParams[key]?.params || params,
|
|
987
|
-
subscriptions: [...prev.stateByParams[key]?.subscriptions || [], subscriptionId]
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
})), () => {
|
|
991
|
-
setTimeout(() => {
|
|
992
|
-
state.set("removeSubscription", (prev) => {
|
|
993
|
-
const entry = prev.stateByParams[key];
|
|
994
|
-
if (!entry) return prev;
|
|
995
|
-
const newSubs = (entry.subscriptions || []).filter((id) => id !== subscriptionId);
|
|
996
|
-
return newSubs.length === 0 ? { stateByParams: omit(prev.stateByParams, key) } : {
|
|
997
|
-
stateByParams: {
|
|
998
|
-
...prev.stateByParams,
|
|
999
|
-
[key]: {
|
|
1000
|
-
...entry,
|
|
1001
|
-
subscriptions: newSubs
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
1004
|
-
};
|
|
1005
|
-
});
|
|
1006
|
-
}, stateExpirationDelay);
|
|
1007
|
-
};
|
|
1008
|
-
}
|
|
1009
|
-
}), resolveState = createAction(store, () => function(...params) {
|
|
1010
|
-
return firstValueFrom(
|
|
1011
|
-
getState2(this, ...params).observable.pipe(first((i2) => i2 !== void 0))
|
|
1012
|
-
);
|
|
1013
|
-
});
|
|
1014
|
-
return { getState: getState2, resolveState };
|
|
1015
|
-
}
|
|
1016
|
-
const datasets = createFetcherStore({
|
|
1017
|
-
name: "Datasets",
|
|
1018
|
-
getKey: () => "datasets",
|
|
1019
|
-
fetcher: (instance) => () => getClientState(instance, { apiVersion: "vX", scope: "project" }).observable.pipe(
|
|
1020
|
-
switchMap((client) => client.observable.datasets.list())
|
|
1021
|
-
)
|
|
1022
|
-
}), getDatasetsState = datasets.getState, resolveDatasets = datasets.resolveState, isSanityMutatePatch = (value) => !(typeof value != "object" || !value || !("type" in value) || typeof value.type != "string" || value.type !== "patch" || !("id" in value) || typeof value.id != "string" || !("patches" in value) || !Array.isArray(value.patches));
|
|
1023
|
-
function createDocument(doc) {
|
|
1024
|
-
return {
|
|
1025
|
-
type: "document.create",
|
|
1026
|
-
...doc._id && { documentId: doc._id },
|
|
1027
|
-
documentType: doc._type,
|
|
1028
|
-
...doc.resourceId && { resourceId: doc.resourceId }
|
|
1029
|
-
};
|
|
1030
|
-
}
|
|
1031
|
-
function deleteDocument(doc) {
|
|
1032
|
-
return {
|
|
1033
|
-
type: "document.delete",
|
|
1034
|
-
documentId: getPublishedId(doc._id),
|
|
1035
|
-
...doc.resourceId && { resourceId: doc.resourceId }
|
|
1036
|
-
};
|
|
1037
|
-
}
|
|
1038
|
-
function convertSanityMutatePatch(sanityPatchMutation) {
|
|
1039
|
-
const encoded = SanityEncoder.encode(sanityPatchMutation);
|
|
1040
|
-
return {
|
|
1041
|
-
documentId: sanityPatchMutation.id,
|
|
1042
|
-
type: "document.edit",
|
|
1043
|
-
patches: encoded.map((i2) => {
|
|
1044
|
-
const copy = { ...i2.patch };
|
|
1045
|
-
return "id" in copy && delete copy.id, copy;
|
|
1046
|
-
})
|
|
1047
|
-
};
|
|
1091
|
+
function isNonNullable(t2) {
|
|
1092
|
+
return t2 != null;
|
|
1048
1093
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1094
|
+
const indexCache = /* @__PURE__ */ new WeakMap();
|
|
1095
|
+
function getIndexForKey(input, key) {
|
|
1096
|
+
if (!Array.isArray(input)) return;
|
|
1097
|
+
const cached = indexCache.get(input);
|
|
1098
|
+
if (cached) return cached[key];
|
|
1099
|
+
const lookup = input.reduce((acc, next, index) => (typeof next?._key == "string" && (acc[next._key] = index), acc), {});
|
|
1100
|
+
return indexCache.set(input, lookup), lookup[key];
|
|
1056
1101
|
}
|
|
1057
|
-
function
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1102
|
+
function getDeep(input, path) {
|
|
1103
|
+
const [currentSegment, ...restOfPath] = path;
|
|
1104
|
+
if (currentSegment === void 0) return input;
|
|
1105
|
+
if (typeof input != "object" || input === null) return;
|
|
1106
|
+
let key;
|
|
1107
|
+
if (isKeySegment(currentSegment) ? key = getIndexForKey(input, currentSegment._key) : (typeof currentSegment == "string" || typeof currentSegment == "number") && (key = currentSegment), key === void 0) return;
|
|
1108
|
+
const nestedInput = typeof key == "number" && Array.isArray(input) ? input.at(key) : input[key];
|
|
1109
|
+
return getDeep(nestedInput, restOfPath);
|
|
1063
1110
|
}
|
|
1064
|
-
function
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1111
|
+
function setDeep(input, path, value) {
|
|
1112
|
+
const [currentSegment, ...restOfPath] = path;
|
|
1113
|
+
if (currentSegment === void 0) return value;
|
|
1114
|
+
if (typeof input != "object" || input === null) {
|
|
1115
|
+
if (typeof currentSegment == "string")
|
|
1116
|
+
return { [currentSegment]: setDeep(null, restOfPath, value) };
|
|
1117
|
+
let index;
|
|
1118
|
+
if (isKeySegment(currentSegment))
|
|
1119
|
+
index = 0;
|
|
1120
|
+
else if (typeof currentSegment == "number" && currentSegment >= 0)
|
|
1121
|
+
index = currentSegment;
|
|
1122
|
+
else
|
|
1123
|
+
return input;
|
|
1124
|
+
return [
|
|
1125
|
+
// fill until index
|
|
1126
|
+
...Array.from({ length: index }).fill(null),
|
|
1127
|
+
// then set deep here
|
|
1128
|
+
setDeep(null, restOfPath, value)
|
|
1129
|
+
];
|
|
1130
|
+
}
|
|
1131
|
+
if (Array.isArray(input)) {
|
|
1132
|
+
let index;
|
|
1133
|
+
return isKeySegment(currentSegment) ? index = getIndexForKey(input, currentSegment._key) : typeof currentSegment == "number" && (index = currentSegment < 0 ? input.length + currentSegment : currentSegment), index === void 0 ? input : index in input ? input.map(
|
|
1134
|
+
(nestedInput, i2) => i2 === index ? setDeep(nestedInput, restOfPath, value) : nestedInput
|
|
1135
|
+
) : [
|
|
1136
|
+
...input,
|
|
1137
|
+
...Array.from({ length: index - input.length }).fill(null),
|
|
1138
|
+
setDeep(null, restOfPath, value)
|
|
1139
|
+
];
|
|
1140
|
+
}
|
|
1141
|
+
return typeof currentSegment == "object" ? input : currentSegment in input ? Object.fromEntries(
|
|
1142
|
+
Object.entries(input).map(
|
|
1143
|
+
([key, nestedInput]) => key === currentSegment ? [key, setDeep(nestedInput, restOfPath, value)] : [key, nestedInput]
|
|
1144
|
+
)
|
|
1145
|
+
) : { ...input, [currentSegment]: setDeep(null, restOfPath, value) };
|
|
1070
1146
|
}
|
|
1071
|
-
function
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1147
|
+
function unsetDeep(input, path) {
|
|
1148
|
+
const [currentSegment, ...restOfPath] = path;
|
|
1149
|
+
if (currentSegment === void 0 || typeof input != "object" || input === null) return input;
|
|
1150
|
+
let _segment;
|
|
1151
|
+
if (isKeySegment(currentSegment) ? _segment = getIndexForKey(input, currentSegment._key) : (typeof currentSegment == "string" || typeof currentSegment == "number") && (_segment = currentSegment), _segment === void 0) return input;
|
|
1152
|
+
let segment = _segment;
|
|
1153
|
+
return typeof segment == "number" && Array.isArray(input) && (segment = segment < 0 ? input.length + segment : segment), segment in input ? restOfPath.length ? Array.isArray(input) ? input.map(
|
|
1154
|
+
(nestedInput, index) => index === segment ? unsetDeep(nestedInput, restOfPath) : nestedInput
|
|
1155
|
+
) : Object.fromEntries(
|
|
1156
|
+
Object.entries(input).map(
|
|
1157
|
+
([key, value]) => key === segment ? [key, unsetDeep(value, restOfPath)] : [key, value]
|
|
1158
|
+
)
|
|
1159
|
+
) : Array.isArray(input) ? input.filter((_nestedInput, index) => index !== segment) : Object.fromEntries(Object.entries(input).filter(([key]) => key !== segment.toString())) : input;
|
|
1077
1160
|
}
|
|
1078
|
-
const
|
|
1161
|
+
const patchOperations = {
|
|
1079
1162
|
ifRevisionID,
|
|
1080
1163
|
set,
|
|
1081
1164
|
setIfMissing,
|
|
@@ -1284,50 +1367,48 @@ function sortListenerEvents(options) {
|
|
|
1284
1367
|
mergeMap((state) => of(...state.emitEvents))
|
|
1285
1368
|
);
|
|
1286
1369
|
}
|
|
1287
|
-
const listen =
|
|
1370
|
+
const listen = ({ state }, documentId) => {
|
|
1288
1371
|
const { sharedListener, fetchDocument } = state.get();
|
|
1289
|
-
return
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
if (next.type === "sync")
|
|
1304
|
-
return {
|
|
1305
|
-
type: "sync",
|
|
1306
|
-
documentId,
|
|
1307
|
-
document: next.document,
|
|
1308
|
-
revision: next.document?._rev,
|
|
1309
|
-
timestamp: next.document?._updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
1310
|
-
};
|
|
1311
|
-
const [document] = Object.values(
|
|
1312
|
-
processMutations({
|
|
1313
|
-
documents: { [documentId]: documentState.remote },
|
|
1314
|
-
mutations: next.mutations,
|
|
1315
|
-
transactionId: next.transactionId,
|
|
1316
|
-
timestamp: next.timestamp
|
|
1317
|
-
})
|
|
1318
|
-
), { previousRev, transactionId, timestamp } = next;
|
|
1372
|
+
return sharedListener.events.pipe(
|
|
1373
|
+
concatMap((e3) => e3.type === "welcome" ? fetchDocument(documentId).pipe(
|
|
1374
|
+
map((document) => ({ type: "sync", document }))
|
|
1375
|
+
) : e3.type === "mutation" && e3.documentId === documentId ? of(e3) : EMPTY),
|
|
1376
|
+
sortListenerEvents(),
|
|
1377
|
+
withLatestFrom(
|
|
1378
|
+
state.observable.pipe(
|
|
1379
|
+
map((s2) => s2.documentStates[documentId]),
|
|
1380
|
+
filter(Boolean),
|
|
1381
|
+
distinctUntilChanged()
|
|
1382
|
+
)
|
|
1383
|
+
),
|
|
1384
|
+
map(([next, documentState]) => {
|
|
1385
|
+
if (next.type === "sync")
|
|
1319
1386
|
return {
|
|
1320
|
-
type: "
|
|
1387
|
+
type: "sync",
|
|
1321
1388
|
documentId,
|
|
1322
|
-
document: document
|
|
1323
|
-
revision:
|
|
1324
|
-
timestamp
|
|
1325
|
-
...previousRev && { previousRev }
|
|
1389
|
+
document: next.document,
|
|
1390
|
+
revision: next.document?._rev,
|
|
1391
|
+
timestamp: next.document?._updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
1326
1392
|
};
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1393
|
+
const [document] = Object.values(
|
|
1394
|
+
processMutations({
|
|
1395
|
+
documents: { [documentId]: documentState.remote },
|
|
1396
|
+
mutations: next.mutations,
|
|
1397
|
+
transactionId: next.transactionId,
|
|
1398
|
+
timestamp: next.timestamp
|
|
1399
|
+
})
|
|
1400
|
+
), { previousRev, transactionId, timestamp } = next;
|
|
1401
|
+
return {
|
|
1402
|
+
type: "mutation",
|
|
1403
|
+
documentId,
|
|
1404
|
+
document: document ?? null,
|
|
1405
|
+
revision: transactionId,
|
|
1406
|
+
timestamp,
|
|
1407
|
+
...previousRev && { previousRev }
|
|
1408
|
+
};
|
|
1409
|
+
})
|
|
1410
|
+
);
|
|
1411
|
+
};
|
|
1331
1412
|
class e {
|
|
1332
1413
|
pattern;
|
|
1333
1414
|
patternRe;
|
|
@@ -3189,8 +3270,8 @@ function createGrantsLookup(datasetAcl) {
|
|
|
3189
3270
|
}
|
|
3190
3271
|
const documentsCache = new MultiKeyWeakMap(), actionsCache = /* @__PURE__ */ new WeakMap(), nullReplacer = {}, documentsSelector = createSelector(
|
|
3191
3272
|
[
|
|
3192
|
-
({ documentStates }) => documentStates,
|
|
3193
|
-
(
|
|
3273
|
+
({ state: { documentStates } }) => documentStates,
|
|
3274
|
+
(_context, actions) => actions
|
|
3194
3275
|
],
|
|
3195
3276
|
(documentStates, actions) => {
|
|
3196
3277
|
const documentIds = new Set(
|
|
@@ -3225,7 +3306,11 @@ function checkGrant$1(grantExpr, document) {
|
|
|
3225
3306
|
return C(grantExpr, { params: { document } }).get();
|
|
3226
3307
|
}
|
|
3227
3308
|
const enNarrowConjunction = new Intl.ListFormat("en", { style: "narrow", type: "conjunction" }), calculatePermissions = createSelector(
|
|
3228
|
-
[
|
|
3309
|
+
[
|
|
3310
|
+
({ state: { grants } }) => grants,
|
|
3311
|
+
documentsSelector,
|
|
3312
|
+
memoizedActionsSelector
|
|
3313
|
+
],
|
|
3229
3314
|
(grants, documents, actions) => {
|
|
3230
3315
|
if (!documents || !grants || !actions) return;
|
|
3231
3316
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString(), reasons = [];
|
|
@@ -3795,7 +3880,7 @@ function removeSubscriptionIdFromDocument(prev, documentId, subscriptionId) {
|
|
|
3795
3880
|
}
|
|
3796
3881
|
} : { ...prev, documentStates: omit(prev.documentStates, documentId) } : prev;
|
|
3797
3882
|
}
|
|
3798
|
-
function manageSubscriberIds(state, documentId) {
|
|
3883
|
+
function manageSubscriberIds({ state }, documentId) {
|
|
3799
3884
|
const documentIds = Array.from(
|
|
3800
3885
|
new Set(
|
|
3801
3886
|
(Array.isArray(documentId) ? documentId : [documentId]).flatMap((id) => [
|
|
@@ -3853,9 +3938,11 @@ function getDocumentEvents(outgoing) {
|
|
|
3853
3938
|
)
|
|
3854
3939
|
);
|
|
3855
3940
|
}
|
|
3856
|
-
const API_VERSION$
|
|
3941
|
+
const API_VERSION$3 = "vX";
|
|
3857
3942
|
function createSharedListener(instance) {
|
|
3858
|
-
const events$ = getClientState(instance, {
|
|
3943
|
+
const dispose$ = new Subject(), events$ = getClientState(instance, {
|
|
3944
|
+
apiVersion: API_VERSION$3
|
|
3945
|
+
}).observable.pipe(
|
|
3859
3946
|
switchMap(
|
|
3860
3947
|
(client) => (
|
|
3861
3948
|
// TODO: it seems like the client.listen method is not emitting disconnected
|
|
@@ -3876,17 +3963,21 @@ function createSharedListener(instance) {
|
|
|
3876
3963
|
)
|
|
3877
3964
|
)
|
|
3878
3965
|
),
|
|
3966
|
+
takeUntil(dispose$),
|
|
3879
3967
|
share()
|
|
3880
3968
|
), [welcome$, mutation$] = partition(events$, (e3) => e3.type === "welcome");
|
|
3881
|
-
return
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3969
|
+
return {
|
|
3970
|
+
events: merge(
|
|
3971
|
+
// we replay the welcome event because that event kicks off fetching the document
|
|
3972
|
+
welcome$.pipe(shareReplay(1)),
|
|
3973
|
+
mutation$
|
|
3974
|
+
),
|
|
3975
|
+
dispose: () => dispose$.next()
|
|
3976
|
+
};
|
|
3886
3977
|
}
|
|
3887
3978
|
function createFetchDocument(instance) {
|
|
3888
3979
|
return function(documentId) {
|
|
3889
|
-
return getClientState(instance, { apiVersion: API_VERSION$
|
|
3980
|
+
return getClientState(instance, { apiVersion: API_VERSION$3 }).observable.pipe(
|
|
3890
3981
|
switchMap((client) => createDocumentLoaderFromClient(client)(documentId)),
|
|
3891
3982
|
map((result) => {
|
|
3892
3983
|
if (!result.accessible) {
|
|
@@ -3910,330 +4001,458 @@ const documentStore = {
|
|
|
3910
4001
|
fetchDocument: createFetchDocument(instance),
|
|
3911
4002
|
events: new Subject()
|
|
3912
4003
|
}),
|
|
3913
|
-
initialize() {
|
|
3914
|
-
const
|
|
4004
|
+
initialize(context) {
|
|
4005
|
+
const { sharedListener } = context.state.get(), subscriptions = [
|
|
4006
|
+
subscribeToQueuedAndApplyNextTransaction(context),
|
|
4007
|
+
subscribeToSubscriptionsAndListenToDocuments(context),
|
|
4008
|
+
subscribeToAppliedAndSubmitNextTransaction(context),
|
|
4009
|
+
subscribeToClientAndFetchDatasetAcl(context)
|
|
4010
|
+
];
|
|
3915
4011
|
return () => {
|
|
3916
|
-
|
|
4012
|
+
sharedListener.dispose(), subscriptions.forEach((subscription) => subscription.unsubscribe());
|
|
3917
4013
|
};
|
|
3918
4014
|
}
|
|
3919
4015
|
};
|
|
3920
4016
|
function getDocumentState(...args) {
|
|
3921
4017
|
return _getDocumentState(...args);
|
|
3922
4018
|
}
|
|
3923
|
-
const _getDocumentState =
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
}
|
|
4019
|
+
const _getDocumentState = bindActionByDataset(
|
|
4020
|
+
documentStore,
|
|
4021
|
+
createStateSourceAction({
|
|
4022
|
+
selector: ({ state: { error, documentStates } }, doc, path) => {
|
|
4023
|
+
const documentId = typeof doc == "string" ? doc : doc.documentId;
|
|
4024
|
+
if (error) throw error;
|
|
4025
|
+
const draftId = getDraftId(documentId), publishedId = getPublishedId$1(documentId), draft = documentStates[draftId]?.local, published = documentStates[publishedId]?.local, document = draft ?? published;
|
|
4026
|
+
if (document !== void 0)
|
|
4027
|
+
return path ? jsonMatch(document, path).at(0)?.value : document;
|
|
4028
|
+
},
|
|
4029
|
+
onSubscribe: (context, doc) => manageSubscriberIds(context, typeof doc == "string" ? doc : doc.documentId)
|
|
4030
|
+
})
|
|
4031
|
+
);
|
|
3933
4032
|
function resolveDocument(...args) {
|
|
3934
4033
|
return _resolveDocument(...args);
|
|
3935
4034
|
}
|
|
3936
|
-
const _resolveDocument =
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
const documentId = doc._id;
|
|
3944
|
-
if (error) throw error;
|
|
3945
|
-
const draftId = getDraftId(documentId), publishedId = getPublishedId$1(documentId), draft = documents[draftId], published = documents[publishedId];
|
|
3946
|
-
if (!(draft === void 0 || published === void 0))
|
|
3947
|
-
return !queued.length && !applied.length && !outgoing;
|
|
3948
|
-
},
|
|
3949
|
-
onSubscribe: ({ state }, doc) => manageSubscriberIds(state, doc._id)
|
|
3950
|
-
}), getPermissionsState = createStateSourceAction(documentStore, {
|
|
3951
|
-
selector: calculatePermissions,
|
|
3952
|
-
onSubscribe: ({ state }, actions) => manageSubscriberIds(state, getDocumentIdsFromActions(actions))
|
|
3953
|
-
}), resolvePermissions = createAction(documentStore, () => function(actions) {
|
|
3954
|
-
return firstValueFrom(
|
|
3955
|
-
getPermissionsState(this, actions).observable.pipe(filter((i2) => i2 !== void 0))
|
|
3956
|
-
);
|
|
3957
|
-
}), subscribeDocumentEvents = createAction(documentStore, ({ state }) => {
|
|
3958
|
-
const { events } = state.get();
|
|
3959
|
-
return function(eventHandler) {
|
|
3960
|
-
const subscription = events.subscribe(eventHandler);
|
|
3961
|
-
return () => subscription.unsubscribe();
|
|
3962
|
-
};
|
|
3963
|
-
}), subscribeToQueuedAndApplyNextTransaction = createInternalAction(
|
|
3964
|
-
({ state }) => {
|
|
3965
|
-
const { events } = state.get();
|
|
3966
|
-
return function() {
|
|
3967
|
-
return state.observable.pipe(
|
|
3968
|
-
map(applyFirstQueuedTransaction),
|
|
3969
|
-
distinctUntilChanged(),
|
|
3970
|
-
tap$1((next) => state.set("applyFirstQueuedTransaction", next)),
|
|
3971
|
-
catchError$1((error, caught) => {
|
|
3972
|
-
if (error instanceof ActionError)
|
|
3973
|
-
return state.set(
|
|
3974
|
-
"removeQueuedTransaction",
|
|
3975
|
-
(prev) => removeQueuedTransaction(prev, error.transactionId)
|
|
3976
|
-
), events.next({
|
|
3977
|
-
type: "error",
|
|
3978
|
-
message: error.message,
|
|
3979
|
-
documentId: error.documentId,
|
|
3980
|
-
transactionId: error.transactionId,
|
|
3981
|
-
error
|
|
3982
|
-
}), caught;
|
|
3983
|
-
throw error;
|
|
3984
|
-
})
|
|
3985
|
-
).subscribe({ error: (error) => state.set("setError", { error }) });
|
|
3986
|
-
};
|
|
3987
|
-
}
|
|
3988
|
-
), subscribeToAppliedAndSubmitNextTransaction = createInternalAction(
|
|
3989
|
-
({ state, instance }) => {
|
|
3990
|
-
const { events } = state.get();
|
|
3991
|
-
return function() {
|
|
3992
|
-
return state.observable.pipe(
|
|
3993
|
-
throttle(
|
|
3994
|
-
(s2) => (
|
|
3995
|
-
// if there is no outgoing transaction, we can throttle by the
|
|
3996
|
-
// initial outgoing throttle time…
|
|
3997
|
-
s2.outgoing ? (
|
|
3998
|
-
// …otherwise, wait until the outgoing has been cleared
|
|
3999
|
-
state.observable.pipe(first$1(({ outgoing }) => !outgoing))
|
|
4000
|
-
) : timer(INITIAL_OUTGOING_THROTTLE_TIME)
|
|
4001
|
-
),
|
|
4002
|
-
{ leading: !1, trailing: !0 }
|
|
4003
|
-
),
|
|
4004
|
-
map(transitionAppliedTransactionsToOutgoing),
|
|
4005
|
-
distinctUntilChanged((a2, b2) => a2.outgoing?.transactionId === b2.outgoing?.transactionId),
|
|
4006
|
-
tap$1((next) => state.set("transitionAppliedTransactionsToOutgoing", next)),
|
|
4007
|
-
map((s2) => s2.outgoing),
|
|
4008
|
-
distinctUntilChanged(),
|
|
4009
|
-
withLatestFrom(getClientState(instance, { apiVersion: API_VERSION$2 }).observable),
|
|
4010
|
-
concatMap(([outgoing, client]) => outgoing ? client.observable.action(outgoing.outgoingActions, {
|
|
4011
|
-
transactionId: outgoing.transactionId,
|
|
4012
|
-
skipCrossDatasetReferenceValidation: !0
|
|
4013
|
-
}).pipe(
|
|
4014
|
-
catchError$1((error) => (state.set("revertOutgoingTransaction", revertOutgoingTransaction), events.next({ type: "reverted", message: error.message, outgoing, error }), EMPTY)),
|
|
4015
|
-
map((result) => ({ result, outgoing }))
|
|
4016
|
-
) : EMPTY),
|
|
4017
|
-
tap$1(({ outgoing, result }) => {
|
|
4018
|
-
state.set("cleanupOutgoingTransaction", cleanupOutgoingTransaction);
|
|
4019
|
-
for (const e3 of getDocumentEvents(outgoing)) events.next(e3);
|
|
4020
|
-
events.next({ type: "accepted", outgoing, result });
|
|
4021
|
-
})
|
|
4022
|
-
).subscribe({ error: (error) => state.set("setError", { error }) });
|
|
4023
|
-
};
|
|
4035
|
+
const _resolveDocument = bindActionByDataset(
|
|
4036
|
+
documentStore,
|
|
4037
|
+
({ instance }, doc) => {
|
|
4038
|
+
const documentId = typeof doc == "string" ? doc : doc.documentId;
|
|
4039
|
+
return firstValueFrom(
|
|
4040
|
+
getDocumentState(instance, documentId).observable.pipe(filter((i2) => i2 !== void 0))
|
|
4041
|
+
);
|
|
4024
4042
|
}
|
|
4025
|
-
),
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
catchError$1((error) => {
|
|
4054
|
-
throw error instanceof OutOfSyncError && listen(this, e3.id), error;
|
|
4055
|
-
}),
|
|
4056
|
-
tap$1(
|
|
4057
|
-
(remote) => state.set(
|
|
4058
|
-
"applyRemoteDocument",
|
|
4059
|
-
(prev) => applyRemoteDocument(prev, remote, events)
|
|
4060
|
-
)
|
|
4061
|
-
)
|
|
4062
|
-
) : EMPTY)
|
|
4063
|
-
)
|
|
4064
|
-
)
|
|
4065
|
-
).subscribe({ error: (error) => state.set("setError", { error }) });
|
|
4066
|
-
};
|
|
4043
|
+
), getDocumentSyncStatus = bindActionByDataset(
|
|
4044
|
+
documentStore,
|
|
4045
|
+
createStateSourceAction({
|
|
4046
|
+
selector: ({ state: { error, documentStates: documents, outgoing, applied, queued } }, doc) => {
|
|
4047
|
+
const documentId = typeof doc == "string" ? doc : doc.documentId;
|
|
4048
|
+
if (error) throw error;
|
|
4049
|
+
const draftId = getDraftId(documentId), publishedId = getPublishedId$1(documentId), draft = documents[draftId], published = documents[publishedId];
|
|
4050
|
+
if (!(draft === void 0 || published === void 0))
|
|
4051
|
+
return !queued.length && !applied.length && !outgoing;
|
|
4052
|
+
},
|
|
4053
|
+
onSubscribe: (context, doc) => manageSubscriberIds(context, doc.documentId)
|
|
4054
|
+
})
|
|
4055
|
+
), getPermissionsState = bindActionByDataset(
|
|
4056
|
+
documentStore,
|
|
4057
|
+
createStateSourceAction({
|
|
4058
|
+
selector: calculatePermissions,
|
|
4059
|
+
onSubscribe: (context, actions) => manageSubscriberIds(context, getDocumentIdsFromActions(actions))
|
|
4060
|
+
})
|
|
4061
|
+
), resolvePermissions = bindActionByDataset(
|
|
4062
|
+
documentStore,
|
|
4063
|
+
({ instance }, actions) => firstValueFrom(
|
|
4064
|
+
getPermissionsState(instance, actions).observable.pipe(filter((i2) => i2 !== void 0))
|
|
4065
|
+
)
|
|
4066
|
+
), subscribeDocumentEvents = bindActionByDataset(
|
|
4067
|
+
documentStore,
|
|
4068
|
+
({ state }, eventHandler) => {
|
|
4069
|
+
const { events } = state.get(), subscription = events.subscribe(eventHandler);
|
|
4070
|
+
return () => subscription.unsubscribe();
|
|
4067
4071
|
}
|
|
4068
|
-
),
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
),
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4072
|
+
), subscribeToQueuedAndApplyNextTransaction = ({ state }) => {
|
|
4073
|
+
const { events } = state.get();
|
|
4074
|
+
return state.observable.pipe(
|
|
4075
|
+
map(applyFirstQueuedTransaction),
|
|
4076
|
+
distinctUntilChanged(),
|
|
4077
|
+
tap$1((next) => state.set("applyFirstQueuedTransaction", next)),
|
|
4078
|
+
catchError$1((error, caught) => {
|
|
4079
|
+
if (error instanceof ActionError)
|
|
4080
|
+
return state.set(
|
|
4081
|
+
"removeQueuedTransaction",
|
|
4082
|
+
(prev) => removeQueuedTransaction(prev, error.transactionId)
|
|
4083
|
+
), events.next({
|
|
4084
|
+
type: "error",
|
|
4085
|
+
message: error.message,
|
|
4086
|
+
documentId: error.documentId,
|
|
4087
|
+
transactionId: error.transactionId,
|
|
4088
|
+
error
|
|
4089
|
+
}), caught;
|
|
4090
|
+
throw error;
|
|
4091
|
+
})
|
|
4092
|
+
).subscribe({ error: (error) => state.set("setError", { error }) });
|
|
4093
|
+
}, subscribeToAppliedAndSubmitNextTransaction = ({
|
|
4094
|
+
state,
|
|
4095
|
+
instance
|
|
4096
|
+
}) => {
|
|
4097
|
+
const { events } = state.get();
|
|
4098
|
+
return state.observable.pipe(
|
|
4099
|
+
throttle(
|
|
4100
|
+
(s2) => (
|
|
4101
|
+
// if there is no outgoing transaction, we can throttle by the
|
|
4102
|
+
// initial outgoing throttle time…
|
|
4103
|
+
s2.outgoing ? (
|
|
4104
|
+
// …otherwise, wait until the outgoing has been cleared
|
|
4105
|
+
state.observable.pipe(first$1(({ outgoing }) => !outgoing))
|
|
4106
|
+
) : timer(INITIAL_OUTGOING_THROTTLE_TIME)
|
|
4107
|
+
),
|
|
4108
|
+
{ leading: !1, trailing: !0 }
|
|
4109
|
+
),
|
|
4110
|
+
map(transitionAppliedTransactionsToOutgoing),
|
|
4111
|
+
distinctUntilChanged((a2, b2) => a2.outgoing?.transactionId === b2.outgoing?.transactionId),
|
|
4112
|
+
tap$1((next) => state.set("transitionAppliedTransactionsToOutgoing", next)),
|
|
4113
|
+
map((s2) => s2.outgoing),
|
|
4114
|
+
distinctUntilChanged(),
|
|
4115
|
+
withLatestFrom(getClientState(instance, { apiVersion: API_VERSION$4 }).observable),
|
|
4116
|
+
concatMap(([outgoing, client]) => outgoing ? client.observable.action(outgoing.outgoingActions, {
|
|
4117
|
+
transactionId: outgoing.transactionId,
|
|
4118
|
+
skipCrossDatasetReferenceValidation: !0
|
|
4119
|
+
}).pipe(
|
|
4120
|
+
catchError$1((error) => (state.set("revertOutgoingTransaction", revertOutgoingTransaction), events.next({ type: "reverted", message: error.message, outgoing, error }), EMPTY)),
|
|
4121
|
+
map((result) => ({ result, outgoing }))
|
|
4122
|
+
) : EMPTY),
|
|
4123
|
+
tap$1(({ outgoing, result }) => {
|
|
4124
|
+
state.set("cleanupOutgoingTransaction", cleanupOutgoingTransaction);
|
|
4125
|
+
for (const e3 of getDocumentEvents(outgoing)) events.next(e3);
|
|
4126
|
+
events.next({ type: "accepted", outgoing, result });
|
|
4127
|
+
})
|
|
4128
|
+
).subscribe({ error: (error) => state.set("setError", { error }) });
|
|
4129
|
+
}, subscribeToSubscriptionsAndListenToDocuments = (context) => {
|
|
4130
|
+
const { state } = context, { events } = state.get();
|
|
4131
|
+
return state.observable.pipe(
|
|
4132
|
+
filter((s2) => !!s2.grants),
|
|
4133
|
+
map((s2) => Object.keys(s2.documentStates)),
|
|
4134
|
+
distinctUntilChanged((curr, next) => {
|
|
4135
|
+
if (curr.length !== next.length) return !1;
|
|
4136
|
+
const currSet = new Set(curr);
|
|
4137
|
+
return next.every((i2) => currSet.has(i2));
|
|
4138
|
+
}),
|
|
4139
|
+
startWith$1(/* @__PURE__ */ new Set()),
|
|
4140
|
+
pairwise$1(),
|
|
4141
|
+
switchMap((pair) => {
|
|
4142
|
+
const [curr, next] = pair.map((ids) => new Set(ids)), added = Array.from(next).filter((i2) => !curr.has(i2)), removed = Array.from(curr).filter((i2) => !next.has(i2)), changes = [
|
|
4143
|
+
...added.map((id) => ({ id, add: !0 })),
|
|
4144
|
+
...removed.map((id) => ({ id, add: !1 }))
|
|
4145
|
+
].sort((a2, b2) => {
|
|
4146
|
+
const aIsDraft = a2.id === getDraftId(a2.id), bIsDraft = b2.id === getDraftId(b2.id);
|
|
4147
|
+
return aIsDraft && bIsDraft ? a2.id.localeCompare(b2.id, "en-US") : aIsDraft ? -1 : bIsDraft ? 1 : a2.id.localeCompare(b2.id, "en-US");
|
|
4083
4148
|
});
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
)
|
|
4149
|
+
return of(...changes);
|
|
4150
|
+
}),
|
|
4151
|
+
groupBy$1((i2) => i2.id),
|
|
4152
|
+
mergeMap$1(
|
|
4153
|
+
(group) => group.pipe(
|
|
4154
|
+
switchMap((e3) => e3.add ? listen(context, e3.id).pipe(
|
|
4155
|
+
catchError$1((error) => {
|
|
4156
|
+
throw error instanceof OutOfSyncError && listen(context, e3.id), error;
|
|
4157
|
+
}),
|
|
4158
|
+
tap$1(
|
|
4159
|
+
(remote) => state.set(
|
|
4160
|
+
"applyRemoteDocument",
|
|
4161
|
+
(prev) => applyRemoteDocument(prev, remote, events)
|
|
4162
|
+
)
|
|
4163
|
+
)
|
|
4164
|
+
) : EMPTY)
|
|
4165
|
+
)
|
|
4166
|
+
)
|
|
4167
|
+
).subscribe({ error: (error) => state.set("setError", { error }) });
|
|
4168
|
+
}, subscribeToClientAndFetchDatasetAcl = ({
|
|
4169
|
+
instance,
|
|
4170
|
+
state
|
|
4171
|
+
}) => {
|
|
4172
|
+
const { projectId, dataset } = instance.config;
|
|
4173
|
+
return getClientState(instance, { apiVersion: API_VERSION$4 }).observable.pipe(
|
|
4174
|
+
switchMap(
|
|
4175
|
+
(client) => client.observable.request({
|
|
4176
|
+
uri: `/projects/${projectId}/datasets/${dataset}/acl`,
|
|
4177
|
+
tag: "acl.get",
|
|
4178
|
+
withCredentials: !0
|
|
4179
|
+
})
|
|
4180
|
+
),
|
|
4181
|
+
tap$1((datasetAcl) => state.set("setGrants", { grants: createGrantsLookup(datasetAcl) }))
|
|
4182
|
+
).subscribe({
|
|
4183
|
+
error: (error) => state.set("setError", { error })
|
|
4184
|
+
});
|
|
4185
|
+
};
|
|
4087
4186
|
function applyDocumentActions(...args) {
|
|
4088
|
-
return
|
|
4187
|
+
return boundApplyDocumentActions(...args);
|
|
4089
4188
|
}
|
|
4090
|
-
const
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
), appliedTransaction$ = state.observable.pipe(
|
|
4105
|
-
map((s2) => s2.applied),
|
|
4106
|
-
distinctUntilChanged(),
|
|
4107
|
-
map((applied) => applied.find((t2) => t2.transactionId === transactionId)),
|
|
4108
|
-
first$1(Boolean)
|
|
4109
|
-
), successfulTransaction$ = events.pipe(
|
|
4110
|
-
filter((e3) => e3.type === "accepted"),
|
|
4111
|
-
first$1((e3) => e3.outgoing.batchedTransactionIds.includes(transactionId))
|
|
4112
|
-
), rejectedTransaction$ = events.pipe(
|
|
4113
|
-
filter((e3) => e3.type === "reverted"),
|
|
4114
|
-
first$1((e3) => e3.outgoing.batchedTransactionIds.includes(transactionId))
|
|
4115
|
-
), appliedTransactionOrError = firstValueFrom(
|
|
4116
|
-
race([fatalError$, transactionError$, appliedTransaction$])
|
|
4117
|
-
), acceptedOrRejectedTransaction = firstValueFrom(
|
|
4118
|
-
race([successfulTransaction$, rejectedTransaction$, transactionError$])
|
|
4119
|
-
);
|
|
4120
|
-
state.set("queueTransaction", (prev) => queueTransaction(prev, transaction));
|
|
4121
|
-
const result = await appliedTransactionOrError;
|
|
4122
|
-
if ("type" in result && result.type === "error") throw result.error;
|
|
4123
|
-
const { working: documents, previous, previousRevs } = result, existingIds = new Set(
|
|
4124
|
-
Object.entries(previous).filter(([, value]) => !!value).map(([key]) => key)
|
|
4125
|
-
), resultingIds = new Set(
|
|
4126
|
-
Object.entries(documents).filter(([, value]) => !!value).map(([key]) => key)
|
|
4127
|
-
), allIds = /* @__PURE__ */ new Set([...existingIds, ...resultingIds]), updated = [], appeared = [], disappeared = [];
|
|
4128
|
-
for (const id of allIds)
|
|
4129
|
-
existingIds.has(id) && resultingIds.has(id) ? updated.push(id) : !existingIds.has(id) && resultingIds.has(id) ? appeared.push(id) : !resultingIds.has(id) && existingIds.has(id) && disappeared.push(id);
|
|
4130
|
-
async function submitted() {
|
|
4131
|
-
const raceResult = await acceptedOrRejectedTransaction;
|
|
4132
|
-
if (raceResult.type !== "accepted") throw raceResult.error;
|
|
4133
|
-
return raceResult.result;
|
|
4189
|
+
const boundApplyDocumentActions = bindActionByDataset(documentStore, _applyDocumentActions);
|
|
4190
|
+
async function _applyDocumentActions({ instance, state }, actionOrActions, { transactionId = crypto.randomUUID(), disableBatching } = {}) {
|
|
4191
|
+
const actions = Array.isArray(actionOrActions) ? actionOrActions : [actionOrActions];
|
|
4192
|
+
let projectId, dataset;
|
|
4193
|
+
for (const action of actions)
|
|
4194
|
+
if (action.projectId) {
|
|
4195
|
+
if (projectId || (projectId = action.projectId), action.projectId !== projectId)
|
|
4196
|
+
throw new Error(
|
|
4197
|
+
`Mismatched project IDs found in actions. All actions must belong to the same project. Found "${action.projectId}" but expected "${projectId}".`
|
|
4198
|
+
);
|
|
4199
|
+
if (action.dataset && (dataset || (dataset = action.dataset), action.dataset !== dataset))
|
|
4200
|
+
throw new Error(
|
|
4201
|
+
`Mismatched datasets found in actions. All actions must belong to the same dataset. Found "${action.dataset}" but expected "${dataset}".`
|
|
4202
|
+
);
|
|
4134
4203
|
}
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
};
|
|
4204
|
+
if (projectId && projectId !== instance.config.projectId || dataset && dataset !== instance.config.dataset) {
|
|
4205
|
+
const matchedInstance = instance.match({ projectId, dataset });
|
|
4206
|
+
if (!matchedInstance)
|
|
4207
|
+
throw new Error(
|
|
4208
|
+
`Could not find a matching instance for projectId: "${projectId}" and dataset: "${dataset}"`
|
|
4209
|
+
);
|
|
4210
|
+
return boundApplyDocumentActions(matchedInstance, actionOrActions, {
|
|
4211
|
+
disableBatching,
|
|
4212
|
+
transactionId
|
|
4213
|
+
});
|
|
4214
|
+
}
|
|
4215
|
+
const { events } = state.get(), transaction = {
|
|
4216
|
+
transactionId,
|
|
4217
|
+
actions,
|
|
4218
|
+
...disableBatching && { disableBatching }
|
|
4219
|
+
}, fatalError$ = state.observable.pipe(
|
|
4220
|
+
map((s2) => s2.error),
|
|
4221
|
+
first$1(Boolean),
|
|
4222
|
+
map((error) => ({ type: "error", error }))
|
|
4223
|
+
), transactionError$ = events.pipe(
|
|
4224
|
+
filter((e3) => e3.type === "error"),
|
|
4225
|
+
first$1((e3) => e3.transactionId === transactionId)
|
|
4226
|
+
), appliedTransaction$ = state.observable.pipe(
|
|
4227
|
+
map((s2) => s2.applied),
|
|
4228
|
+
distinctUntilChanged(),
|
|
4229
|
+
map((applied) => applied.find((t2) => t2.transactionId === transactionId)),
|
|
4230
|
+
first$1(Boolean)
|
|
4231
|
+
), successfulTransaction$ = events.pipe(
|
|
4232
|
+
filter((e3) => e3.type === "accepted"),
|
|
4233
|
+
first$1((e3) => e3.outgoing.batchedTransactionIds.includes(transactionId))
|
|
4234
|
+
), rejectedTransaction$ = events.pipe(
|
|
4235
|
+
filter((e3) => e3.type === "reverted"),
|
|
4236
|
+
first$1((e3) => e3.outgoing.batchedTransactionIds.includes(transactionId))
|
|
4237
|
+
), appliedTransactionOrError = firstValueFrom(
|
|
4238
|
+
race([fatalError$, transactionError$, appliedTransaction$])
|
|
4239
|
+
), acceptedOrRejectedTransaction = firstValueFrom(
|
|
4240
|
+
race([successfulTransaction$, rejectedTransaction$, transactionError$])
|
|
4241
|
+
);
|
|
4242
|
+
state.set("queueTransaction", (prev) => queueTransaction(prev, transaction));
|
|
4243
|
+
const result = await appliedTransactionOrError;
|
|
4244
|
+
if ("type" in result && result.type === "error") throw result.error;
|
|
4245
|
+
const { working: documents, previous, previousRevs } = result, existingIds = new Set(
|
|
4246
|
+
Object.entries(previous).filter(([, value]) => !!value).map(([key]) => key)
|
|
4247
|
+
), resultingIds = new Set(
|
|
4248
|
+
Object.entries(documents).filter(([, value]) => !!value).map(([key]) => key)
|
|
4249
|
+
), allIds = /* @__PURE__ */ new Set([...existingIds, ...resultingIds]), updated = [], appeared = [], disappeared = [];
|
|
4250
|
+
for (const id of allIds)
|
|
4251
|
+
existingIds.has(id) && resultingIds.has(id) ? updated.push(id) : !existingIds.has(id) && resultingIds.has(id) ? appeared.push(id) : !resultingIds.has(id) && existingIds.has(id) && disappeared.push(id);
|
|
4252
|
+
async function submitted() {
|
|
4253
|
+
const raceResult = await acceptedOrRejectedTransaction;
|
|
4254
|
+
if (raceResult.type !== "accepted") throw raceResult.error;
|
|
4255
|
+
return raceResult.result;
|
|
4256
|
+
}
|
|
4257
|
+
return {
|
|
4258
|
+
transactionId,
|
|
4259
|
+
documents,
|
|
4260
|
+
previous,
|
|
4261
|
+
previousRevs,
|
|
4262
|
+
appeared,
|
|
4263
|
+
updated,
|
|
4264
|
+
disappeared,
|
|
4265
|
+
submitted
|
|
4145
4266
|
};
|
|
4146
|
-
});
|
|
4147
|
-
function getSdkIdentity({
|
|
4148
|
-
projectId,
|
|
4149
|
-
dataset
|
|
4150
|
-
}) {
|
|
4151
|
-
const id = generateId();
|
|
4152
|
-
return Object.freeze({
|
|
4153
|
-
id,
|
|
4154
|
-
projectId,
|
|
4155
|
-
dataset,
|
|
4156
|
-
resourceId: `${projectId}.${dataset}`
|
|
4157
|
-
});
|
|
4158
4267
|
}
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4268
|
+
const QUERY_STATE_CLEAR_DELAY = 1e3, QUERY_STORE_API_VERSION = "vX", setQueryError = (key, error) => (prev) => {
|
|
4269
|
+
const prevQuery = prev.queries[key];
|
|
4270
|
+
return prevQuery ? { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, error } } } : prev;
|
|
4271
|
+
}, setQueryData = (key, result, syncTags) => (prev) => {
|
|
4272
|
+
const prevQuery = prev.queries[key];
|
|
4273
|
+
return prevQuery ? {
|
|
4274
|
+
...prev,
|
|
4275
|
+
queries: { ...prev.queries, [key]: { ...prevQuery, result: result ?? null, syncTags } }
|
|
4276
|
+
} : prev;
|
|
4277
|
+
}, setLastLiveEventId = (key, lastLiveEventId) => (prev) => {
|
|
4278
|
+
const prevQuery = prev.queries[key];
|
|
4279
|
+
return prevQuery ? { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, lastLiveEventId } } } : prev;
|
|
4280
|
+
}, addSubscriber = (key, subscriptionId) => (prev) => {
|
|
4281
|
+
const prevQuery = prev.queries[key], subscribers = [...prevQuery?.subscribers ?? [], subscriptionId];
|
|
4282
|
+
return { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, subscribers } } };
|
|
4283
|
+
}, removeSubscriber = (key, subscriptionId) => (prev) => {
|
|
4284
|
+
const prevQuery = prev.queries[key];
|
|
4285
|
+
if (!prevQuery) return prev;
|
|
4286
|
+
const subscribers = prevQuery.subscribers.filter((id) => id !== subscriptionId);
|
|
4287
|
+
return subscribers.length ? { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, subscribers } } } : { ...prev, queries: omit(prev.queries, key) };
|
|
4288
|
+
}, cancelQuery = (key) => (prev) => {
|
|
4289
|
+
const prevQuery = prev.queries[key];
|
|
4290
|
+
return !prevQuery || prevQuery.subscribers.length ? prev : { ...prev, queries: omit(prev.queries, key) };
|
|
4291
|
+
}, initializeQuery = (key) => (prev) => prev.queries[key] ? prev : { ...prev, queries: { ...prev.queries, [key]: { subscribers: [] } } }, EMPTY_ARRAY = [], getQueryKey = (query, options = {}) => JSON.stringify({ query, options }), parseQueryKey = (key) => JSON.parse(key), queryStore = {
|
|
4292
|
+
name: "QueryStore",
|
|
4293
|
+
getInitialState: () => ({ queries: {} }),
|
|
4294
|
+
initialize(context) {
|
|
4295
|
+
const subscriptions = [
|
|
4296
|
+
listenForNewSubscribersAndFetch(context),
|
|
4297
|
+
listenToLiveClientAndSetLastLiveEventIds(context)
|
|
4298
|
+
];
|
|
4299
|
+
return () => {
|
|
4300
|
+
for (const subscription of subscriptions)
|
|
4301
|
+
subscription.unsubscribe();
|
|
4302
|
+
};
|
|
4303
|
+
}
|
|
4304
|
+
}, errorHandler$1 = (state) => (error) => state.set("setError", { error }), listenForNewSubscribersAndFetch = ({ state, instance }) => state.observable.pipe(
|
|
4305
|
+
map((s2) => new Set(Object.keys(s2.queries))),
|
|
4306
|
+
distinctUntilChanged((curr, next) => curr.size !== next.size ? !1 : Array.from(next).every((i2) => curr.has(i2))),
|
|
4307
|
+
startWith$1(/* @__PURE__ */ new Set()),
|
|
4308
|
+
pairwise$1(),
|
|
4309
|
+
mergeMap$1(([curr, next]) => {
|
|
4310
|
+
const added = Array.from(next).filter((i2) => !curr.has(i2)), removed = Array.from(curr).filter((i2) => !next.has(i2));
|
|
4311
|
+
return [
|
|
4312
|
+
...added.map((key) => ({ key, added: !0 })),
|
|
4313
|
+
...removed.map((key) => ({ key, added: !1 }))
|
|
4314
|
+
];
|
|
4315
|
+
}),
|
|
4316
|
+
groupBy$1((i2) => i2.key),
|
|
4317
|
+
mergeMap$1(
|
|
4318
|
+
(group$) => group$.pipe(
|
|
4319
|
+
switchMap((e3) => {
|
|
4320
|
+
if (!e3.added) return EMPTY;
|
|
4321
|
+
const lastLiveEventId$ = state.observable.pipe(
|
|
4322
|
+
map((s2) => s2.queries[group$.key]?.lastLiveEventId),
|
|
4323
|
+
distinctUntilChanged()
|
|
4324
|
+
), { query, options: { params, projectId, dataset, tag, ...options } = {} } = parseQueryKey(group$.key), client$ = getClientState(instance, {
|
|
4325
|
+
apiVersion: QUERY_STORE_API_VERSION,
|
|
4326
|
+
projectId,
|
|
4327
|
+
dataset
|
|
4328
|
+
}).observable;
|
|
4329
|
+
return combineLatest([lastLiveEventId$, client$]).pipe(
|
|
4330
|
+
switchMap(
|
|
4331
|
+
([lastLiveEventId, client]) => client.observable.fetch(query, params, {
|
|
4332
|
+
...options,
|
|
4333
|
+
filterResponse: !1,
|
|
4334
|
+
returnQuery: !1,
|
|
4335
|
+
lastLiveEventId,
|
|
4336
|
+
tag
|
|
4337
|
+
})
|
|
4338
|
+
)
|
|
4339
|
+
);
|
|
4340
|
+
}),
|
|
4341
|
+
catchError$1((error) => (state.set("setQueryError", setQueryError(group$.key, error)), EMPTY)),
|
|
4342
|
+
tap$1(({ result, syncTags }) => {
|
|
4343
|
+
state.set("setQueryData", setQueryData(group$.key, result, syncTags));
|
|
4344
|
+
})
|
|
4345
|
+
)
|
|
4346
|
+
)
|
|
4347
|
+
).subscribe({ error: errorHandler$1(state) }), listenToLiveClientAndSetLastLiveEventIds = ({
|
|
4348
|
+
state,
|
|
4349
|
+
instance
|
|
4350
|
+
}) => {
|
|
4351
|
+
const liveMessages$ = getClientState(instance, {
|
|
4352
|
+
apiVersion: QUERY_STORE_API_VERSION
|
|
4353
|
+
}).observable.pipe(
|
|
4354
|
+
switchMap(
|
|
4355
|
+
(client) => client.live.events({ includeDrafts: !!client.config().token, tag: "query-store" })
|
|
4356
|
+
),
|
|
4357
|
+
share(),
|
|
4358
|
+
filter((e3) => e3.type === "message")
|
|
4359
|
+
);
|
|
4360
|
+
return state.observable.pipe(
|
|
4361
|
+
mergeMap$1((s2) => Object.entries(s2.queries)),
|
|
4362
|
+
groupBy$1(([key]) => key),
|
|
4363
|
+
mergeMap$1((group$) => {
|
|
4364
|
+
const syncTags$ = group$.pipe(
|
|
4365
|
+
map(([, queryState]) => queryState),
|
|
4366
|
+
map((i2) => i2?.syncTags ?? EMPTY_ARRAY),
|
|
4367
|
+
distinctUntilChanged()
|
|
4368
|
+
);
|
|
4369
|
+
return combineLatest([liveMessages$, syncTags$]).pipe(
|
|
4370
|
+
filter(([message, syncTags]) => message.tags.some((tag) => syncTags.includes(tag))),
|
|
4371
|
+
tap$1(([message]) => {
|
|
4372
|
+
state.set("setLastLiveEventId", setLastLiveEventId(group$.key, message.id));
|
|
4373
|
+
})
|
|
4374
|
+
);
|
|
4375
|
+
})
|
|
4376
|
+
).subscribe({ error: errorHandler$1(state) });
|
|
4377
|
+
};
|
|
4378
|
+
function getQueryState(...args) {
|
|
4379
|
+
return _getQueryState(...args);
|
|
4380
|
+
}
|
|
4381
|
+
const _getQueryState = bindActionByDataset(
|
|
4382
|
+
queryStore,
|
|
4383
|
+
createStateSourceAction({
|
|
4384
|
+
selector: ({ state }, query, options) => {
|
|
4385
|
+
if (state.error) throw state.error;
|
|
4386
|
+
const key = getQueryKey(query, options), queryState = state.queries[key];
|
|
4387
|
+
if (queryState?.error) throw queryState.error;
|
|
4388
|
+
return queryState?.result;
|
|
4389
|
+
},
|
|
4390
|
+
onSubscribe: ({ state }, query, options) => {
|
|
4391
|
+
const subscriptionId = insecureRandomId(), key = getQueryKey(query, options);
|
|
4392
|
+
return state.set("addSubscriber", addSubscriber(key, subscriptionId)), () => {
|
|
4393
|
+
setTimeout(
|
|
4394
|
+
() => state.set("removeSubscriber", removeSubscriber(key, subscriptionId)),
|
|
4395
|
+
QUERY_STATE_CLEAR_DELAY
|
|
4396
|
+
);
|
|
4397
|
+
};
|
|
4398
|
+
}
|
|
4399
|
+
})
|
|
4400
|
+
);
|
|
4401
|
+
function resolveQuery(...args) {
|
|
4402
|
+
return _resolveQuery(...args);
|
|
4176
4403
|
}
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4404
|
+
const _resolveQuery = bindActionByDataset(
|
|
4405
|
+
queryStore,
|
|
4406
|
+
({ state, instance }, query, { signal, ...options } = {}) => {
|
|
4407
|
+
const { getCurrent } = getQueryState(instance, query, options), key = getQueryKey(query, options), aborted$ = signal ? new Observable((observer) => {
|
|
4408
|
+
const cleanup = () => {
|
|
4409
|
+
signal.removeEventListener("abort", listener);
|
|
4410
|
+
}, listener = () => {
|
|
4411
|
+
observer.error(new DOMException("The operation was aborted.", "AbortError")), observer.complete(), cleanup();
|
|
4412
|
+
};
|
|
4413
|
+
return signal.addEventListener("abort", listener), cleanup;
|
|
4414
|
+
}).pipe(
|
|
4415
|
+
catchError$1((error) => {
|
|
4416
|
+
throw error instanceof Error && error.name === "AbortError" && state.set("cancelQuery", cancelQuery(key)), error;
|
|
4417
|
+
})
|
|
4418
|
+
) : NEVER;
|
|
4419
|
+
state.set("initializeQuery", initializeQuery(key));
|
|
4420
|
+
const resolved$ = state.observable.pipe(
|
|
4421
|
+
map(getCurrent),
|
|
4422
|
+
first$1((i2) => i2 !== void 0)
|
|
4182
4423
|
);
|
|
4183
|
-
return
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
(client) => client.live.events({ includeDrafts: !!client.config().token, tag }).pipe(filter((e3) => e3.type === "message"))
|
|
4187
|
-
)
|
|
4188
|
-
);
|
|
4189
|
-
return combineLatest([messageEvents$, syncTags$]).subscribe({
|
|
4190
|
-
next: ([event, currentSyncTags]) => {
|
|
4191
|
-
for (const eventTag of event.tags)
|
|
4192
|
-
if (currentSyncTags[eventTag]) {
|
|
4193
|
-
state.set("setLastLiveEventId", (prevState) => ({
|
|
4194
|
-
...prevState,
|
|
4195
|
-
lastLiveEventId: event.id
|
|
4196
|
-
}));
|
|
4197
|
-
return;
|
|
4198
|
-
}
|
|
4199
|
-
}
|
|
4200
|
-
});
|
|
4201
|
-
};
|
|
4202
|
-
});
|
|
4203
|
-
}
|
|
4424
|
+
return firstValueFrom(race([resolved$, aborted$]));
|
|
4425
|
+
}
|
|
4426
|
+
);
|
|
4204
4427
|
function hashString(str) {
|
|
4205
4428
|
let hash = 0;
|
|
4206
4429
|
for (let i2 = 0; i2 < str.length; i2++)
|
|
4207
4430
|
hash = (hash * 31 + str.charCodeAt(i2)) % 2147483647;
|
|
4208
4431
|
return Math.abs(hash).toString(16).padStart(8, "0");
|
|
4209
4432
|
}
|
|
4210
|
-
const TITLE_CANDIDATES = ["title", "name", "label", "heading", "header", "caption"], SUBTITLE_CANDIDATES = ["description", "subtitle", ...TITLE_CANDIDATES]
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
"titleCandidates": {
|
|
4215
|
-
${TITLE_CANDIDATES.map((field) => `"${field}": ${field}`).join(`,
|
|
4433
|
+
const TITLE_CANDIDATES = ["title", "name", "label", "heading", "header", "caption"], SUBTITLE_CANDIDATES = ["description", "subtitle", ...TITLE_CANDIDATES], PREVIEW_PROJECTION = `{
|
|
4434
|
+
// Get all potential title fields
|
|
4435
|
+
"titleCandidates": {
|
|
4436
|
+
${TITLE_CANDIDATES.map((field) => `"${field}": ${field}`).join(`,
|
|
4216
4437
|
`)}
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4438
|
+
},
|
|
4439
|
+
// Get all potential subtitle fields
|
|
4440
|
+
"subtitleCandidates": {
|
|
4441
|
+
${SUBTITLE_CANDIDATES.map((field) => `"${field}": ${field}`).join(`,
|
|
4221
4442
|
`)}
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
}
|
|
4236
|
-
const PREVIEW_TAG = "preview", STABLE_EMPTY_PREVIEW = { data: null, isPending: !1 }, STABLE_ERROR_PREVIEW = {
|
|
4443
|
+
},
|
|
4444
|
+
"media": coalesce(
|
|
4445
|
+
select(
|
|
4446
|
+
defined(asset) => {"type": "image-asset", "_ref": asset._ref},
|
|
4447
|
+
defined(image.asset) => {"type": "image-asset", "_ref": image.asset._ref},
|
|
4448
|
+
defined(mainImage.asset) => {"type": "image-asset", "_ref": mainImage.asset._ref},
|
|
4449
|
+
null
|
|
4450
|
+
)
|
|
4451
|
+
),
|
|
4452
|
+
_type,
|
|
4453
|
+
_id,
|
|
4454
|
+
_updatedAt
|
|
4455
|
+
}`, PREVIEW_TAG = "preview", PREVIEW_PERSPECTIVE = "drafts", STABLE_EMPTY_PREVIEW = { data: null, isPending: !1 }, STABLE_ERROR_PREVIEW = {
|
|
4237
4456
|
data: {
|
|
4238
4457
|
title: "Preview Error",
|
|
4239
4458
|
...!!getEnv("DEV") && { subtitle: "Check the console for more details" }
|
|
@@ -4297,104 +4516,92 @@ function processPreviewQuery({
|
|
|
4297
4516
|
);
|
|
4298
4517
|
}
|
|
4299
4518
|
function createPreviewQuery(documentIds) {
|
|
4300
|
-
const allIds = Array.from(documentIds).flatMap((id) => [getPublishedId(id), getDraftId(id)]),
|
|
4519
|
+
const allIds = Array.from(documentIds).flatMap((id) => [getPublishedId(id), getDraftId(id)]), queryHash = hashString(PREVIEW_PROJECTION);
|
|
4301
4520
|
return {
|
|
4302
|
-
query: `*[_id in $__ids_${queryHash}]${
|
|
4521
|
+
query: `*[_id in $__ids_${queryHash}]${PREVIEW_PROJECTION}`,
|
|
4303
4522
|
params: {
|
|
4304
4523
|
[`__ids_${queryHash}`]: allIds
|
|
4305
4524
|
}
|
|
4306
4525
|
};
|
|
4307
4526
|
}
|
|
4308
|
-
const BATCH_DEBOUNCE_TIME$1 = 50, subscribeToStateAndFetchBatches$1 =
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
)
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
return client.observable.fetch(query, params, {
|
|
4342
|
-
filterResponse: !1,
|
|
4343
|
-
returnQuery: !1,
|
|
4344
|
-
perspective: "drafts",
|
|
4527
|
+
const BATCH_DEBOUNCE_TIME$1 = 50, isSetEqual$1 = (a2, b2) => a2.size === b2.size && Array.from(a2).every((i2) => b2.has(i2)), subscribeToStateAndFetchBatches$1 = ({
|
|
4528
|
+
state,
|
|
4529
|
+
instance
|
|
4530
|
+
}) => state.observable.pipe(
|
|
4531
|
+
map(({ subscriptions }) => new Set(Object.keys(subscriptions))),
|
|
4532
|
+
distinctUntilChanged(isSetEqual$1),
|
|
4533
|
+
debounceTime(BATCH_DEBOUNCE_TIME$1),
|
|
4534
|
+
startWith$1(/* @__PURE__ */ new Set()),
|
|
4535
|
+
pairwise$1(),
|
|
4536
|
+
tap$1(([prevIds, currIds]) => {
|
|
4537
|
+
const newIds = [...currIds].filter((element) => !prevIds.has(element));
|
|
4538
|
+
state.set("updatingPending", (prev) => {
|
|
4539
|
+
const pendingValues = newIds.reduce((acc, id) => {
|
|
4540
|
+
const prevValue = prev.values[id], value = prevValue?.data ? prevValue.data : null;
|
|
4541
|
+
return acc[id] = { data: value, isPending: !0 }, acc;
|
|
4542
|
+
}, {});
|
|
4543
|
+
return { values: { ...prev.values, ...pendingValues } };
|
|
4544
|
+
});
|
|
4545
|
+
}),
|
|
4546
|
+
map(([, ids]) => ids),
|
|
4547
|
+
distinctUntilChanged(isSetEqual$1)
|
|
4548
|
+
).pipe(
|
|
4549
|
+
switchMap((ids) => {
|
|
4550
|
+
if (!ids.size) return EMPTY;
|
|
4551
|
+
const { query, params } = createPreviewQuery(ids), controller = new AbortController();
|
|
4552
|
+
return new Observable((observer) => {
|
|
4553
|
+
const { getCurrent, observable } = getQueryState(instance, query, {
|
|
4554
|
+
params,
|
|
4555
|
+
tag: PREVIEW_TAG,
|
|
4556
|
+
perspective: PREVIEW_PERSPECTIVE
|
|
4557
|
+
}), subscription = defer(() => getCurrent() === void 0 ? from(
|
|
4558
|
+
resolveQuery(instance, query, {
|
|
4559
|
+
params,
|
|
4345
4560
|
tag: PREVIEW_TAG,
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
}),
|
|
4349
|
-
map(({ ids, result, syncTags }) => ({
|
|
4350
|
-
syncTags,
|
|
4351
|
-
values: processPreviewQuery({
|
|
4352
|
-
projectId: instance.identity.projectId,
|
|
4353
|
-
dataset: instance.identity.dataset,
|
|
4354
|
-
ids,
|
|
4355
|
-
results: result
|
|
4561
|
+
perspective: PREVIEW_PERSPECTIVE,
|
|
4562
|
+
signal: controller.signal
|
|
4356
4563
|
})
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4564
|
+
).pipe(switchMap(() => observable)) : observable).pipe(filter((result) => result !== void 0)).subscribe(observer);
|
|
4565
|
+
return () => {
|
|
4566
|
+
controller.signal.aborted || controller.abort(), subscription.unsubscribe();
|
|
4567
|
+
};
|
|
4568
|
+
}).pipe(map((data) => ({ data, ids })));
|
|
4569
|
+
}),
|
|
4570
|
+
map(({ ids, data }) => ({
|
|
4571
|
+
values: processPreviewQuery({
|
|
4572
|
+
projectId: instance.config.projectId,
|
|
4573
|
+
dataset: instance.config.dataset,
|
|
4574
|
+
ids,
|
|
4575
|
+
results: data
|
|
4576
|
+
})
|
|
4577
|
+
}))
|
|
4578
|
+
).subscribe({
|
|
4579
|
+
next: ({ values }) => {
|
|
4580
|
+
state.set("updateResult", (prev) => ({ values: { ...prev.values, ...values } }));
|
|
4366
4581
|
}
|
|
4367
|
-
), previewStore = {
|
|
4582
|
+
}), previewStore = {
|
|
4368
4583
|
name: "Preview",
|
|
4369
4584
|
getInitialState() {
|
|
4370
4585
|
return {
|
|
4371
|
-
documentTypes: {},
|
|
4372
|
-
lastLiveEventId: null,
|
|
4373
4586
|
subscriptions: {},
|
|
4374
|
-
syncTags: {},
|
|
4375
4587
|
values: {}
|
|
4376
4588
|
};
|
|
4377
4589
|
},
|
|
4378
|
-
initialize() {
|
|
4379
|
-
const
|
|
4380
|
-
return () =>
|
|
4381
|
-
stateSubscriptionForBatches.unsubscribe(), liveSubscription.unsubscribe();
|
|
4382
|
-
};
|
|
4590
|
+
initialize: (context) => {
|
|
4591
|
+
const subscription = subscribeToStateAndFetchBatches$1(context);
|
|
4592
|
+
return () => subscription.unsubscribe;
|
|
4383
4593
|
}
|
|
4384
|
-
}
|
|
4594
|
+
};
|
|
4595
|
+
function getPreviewState(...args) {
|
|
4596
|
+
return _getPreviewState(...args);
|
|
4597
|
+
}
|
|
4598
|
+
const _getPreviewState = bindActionByDataset(
|
|
4385
4599
|
previewStore,
|
|
4386
|
-
(
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
subscribe: (subscriber) => {
|
|
4392
|
-
const subscriptionId = insecureRandomId();
|
|
4393
|
-
state.set("addSubscription", (prev) => ({
|
|
4394
|
-
documentTypes: {
|
|
4395
|
-
...prev.documentTypes,
|
|
4396
|
-
[documentId]: documentType
|
|
4397
|
-
},
|
|
4600
|
+
createStateSourceAction({
|
|
4601
|
+
selector: ({ state }, docHandle) => state.values[docHandle.documentId] ?? STABLE_EMPTY_PREVIEW,
|
|
4602
|
+
onSubscribe: ({ state }, docHandle) => {
|
|
4603
|
+
const subscriptionId = insecureRandomId(), documentId = getPublishedId(docHandle.documentId);
|
|
4604
|
+
return state.set("addSubscription", (prev) => ({
|
|
4398
4605
|
subscriptions: {
|
|
4399
4606
|
...prev.subscriptions,
|
|
4400
4607
|
[documentId]: {
|
|
@@ -4402,10 +4609,8 @@ const BATCH_DEBOUNCE_TIME$1 = 50, subscribeToStateAndFetchBatches$1 = createInte
|
|
|
4402
4609
|
[subscriptionId]: !0
|
|
4403
4610
|
}
|
|
4404
4611
|
}
|
|
4405
|
-
}))
|
|
4406
|
-
|
|
4407
|
-
return () => {
|
|
4408
|
-
unsubscribe(), state.set("removeSubscription", (prev) => {
|
|
4612
|
+
})), () => {
|
|
4613
|
+
state.set("removeSubscription", (prev) => {
|
|
4409
4614
|
const documentSubscriptions = omit(prev.subscriptions[documentId], subscriptionId), hasSubscribers = !!Object.keys(documentSubscriptions).length, prevValue = prev.values[documentId], previewValue = prevValue?.data ? prevValue.data : null;
|
|
4410
4615
|
return {
|
|
4411
4616
|
subscriptions: hasSubscribers ? { ...prev.subscriptions, [documentId]: documentSubscriptions } : omit(prev.subscriptions, documentId),
|
|
@@ -4414,40 +4619,46 @@ const BATCH_DEBOUNCE_TIME$1 = 50, subscribeToStateAndFetchBatches$1 = createInte
|
|
|
4414
4619
|
});
|
|
4415
4620
|
};
|
|
4416
4621
|
}
|
|
4417
|
-
}
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
const current = getCurrent();
|
|
4423
|
-
current?.data && (resolve(current), unsubscribe());
|
|
4424
|
-
});
|
|
4425
|
-
});
|
|
4426
|
-
}), project = createFetcherStore({
|
|
4622
|
+
})
|
|
4623
|
+
), resolvePreview = bindActionByDataset(
|
|
4624
|
+
previewStore,
|
|
4625
|
+
({ instance }, docHandle) => firstValueFrom(getPreviewState(instance, docHandle).observable.pipe(filter((i2) => !!i2.data)))
|
|
4626
|
+
), API_VERSION$2 = "v2025-02-19", project = createFetcherStore({
|
|
4427
4627
|
name: "Project",
|
|
4428
|
-
getKey: (
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4628
|
+
getKey: (instance, options) => {
|
|
4629
|
+
const projectId = options?.projectId ?? instance.config.projectId;
|
|
4630
|
+
if (!projectId)
|
|
4631
|
+
throw new Error("A projectId is required to use the project API.");
|
|
4632
|
+
return projectId;
|
|
4633
|
+
},
|
|
4634
|
+
fetcher: (instance) => (options = {}) => {
|
|
4635
|
+
const projectId = options.projectId ?? instance.config.projectId;
|
|
4636
|
+
return getClientState(instance, {
|
|
4637
|
+
apiVersion: API_VERSION$2,
|
|
4638
|
+
scope: "global",
|
|
4639
|
+
projectId
|
|
4640
|
+
}).observable.pipe(
|
|
4641
|
+
switchMap(
|
|
4642
|
+
(client) => client.observable.projects.getById(
|
|
4643
|
+
// non-null assertion is fine with the above throwing
|
|
4644
|
+
projectId ?? instance.config.projectId
|
|
4645
|
+
)
|
|
4646
|
+
)
|
|
4440
4647
|
);
|
|
4441
|
-
|
|
4442
|
-
}
|
|
4648
|
+
}
|
|
4649
|
+
}), getProjectState = project.getState, resolveProject = project.resolveState;
|
|
4443
4650
|
function createProjectionQuery(documentIds, documentProjections) {
|
|
4444
|
-
const projections = Array.from(documentIds).
|
|
4445
|
-
const
|
|
4446
|
-
return
|
|
4651
|
+
const projections = Array.from(documentIds).flatMap((id) => {
|
|
4652
|
+
const projectionsForDoc = documentProjections[id];
|
|
4653
|
+
return projectionsForDoc ? Object.entries(projectionsForDoc).map(([projectionHash, projection]) => ({
|
|
4654
|
+
documentId: id,
|
|
4655
|
+
projection,
|
|
4656
|
+
projectionHash
|
|
4657
|
+
})) : [];
|
|
4447
4658
|
}).reduce((acc, { documentId, projection, projectionHash }) => {
|
|
4448
4659
|
const obj = acc[projectionHash] ?? { documentIds: /* @__PURE__ */ new Set(), projection };
|
|
4449
4660
|
return obj.documentIds.add(documentId), acc[projectionHash] = obj, acc;
|
|
4450
|
-
}, {}), query = `[${Object.entries(projections).map(([projectionHash, { projection }]) => `...*[_id in $__ids_${projectionHash}]{_id,_type,_updatedAt,"result":{...${projection}}}`).join(",")}]`, params = Object.fromEntries(
|
|
4661
|
+
}, {}), query = `[${Object.entries(projections).map(([projectionHash, { projection }]) => `...*[_id in $__ids_${projectionHash}]{_id,_type,_updatedAt,"__projectionHash":"${projectionHash}","result":{...${projection}}}`).join(",")}]`, params = Object.fromEntries(
|
|
4451
4662
|
Object.entries(projections).map(([projectionHash, value]) => {
|
|
4452
4663
|
const idsInProjection = Array.from(value.documentIds).flatMap((id) => [
|
|
4453
4664
|
getPublishedId(id),
|
|
@@ -4459,408 +4670,397 @@ function createProjectionQuery(documentIds, documentProjections) {
|
|
|
4459
4670
|
return { query, params };
|
|
4460
4671
|
}
|
|
4461
4672
|
function processProjectionQuery({ ids, results }) {
|
|
4462
|
-
const
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4673
|
+
const groupedResults = {};
|
|
4674
|
+
for (const result of results) {
|
|
4675
|
+
const originalId = getPublishedId(result._id), hash = result.__projectionHash, isDraft = result._id.startsWith("drafts.");
|
|
4676
|
+
ids.has(originalId) && (groupedResults[originalId] || (groupedResults[originalId] = {}), groupedResults[originalId][hash] || (groupedResults[originalId][hash] = {}), isDraft ? groupedResults[originalId][hash].draft = result : groupedResults[originalId][hash].published = result);
|
|
4677
|
+
}
|
|
4678
|
+
const finalValues = {};
|
|
4679
|
+
for (const originalId of ids) {
|
|
4680
|
+
finalValues[originalId] = {};
|
|
4681
|
+
const projectionsForDoc = groupedResults[originalId];
|
|
4682
|
+
if (projectionsForDoc)
|
|
4683
|
+
for (const hash in projectionsForDoc) {
|
|
4684
|
+
const { draft, published } = projectionsForDoc[hash], projectionResultData = draft?.result ?? published?.result;
|
|
4685
|
+
if (!projectionResultData) {
|
|
4686
|
+
finalValues[originalId][hash] = { data: null, isPending: !1 };
|
|
4687
|
+
continue;
|
|
4688
|
+
}
|
|
4689
|
+
const status = {
|
|
4690
|
+
...draft?._updatedAt && { lastEditedDraftAt: draft._updatedAt },
|
|
4691
|
+
...published?._updatedAt && { lastEditedPublishedAt: published._updatedAt }
|
|
4692
|
+
};
|
|
4693
|
+
finalValues[originalId][hash] = {
|
|
4694
|
+
data: { ...projectionResultData, status },
|
|
4695
|
+
isPending: !1
|
|
4696
|
+
};
|
|
4697
|
+
}
|
|
4698
|
+
}
|
|
4699
|
+
return finalValues;
|
|
4477
4700
|
}
|
|
4478
|
-
const
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
map((i2) => i2.lastLiveEventId),
|
|
4487
|
-
distinctUntilChanged()
|
|
4488
|
-
), newSubscriberIds$ = state.observable.pipe(
|
|
4489
|
-
map(({ subscriptions }) => new Set(Object.keys(subscriptions))),
|
|
4490
|
-
distinctUntilChanged(
|
|
4491
|
-
(a2, b2) => a2.size !== b2.size ? !1 : Array.from(a2).every((i2) => b2.has(i2))
|
|
4492
|
-
),
|
|
4493
|
-
debounceTime(BATCH_DEBOUNCE_TIME),
|
|
4494
|
-
startWith$1(/* @__PURE__ */ new Set()),
|
|
4495
|
-
pairwise$1(),
|
|
4496
|
-
tap$1(([prevIds, currIds]) => {
|
|
4497
|
-
const newIds = [...currIds].filter((element) => !prevIds.has(element));
|
|
4498
|
-
state.set("updatingPending", (prev) => {
|
|
4499
|
-
const pendingValues = newIds.reduce((acc, id) => {
|
|
4500
|
-
const prevValue = prev.values[id], value = prevValue?.data ? prevValue.data : null;
|
|
4501
|
-
return acc[id] = { data: value, isPending: !0 }, acc;
|
|
4502
|
-
}, {});
|
|
4503
|
-
return { values: { ...prev.values, ...pendingValues } };
|
|
4504
|
-
});
|
|
4505
|
-
}),
|
|
4506
|
-
withLatestFrom(documentProjections$),
|
|
4507
|
-
map(([[, ids], documentProjections]) => ({ ids, documentProjections }))
|
|
4701
|
+
const PROJECTION_TAG = "sdk.projection", PROJECTION_PERSPECTIVE = "drafts", PROJECTION_STATE_CLEAR_DELAY = 1e3, STABLE_EMPTY_PROJECTION = {
|
|
4702
|
+
data: null,
|
|
4703
|
+
isPending: !1
|
|
4704
|
+
};
|
|
4705
|
+
function validateProjection(projection) {
|
|
4706
|
+
if (!projection.startsWith("{") || !projection.endsWith("}"))
|
|
4707
|
+
throw new Error(
|
|
4708
|
+
`Invalid projection format: "${projection}". Projections must be enclosed in curly braces, e.g. "{title, 'author': author.name}"`
|
|
4508
4709
|
);
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4710
|
+
return projection;
|
|
4711
|
+
}
|
|
4712
|
+
const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a2, b2) => a2.size === b2.size && Array.from(a2).every((i2) => b2.has(i2)), subscribeToStateAndFetchBatches = ({
|
|
4713
|
+
state,
|
|
4714
|
+
instance
|
|
4715
|
+
}) => {
|
|
4716
|
+
const documentProjections$ = state.observable.pipe(
|
|
4717
|
+
map((s2) => s2.documentProjections),
|
|
4718
|
+
distinctUntilChanged(isEqual)
|
|
4719
|
+
), activeDocumentIds$ = state.observable.pipe(
|
|
4720
|
+
map(({ subscriptions }) => new Set(Object.keys(subscriptions))),
|
|
4721
|
+
distinctUntilChanged(isSetEqual)
|
|
4722
|
+
), pendingUpdateSubscription = activeDocumentIds$.pipe(
|
|
4723
|
+
debounceTime(BATCH_DEBOUNCE_TIME),
|
|
4724
|
+
startWith$1(/* @__PURE__ */ new Set()),
|
|
4725
|
+
pairwise$1(),
|
|
4726
|
+
tap$1(([prevIds, currIds]) => {
|
|
4727
|
+
const newIds = [...currIds].filter((id) => !prevIds.has(id));
|
|
4728
|
+
newIds.length !== 0 && state.set("updatingPending", (prev) => {
|
|
4729
|
+
const nextValues = { ...prev.values };
|
|
4730
|
+
for (const id of newIds) {
|
|
4731
|
+
const projectionsForDoc = prev.documentProjections[id];
|
|
4732
|
+
if (!projectionsForDoc) continue;
|
|
4733
|
+
const updatedValuesForDoc = { ...prev.values[id] ?? {} };
|
|
4734
|
+
for (const hash in projectionsForDoc) {
|
|
4735
|
+
const currentValue = updatedValuesForDoc[hash];
|
|
4736
|
+
updatedValuesForDoc[hash] = {
|
|
4737
|
+
data: currentValue?.data ?? null,
|
|
4738
|
+
isPending: !0
|
|
4739
|
+
};
|
|
4740
|
+
}
|
|
4741
|
+
nextValues[id] = updatedValuesForDoc;
|
|
4742
|
+
}
|
|
4743
|
+
return { values: nextValues };
|
|
4744
|
+
});
|
|
4745
|
+
})
|
|
4746
|
+
).subscribe(), queryExecutionSubscription = combineLatest([activeDocumentIds$, documentProjections$]).pipe(
|
|
4747
|
+
debounceTime(BATCH_DEBOUNCE_TIME),
|
|
4748
|
+
distinctUntilChanged(isEqual)
|
|
4749
|
+
).pipe(
|
|
4750
|
+
switchMap(([ids, documentProjections]) => {
|
|
4751
|
+
if (!ids.size) return EMPTY;
|
|
4752
|
+
const { query, params } = createProjectionQuery(ids, documentProjections), controller = new AbortController();
|
|
4753
|
+
return new Observable((observer) => {
|
|
4754
|
+
const { getCurrent, observable } = getQueryState(instance, query, {
|
|
4755
|
+
params,
|
|
4517
4756
|
tag: PROJECTION_TAG,
|
|
4518
|
-
|
|
4519
|
-
})
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
)
|
|
4757
|
+
perspective: PROJECTION_PERSPECTIVE
|
|
4758
|
+
}), subscription = defer(() => getCurrent() === void 0 ? from(
|
|
4759
|
+
resolveQuery(instance, query, {
|
|
4760
|
+
params,
|
|
4761
|
+
tag: PROJECTION_TAG,
|
|
4762
|
+
perspective: PROJECTION_PERSPECTIVE,
|
|
4763
|
+
signal: controller.signal
|
|
4764
|
+
})
|
|
4765
|
+
).pipe(switchMap(() => observable)) : observable).pipe(filter((result) => result !== void 0)).subscribe(observer);
|
|
4766
|
+
return () => {
|
|
4767
|
+
controller.signal.aborted || controller.abort(), subscription.unsubscribe();
|
|
4768
|
+
};
|
|
4769
|
+
}).pipe(map((data) => ({ data, ids })));
|
|
4770
|
+
}),
|
|
4771
|
+
map(
|
|
4772
|
+
({ ids, data }) => processProjectionQuery({
|
|
4773
|
+
ids,
|
|
4774
|
+
results: data
|
|
4775
|
+
})
|
|
4776
|
+
)
|
|
4777
|
+
).subscribe({
|
|
4778
|
+
next: (processedValues) => {
|
|
4779
|
+
state.set("updateResult", (prev) => {
|
|
4780
|
+
const nextValues = { ...prev.values };
|
|
4781
|
+
for (const docId in processedValues)
|
|
4782
|
+
processedValues[docId] && (nextValues[docId] = {
|
|
4783
|
+
...prev.values[docId] ?? {},
|
|
4784
|
+
...processedValues[docId]
|
|
4785
|
+
});
|
|
4786
|
+
return { values: nextValues };
|
|
4787
|
+
});
|
|
4788
|
+
},
|
|
4789
|
+
error: (err) => {
|
|
4790
|
+
console.error("Error fetching projection batches:", err);
|
|
4791
|
+
}
|
|
4792
|
+
});
|
|
4793
|
+
return new Subscription(() => {
|
|
4794
|
+
pendingUpdateSubscription.unsubscribe(), queryExecutionSubscription.unsubscribe();
|
|
4795
|
+
});
|
|
4796
|
+
}, projectionStore = {
|
|
4538
4797
|
name: "Projection",
|
|
4539
4798
|
getInitialState() {
|
|
4540
4799
|
return {
|
|
4541
4800
|
values: {},
|
|
4542
4801
|
documentProjections: {},
|
|
4543
|
-
subscriptions: {}
|
|
4544
|
-
syncTags: {},
|
|
4545
|
-
lastLiveEventId: null
|
|
4802
|
+
subscriptions: {}
|
|
4546
4803
|
};
|
|
4547
4804
|
},
|
|
4548
|
-
initialize() {
|
|
4549
|
-
const
|
|
4550
|
-
return () =>
|
|
4551
|
-
liveSubscription.unsubscribe(), batchSubscription.unsubscribe();
|
|
4552
|
-
};
|
|
4805
|
+
initialize(context) {
|
|
4806
|
+
const batchSubscription = subscribeToStateAndFetchBatches(context);
|
|
4807
|
+
return () => batchSubscription.unsubscribe();
|
|
4553
4808
|
}
|
|
4554
|
-
}
|
|
4555
|
-
projectionStore,
|
|
4556
|
-
(state, { document }) => state.values[document._id] ?? STABLE_EMPTY_PROJECTION
|
|
4557
|
-
);
|
|
4809
|
+
};
|
|
4558
4810
|
function getProjectionState(...args) {
|
|
4559
4811
|
return _getProjectionState(...args);
|
|
4560
4812
|
}
|
|
4561
|
-
const _getProjectionState =
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
}) {
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
const subscriptionId = insecureRandomId();
|
|
4570
|
-
state.set("addSubscription", (prev) => ({
|
|
4813
|
+
const _getProjectionState = bindActionByDataset(
|
|
4814
|
+
projectionStore,
|
|
4815
|
+
createStateSourceAction({
|
|
4816
|
+
selector: ({ state }, options) => {
|
|
4817
|
+
const documentId = getPublishedId(options.documentId), projectionHash = hashString(options.projection);
|
|
4818
|
+
return state.values[documentId]?.[projectionHash] ?? STABLE_EMPTY_PROJECTION;
|
|
4819
|
+
},
|
|
4820
|
+
onSubscribe: ({ state }, { projection, ...docHandle }) => {
|
|
4821
|
+
const subscriptionId = insecureRandomId(), documentId = getPublishedId(docHandle.documentId), validProjection = validateProjection(projection), projectionHash = hashString(validProjection);
|
|
4822
|
+
return state.set("addSubscription", (prev) => ({
|
|
4571
4823
|
documentProjections: {
|
|
4572
4824
|
...prev.documentProjections,
|
|
4573
|
-
[documentId]:
|
|
4825
|
+
[documentId]: {
|
|
4826
|
+
...prev.documentProjections[documentId],
|
|
4827
|
+
[projectionHash]: validProjection
|
|
4828
|
+
}
|
|
4574
4829
|
},
|
|
4575
4830
|
subscriptions: {
|
|
4576
4831
|
...prev.subscriptions,
|
|
4577
4832
|
[documentId]: {
|
|
4578
4833
|
...prev.subscriptions[documentId],
|
|
4579
|
-
[
|
|
4834
|
+
[projectionHash]: {
|
|
4835
|
+
...prev.subscriptions[documentId]?.[projectionHash],
|
|
4836
|
+
[subscriptionId]: !0
|
|
4837
|
+
}
|
|
4580
4838
|
}
|
|
4581
4839
|
}
|
|
4582
|
-
}))
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4840
|
+
})), () => {
|
|
4841
|
+
setTimeout(() => {
|
|
4842
|
+
state.set("removeSubscription", (prev) => {
|
|
4843
|
+
const documentSubscriptionsForHash = omit(
|
|
4844
|
+
prev.subscriptions[documentId]?.[projectionHash],
|
|
4845
|
+
subscriptionId
|
|
4846
|
+
), hasSubscribersForProjection = !!Object.keys(documentSubscriptionsForHash).length, nextSubscriptions = { ...prev.subscriptions }, nextDocumentProjections = { ...prev.documentProjections }, nextValues = { ...prev.values };
|
|
4847
|
+
if (hasSubscribersForProjection)
|
|
4848
|
+
nextSubscriptions[documentId] && (nextSubscriptions[documentId][projectionHash] = documentSubscriptionsForHash);
|
|
4849
|
+
else {
|
|
4850
|
+
delete nextSubscriptions[documentId][projectionHash], delete nextDocumentProjections[documentId][projectionHash];
|
|
4851
|
+
const currentProjectionValue = prev.values[documentId]?.[projectionHash];
|
|
4852
|
+
currentProjectionValue && nextValues[documentId] && (nextValues[documentId][projectionHash] = {
|
|
4853
|
+
data: currentProjectionValue.data,
|
|
4854
|
+
isPending: !1
|
|
4855
|
+
});
|
|
4856
|
+
}
|
|
4857
|
+
return Object.values(
|
|
4858
|
+
nextSubscriptions[documentId] ?? {}
|
|
4859
|
+
).some((subs) => Object.keys(subs).length > 0) || (delete nextSubscriptions[documentId], delete nextDocumentProjections[documentId]), {
|
|
4860
|
+
subscriptions: nextSubscriptions,
|
|
4861
|
+
documentProjections: nextDocumentProjections,
|
|
4862
|
+
values: nextValues
|
|
4863
|
+
};
|
|
4864
|
+
});
|
|
4865
|
+
}, PROJECTION_STATE_CLEAR_DELAY);
|
|
4592
4866
|
};
|
|
4593
4867
|
}
|
|
4594
|
-
}
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
}), projects = createFetcherStore({
|
|
4868
|
+
})
|
|
4869
|
+
), resolveProjection = bindActionByDataset(
|
|
4870
|
+
projectionStore,
|
|
4871
|
+
({ instance }, { projection, ...docHandle }) => firstValueFrom(
|
|
4872
|
+
getProjectionState(instance, { ...docHandle, projection }).observable.pipe(
|
|
4873
|
+
filter((i2) => !!i2.data)
|
|
4874
|
+
)
|
|
4875
|
+
)
|
|
4876
|
+
), API_VERSION$1 = "v2025-02-19", projects = createFetcherStore({
|
|
4604
4877
|
name: "Projects",
|
|
4605
4878
|
getKey: () => "projects",
|
|
4606
|
-
fetcher: (instance) => () => getClientState(instance, {
|
|
4879
|
+
fetcher: (instance) => () => getClientState(instance, {
|
|
4880
|
+
apiVersion: API_VERSION$1,
|
|
4881
|
+
scope: "global"
|
|
4882
|
+
}).observable.pipe(
|
|
4607
4883
|
switchMap((client) => client.observable.projects.list({ includeMembers: !1 }))
|
|
4608
4884
|
)
|
|
4609
|
-
}), getProjectsState = projects.getState, resolveProjects = projects.resolveState,
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
const
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
subscription.unsubscribe();
|
|
4643
|
-
};
|
|
4644
|
-
}
|
|
4645
|
-
}, errorHandler = createInternalAction(({ state }) => function() {
|
|
4646
|
-
return (error) => state.set("setError", { error });
|
|
4647
|
-
}), listenForNewSubscribersAndFetch = createInternalAction(
|
|
4648
|
-
({ state, instance }) => function() {
|
|
4649
|
-
return state.observable.pipe(
|
|
4650
|
-
map((s2) => new Set(Object.keys(s2.queries))),
|
|
4651
|
-
distinctUntilChanged((curr, next) => curr.size !== next.size ? !1 : Array.from(next).every((i2) => curr.has(i2))),
|
|
4652
|
-
startWith$1(/* @__PURE__ */ new Set()),
|
|
4653
|
-
pairwise$1(),
|
|
4654
|
-
mergeMap$1(([curr, next]) => {
|
|
4655
|
-
const added = Array.from(next).filter((i2) => !curr.has(i2)), removed = Array.from(curr).filter((i2) => !next.has(i2));
|
|
4656
|
-
return [
|
|
4657
|
-
...added.map((key) => ({ key, added: !0 })),
|
|
4658
|
-
...removed.map((key) => ({ key, added: !1 }))
|
|
4659
|
-
];
|
|
4660
|
-
}),
|
|
4661
|
-
groupBy$1((i2) => i2.key),
|
|
4662
|
-
mergeMap$1(
|
|
4663
|
-
(group$) => group$.pipe(
|
|
4664
|
-
switchMap((e3) => {
|
|
4665
|
-
if (!e3.added) return EMPTY;
|
|
4666
|
-
const lastLiveEventId$ = state.observable.pipe(
|
|
4667
|
-
map((s2) => s2.queries[group$.key]?.lastLiveEventId),
|
|
4668
|
-
distinctUntilChanged()
|
|
4669
|
-
), { query, options: { params, scope, ...options } = {} } = parseQueryKey(group$.key), client$ = getClientState(instance, { apiVersion: "vX", scope }).observable;
|
|
4670
|
-
return combineLatest([lastLiveEventId$, client$]).pipe(
|
|
4671
|
-
switchMap(
|
|
4672
|
-
([lastLiveEventId, client]) => client.observable.fetch(query, params, {
|
|
4673
|
-
...options,
|
|
4674
|
-
filterResponse: !1,
|
|
4675
|
-
returnQuery: !1,
|
|
4676
|
-
lastLiveEventId
|
|
4677
|
-
})
|
|
4678
|
-
)
|
|
4679
|
-
);
|
|
4680
|
-
}),
|
|
4681
|
-
catchError$1((error) => (state.set("setQueryError", setQueryError(group$.key, error)), EMPTY)),
|
|
4682
|
-
tap$1(({ result, syncTags }) => {
|
|
4683
|
-
state.set("setQueryData", setQueryData(group$.key, result, syncTags));
|
|
4684
|
-
})
|
|
4685
|
-
)
|
|
4686
|
-
)
|
|
4687
|
-
).subscribe({ error: errorHandler(this) });
|
|
4885
|
+
}), getProjectsState = projects.getState, resolveProjects = projects.resolveState, API_VERSION = "vX", USERS_STATE_CLEAR_DELAY = 5e3, DEFAULT_USERS_BATCH_SIZE = 100, getUsersKey = (instance, {
|
|
4886
|
+
resourceType,
|
|
4887
|
+
organizationId,
|
|
4888
|
+
batchSize = DEFAULT_USERS_BATCH_SIZE,
|
|
4889
|
+
projectId = instance.config.projectId
|
|
4890
|
+
} = {}) => JSON.stringify({ resourceType, organizationId, batchSize, projectId }), parseUsersKey = (key) => JSON.parse(key), addSubscription = (subscriptionId, key) => (prev) => {
|
|
4891
|
+
const group = prev.users[key], subscriptions = [...group?.subscriptions ?? [], subscriptionId];
|
|
4892
|
+
return { ...prev, users: { ...prev.users, [key]: { ...group, subscriptions } } };
|
|
4893
|
+
}, removeSubscription = (subscriptionId, key) => (prev) => {
|
|
4894
|
+
const group = prev.users[key];
|
|
4895
|
+
if (!group) return prev;
|
|
4896
|
+
const subscriptions = group.subscriptions.filter((id) => id !== subscriptionId);
|
|
4897
|
+
return subscriptions.length ? { ...prev, users: { ...prev.users, [key]: { ...group, subscriptions } } } : { ...prev, users: omit(prev.users, key) };
|
|
4898
|
+
}, setUsersData = (key, { data, nextCursor, totalCount }) => (prev) => {
|
|
4899
|
+
const group = prev.users[key];
|
|
4900
|
+
if (!group) return prev;
|
|
4901
|
+
const users = [...group.users ?? [], ...data];
|
|
4902
|
+
return { ...prev, users: { ...prev.users, [key]: { ...group, users, totalCount, nextCursor } } };
|
|
4903
|
+
}, updateLastLoadMoreRequest = (timestamp, key) => (prev) => {
|
|
4904
|
+
const group = prev.users[key];
|
|
4905
|
+
return group ? { ...prev, users: { ...prev.users, [key]: { ...group, lastLoadMoreRequest: timestamp } } } : prev;
|
|
4906
|
+
}, setUsersError = (key, error) => (prev) => {
|
|
4907
|
+
const group = prev.users[key];
|
|
4908
|
+
return group ? { ...prev, users: { ...prev.users, [key]: { ...group, error } } } : prev;
|
|
4909
|
+
}, cancelRequest = (key) => (prev) => {
|
|
4910
|
+
const group = prev.users[key];
|
|
4911
|
+
return !group || group.subscriptions.length ? prev : { ...prev, users: omit(prev.users, key) };
|
|
4912
|
+
}, initializeRequest = (key) => (prev) => prev.users[key] ? prev : { ...prev, users: { ...prev.users, [key]: { subscriptions: [] } } }, usersStore = {
|
|
4913
|
+
name: "UsersStore",
|
|
4914
|
+
getInitialState: () => ({ users: {} }),
|
|
4915
|
+
initialize: (context) => {
|
|
4916
|
+
const subscription = listenForLoadMoreAndFetch(context);
|
|
4917
|
+
return () => subscription.unsubscribe();
|
|
4688
4918
|
}
|
|
4689
|
-
),
|
|
4690
|
-
(
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4919
|
+
}, errorHandler = (state) => (error) => state.set("setError", { error }), listenForLoadMoreAndFetch = ({ state, instance }) => state.observable.pipe(
|
|
4920
|
+
map((s2) => new Set(Object.keys(s2.users))),
|
|
4921
|
+
distinctUntilChanged((curr, next) => curr.size !== next.size ? !1 : Array.from(next).every((i2) => curr.has(i2))),
|
|
4922
|
+
startWith$1(/* @__PURE__ */ new Set()),
|
|
4923
|
+
pairwise$1(),
|
|
4924
|
+
mergeMap$1(([curr, next]) => {
|
|
4925
|
+
const added = Array.from(next).filter((i2) => !curr.has(i2)), removed = Array.from(curr).filter((i2) => !next.has(i2));
|
|
4926
|
+
return [
|
|
4927
|
+
...added.map((key) => ({ key, added: !0 })),
|
|
4928
|
+
...removed.map((key) => ({ key, added: !1 }))
|
|
4929
|
+
];
|
|
4930
|
+
}),
|
|
4931
|
+
groupBy$1((i2) => i2.key),
|
|
4932
|
+
mergeMap$1(
|
|
4933
|
+
(group$) => group$.pipe(
|
|
4934
|
+
switchMap((e3) => {
|
|
4935
|
+
if (!e3.added) return EMPTY;
|
|
4936
|
+
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(instance).observable.pipe(
|
|
4937
|
+
filter((i2) => typeof i2 == "string")
|
|
4938
|
+
), 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, {
|
|
4939
|
+
scope: "global",
|
|
4940
|
+
apiVersion: API_VERSION
|
|
4941
|
+
}).observable, loadMore$ = state.observable.pipe(
|
|
4942
|
+
map((s2) => s2.users[group$.key]?.lastLoadMoreRequest),
|
|
4705
4943
|
distinctUntilChanged()
|
|
4944
|
+
), cursor$ = state.observable.pipe(
|
|
4945
|
+
map((s2) => s2.users[group$.key]?.nextCursor),
|
|
4946
|
+
distinctUntilChanged(),
|
|
4947
|
+
filter((cursor) => cursor !== null)
|
|
4706
4948
|
);
|
|
4707
|
-
return combineLatest([
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4949
|
+
return combineLatest([resource$, client$, loadMore$]).pipe(
|
|
4950
|
+
withLatestFrom(cursor$),
|
|
4951
|
+
switchMap(
|
|
4952
|
+
([[resource, client], cursor]) => client.observable.request({
|
|
4953
|
+
method: "GET",
|
|
4954
|
+
uri: `access/${resource.type}/${resource.id}/users`,
|
|
4955
|
+
query: cursor ? { nextCursor: cursor, limit: batchSize.toString() } : { limit: batchSize.toString() }
|
|
4956
|
+
})
|
|
4957
|
+
),
|
|
4958
|
+
catchError$1((error) => (state.set("setUsersError", setUsersError(group$.key, error)), EMPTY)),
|
|
4959
|
+
tap$1((response) => state.set("setUsersData", setUsersData(group$.key, response)))
|
|
4712
4960
|
);
|
|
4713
4961
|
})
|
|
4714
|
-
)
|
|
4715
|
-
|
|
4716
|
-
)
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
);
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
}
|
|
4740
|
-
const _resolveQuery = createAction(queryStore, ({ state }) => function(query, { signal, ...options } = {}) {
|
|
4741
|
-
const { getCurrent } = getQueryState(this, query, options), key = getQueryKey(query, options), aborted$ = signal ? new Observable((observer) => {
|
|
4742
|
-
const cleanup = () => {
|
|
4743
|
-
signal.removeEventListener("abort", listener);
|
|
4744
|
-
}, listener = () => {
|
|
4745
|
-
observer.error(new DOMException("The operation was aborted.", "AbortError")), observer.complete(), cleanup();
|
|
4746
|
-
};
|
|
4747
|
-
return signal.addEventListener("abort", listener), cleanup;
|
|
4748
|
-
}).pipe(
|
|
4749
|
-
catchError$1((error) => {
|
|
4750
|
-
throw error instanceof Error && error.name === "AbortError" && state.set("cancelQuery", cancelQuery(key)), error;
|
|
4751
|
-
})
|
|
4752
|
-
) : NEVER;
|
|
4753
|
-
state.set("initializeQuery", initializeQuery(key));
|
|
4754
|
-
const resolved$ = state.observable.pipe(
|
|
4755
|
-
map(getCurrent),
|
|
4756
|
-
first$1((i2) => i2 !== void 0)
|
|
4757
|
-
);
|
|
4758
|
-
return firstValueFrom(race([resolved$, aborted$]));
|
|
4759
|
-
});
|
|
4760
|
-
function createStore(resource, actions) {
|
|
4761
|
-
return function(dependencies) {
|
|
4762
|
-
const instance = "instance" in dependencies ? dependencies.instance : dependencies, { state, dispose } = "state" in dependencies ? { state: dependencies.state, dispose: noop } : initializeResource(instance, resource), boundActions = Object.entries(actions).reduce((acc, [key, action]) => (acc[key] = action.bind(null, { state, instance }), acc), {});
|
|
4763
|
-
return { dispose, ...boundActions };
|
|
4764
|
-
};
|
|
4765
|
-
}
|
|
4766
|
-
const API_VERSION = "vX", usersStore = {
|
|
4767
|
-
name: "users",
|
|
4768
|
-
getInitialState: () => ({
|
|
4769
|
-
users: [],
|
|
4770
|
-
totalCount: 0,
|
|
4771
|
-
nextCursor: null,
|
|
4772
|
-
hasMore: !1,
|
|
4773
|
-
initialFetchCompleted: !1,
|
|
4774
|
-
options: {
|
|
4775
|
-
resourceType: "",
|
|
4776
|
-
resourceId: "",
|
|
4777
|
-
limit: 100
|
|
4962
|
+
)
|
|
4963
|
+
)
|
|
4964
|
+
).subscribe({ error: errorHandler(state) }), getUsersState = bindActionGlobally(
|
|
4965
|
+
usersStore,
|
|
4966
|
+
createStateSourceAction({
|
|
4967
|
+
selector: createSelector(
|
|
4968
|
+
[
|
|
4969
|
+
({ instance, state }, options) => state.error ?? state.users[getUsersKey(instance, options)]?.error,
|
|
4970
|
+
({ instance, state }, options) => state.users[getUsersKey(instance, options)]?.users,
|
|
4971
|
+
({ instance, state }, options) => state.users[getUsersKey(instance, options)]?.totalCount,
|
|
4972
|
+
({ instance, state }, options) => state.users[getUsersKey(instance, options)]?.nextCursor
|
|
4973
|
+
],
|
|
4974
|
+
(error, data, totalCount, nextCursor) => {
|
|
4975
|
+
if (error) throw error;
|
|
4976
|
+
if (!(data === void 0 || totalCount === void 0 || nextCursor === void 0))
|
|
4977
|
+
return { data, totalCount, hasMore: nextCursor !== null };
|
|
4978
|
+
}
|
|
4979
|
+
),
|
|
4980
|
+
onSubscribe: ({ instance, state }, options) => {
|
|
4981
|
+
const subscriptionId = insecureRandomId(), key = getUsersKey(instance, options);
|
|
4982
|
+
return state.set("addSubscription", addSubscription(subscriptionId, key)), () => {
|
|
4983
|
+
setTimeout(
|
|
4984
|
+
() => state.set("removeSubscription", removeSubscription(subscriptionId, key)),
|
|
4985
|
+
USERS_STATE_CLEAR_DELAY
|
|
4986
|
+
);
|
|
4987
|
+
};
|
|
4778
4988
|
}
|
|
4779
|
-
})
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4989
|
+
})
|
|
4990
|
+
), resolveUsers = bindActionGlobally(
|
|
4991
|
+
usersStore,
|
|
4992
|
+
async ({ state, instance }, { signal, ...options }) => {
|
|
4993
|
+
const key = getUsersKey(instance, options), { getCurrent } = getUsersState(instance, options), aborted$ = signal ? new Observable((observer) => {
|
|
4994
|
+
const cleanup = () => {
|
|
4995
|
+
signal.removeEventListener("abort", listener);
|
|
4996
|
+
}, listener = () => {
|
|
4997
|
+
observer.error(new DOMException("The operation was aborted.", "AbortError")), observer.complete(), cleanup();
|
|
4998
|
+
};
|
|
4999
|
+
return signal.addEventListener("abort", listener), cleanup;
|
|
5000
|
+
}).pipe(
|
|
5001
|
+
catchError$1((error) => {
|
|
5002
|
+
throw error instanceof Error && error.name === "AbortError" && state.set("cancelRequest", cancelRequest(key)), error;
|
|
5003
|
+
})
|
|
5004
|
+
) : NEVER;
|
|
5005
|
+
state.set("initializeRequest", initializeRequest(key));
|
|
5006
|
+
const resolved$ = state.observable.pipe(
|
|
5007
|
+
map(getCurrent),
|
|
5008
|
+
first$1((i2) => i2 !== void 0)
|
|
5009
|
+
);
|
|
5010
|
+
return firstValueFrom(race([resolved$, aborted$]));
|
|
4783
5011
|
}
|
|
4784
|
-
|
|
5012
|
+
), loadMoreUsers = bindActionGlobally(
|
|
4785
5013
|
usersStore,
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
(
|
|
4790
|
-
|
|
4791
|
-
(
|
|
4792
|
-
|
|
4793
|
-
(
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
const { options } = state.get(), { resourceType, resourceId, limit } = options;
|
|
4825
|
-
if (!resourceType || !resourceId)
|
|
4826
|
-
throw new Error("Resource type and ID are required to resolve users");
|
|
4827
|
-
const response = await fetchUsers(instance, { resourceType, resourceId, limit }), hasMore = response.data.length < response.totalCount;
|
|
4828
|
-
return state.set("resolveUsers", {
|
|
4829
|
-
users: response.data,
|
|
4830
|
-
totalCount: response.totalCount,
|
|
4831
|
-
nextCursor: response.nextCursor,
|
|
4832
|
-
hasMore,
|
|
4833
|
-
initialFetchCompleted: !0
|
|
4834
|
-
}), response;
|
|
4835
|
-
}), setOptions = createAction(usersStore, ({ state }) => function(options) {
|
|
4836
|
-
state.set("options", {
|
|
4837
|
-
...state.get(),
|
|
4838
|
-
options: {
|
|
4839
|
-
...state.get().options,
|
|
4840
|
-
resourceType: options.resourceType,
|
|
4841
|
-
resourceId: options.resourceId
|
|
4842
|
-
}
|
|
4843
|
-
});
|
|
4844
|
-
}), createUsersStore = createStore(usersStore, {
|
|
4845
|
-
getState,
|
|
4846
|
-
loadMore,
|
|
4847
|
-
resolveUsers,
|
|
4848
|
-
setOptions
|
|
4849
|
-
});
|
|
4850
|
-
var version = "0.0.0-chore-react-18-compat.1";
|
|
5014
|
+
async ({ state, instance }, options) => {
|
|
5015
|
+
const key = getUsersKey(instance, options), users = getUsersState(instance, options), usersState = users.getCurrent();
|
|
5016
|
+
if (!usersState)
|
|
5017
|
+
throw new Error("Users not loaded for specified resource. Please call resolveUsers first.");
|
|
5018
|
+
if (!usersState.hasMore)
|
|
5019
|
+
throw new Error("No more users available to load for this resource.");
|
|
5020
|
+
const promise = firstValueFrom(
|
|
5021
|
+
users.observable.pipe(
|
|
5022
|
+
filter((i2) => i2 !== void 0),
|
|
5023
|
+
skip(1)
|
|
5024
|
+
)
|
|
5025
|
+
), timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
5026
|
+
return state.set("updateLastLoadMoreRequest", updateLastLoadMoreRequest(timestamp, key)), await promise;
|
|
5027
|
+
}
|
|
5028
|
+
), WILDCARD_TOKEN = "*", NEGATION_TOKEN = "-", TOKEN_REGEX = /(?:[^\s"]+|"[^"]*")+/g;
|
|
5029
|
+
function isNegationToken(token) {
|
|
5030
|
+
return typeof token < "u" && token.trim().startsWith(NEGATION_TOKEN);
|
|
5031
|
+
}
|
|
5032
|
+
function isPrefixToken(token) {
|
|
5033
|
+
return typeof token < "u" && token.trim().endsWith(WILDCARD_TOKEN);
|
|
5034
|
+
}
|
|
5035
|
+
function isExactMatchToken(token) {
|
|
5036
|
+
return !!token && token.length >= 2 && token.startsWith('"') && token.endsWith('"');
|
|
5037
|
+
}
|
|
5038
|
+
function createGroqSearchFilter(query) {
|
|
5039
|
+
const trimmedQuery = query.trim();
|
|
5040
|
+
if (!trimmedQuery)
|
|
5041
|
+
return "";
|
|
5042
|
+
const tokens = trimmedQuery.match(TOKEN_REGEX) ?? [], reversedIndex = [...tokens].reverse().findIndex(
|
|
5043
|
+
(token) => !isNegationToken(token) && !isExactMatchToken(token)
|
|
5044
|
+
), finalIncrementalTokenIndex = reversedIndex === -1 ? -1 : tokens.length - 1 - reversedIndex, finalIncrementalToken = tokens[finalIncrementalTokenIndex], processedTokens = [...tokens];
|
|
5045
|
+
return finalIncrementalToken !== void 0 && !isPrefixToken(finalIncrementalToken) && processedTokens.splice(
|
|
5046
|
+
finalIncrementalTokenIndex,
|
|
5047
|
+
1,
|
|
5048
|
+
`${finalIncrementalToken}${WILDCARD_TOKEN}`
|
|
5049
|
+
), `[@] match text::query("${processedTokens.join(" ").replace(/"/g, '\\"')}")`;
|
|
5050
|
+
}
|
|
5051
|
+
var version = "0.0.0-chore-react-18-compat.3";
|
|
4851
5052
|
const CORE_SDK_VERSION = getEnv("PKG_VERSION") || `${version}-development`;
|
|
4852
5053
|
export {
|
|
4853
5054
|
AuthStateType,
|
|
4854
5055
|
CORE_SDK_VERSION,
|
|
4855
5056
|
applyDocumentActions,
|
|
4856
5057
|
createDocument,
|
|
5058
|
+
createGroqSearchFilter,
|
|
4857
5059
|
createSanityInstance,
|
|
4858
|
-
createUsersStore,
|
|
4859
5060
|
deleteDocument,
|
|
4860
5061
|
destroyController,
|
|
4861
5062
|
discardDocument,
|
|
4862
5063
|
editDocument,
|
|
4863
|
-
fetchLoginUrls,
|
|
4864
5064
|
getAuthState,
|
|
4865
5065
|
getClient,
|
|
4866
5066
|
getClientState,
|
|
@@ -4869,7 +5069,7 @@ export {
|
|
|
4869
5069
|
getDatasetsState,
|
|
4870
5070
|
getDocumentState,
|
|
4871
5071
|
getDocumentSyncStatus,
|
|
4872
|
-
|
|
5072
|
+
getLoginUrlState,
|
|
4873
5073
|
getOrCreateChannel,
|
|
4874
5074
|
getOrCreateController,
|
|
4875
5075
|
getOrCreateNode,
|
|
@@ -4880,12 +5080,15 @@ export {
|
|
|
4880
5080
|
getProjectsState,
|
|
4881
5081
|
getQueryKey,
|
|
4882
5082
|
getQueryState,
|
|
4883
|
-
getResourceId,
|
|
4884
5083
|
getTokenState,
|
|
5084
|
+
getUsersKey,
|
|
5085
|
+
getUsersState,
|
|
4885
5086
|
handleAuthCallback,
|
|
4886
5087
|
jsonMatch,
|
|
5088
|
+
loadMoreUsers,
|
|
4887
5089
|
logout,
|
|
4888
5090
|
parseQueryKey,
|
|
5091
|
+
parseUsersKey,
|
|
4889
5092
|
publishDocument,
|
|
4890
5093
|
releaseChannel,
|
|
4891
5094
|
releaseNode,
|
|
@@ -4897,6 +5100,7 @@ export {
|
|
|
4897
5100
|
resolveProjection,
|
|
4898
5101
|
resolveProjects,
|
|
4899
5102
|
resolveQuery,
|
|
5103
|
+
resolveUsers,
|
|
4900
5104
|
subscribeDocumentEvents,
|
|
4901
5105
|
unpublishDocument
|
|
4902
5106
|
};
|