1 | import { __assign, __rest } from "tslib";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | import { invariant } from "../../utilities/globals/index.js";
|
22 | import * as React from "rehackt";
|
23 | import { useSyncExternalStore } from "./useSyncExternalStore.js";
|
24 | import { equal } from "@wry/equality";
|
25 | import { mergeOptions } from "../../utilities/index.js";
|
26 | import { getApolloContext } from "../context/index.js";
|
27 | import { ApolloError } from "../../errors/index.js";
|
28 | import { NetworkStatus } from "../../core/index.js";
|
29 | import { DocumentType, verifyDocumentType } from "../parser/index.js";
|
30 | import { useApolloClient } from "./useApolloClient.js";
|
31 | import { compact, isNonEmptyArray, maybeDeepFreeze, } from "../../utilities/index.js";
|
32 | import { wrapHook } from "./internal/index.js";
|
33 | var hasOwnProperty = Object.prototype.hasOwnProperty;
|
34 | function noop() { }
|
35 | export var lastWatchOptions = Symbol();
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 | export function useQuery(query, options) {
|
71 | if (options === void 0) { options = Object.create(null); }
|
72 | return wrapHook("useQuery", _useQuery, useApolloClient(options && options.client))(query, options);
|
73 | }
|
74 | function _useQuery(query, options) {
|
75 | var _a = useQueryInternals(query, options), result = _a.result, obsQueryFields = _a.obsQueryFields;
|
76 | return React.useMemo(function () { return (__assign(__assign({}, result), obsQueryFields)); }, [result, obsQueryFields]);
|
77 | }
|
78 | function useInternalState(client, query, options, renderPromises, makeWatchQueryOptions) {
|
79 | function createInternalState(previous) {
|
80 | var _a;
|
81 | verifyDocumentType(query, DocumentType.Query);
|
82 | var internalState = {
|
83 | client: client,
|
84 | query: query,
|
85 | observable:
|
86 |
|
87 |
|
88 |
|
89 | (renderPromises &&
|
90 | renderPromises.getSSRObservable(makeWatchQueryOptions())) ||
|
91 | client.watchQuery(getObsQueryOptions(void 0, client, options, makeWatchQueryOptions())),
|
92 | resultData: {
|
93 |
|
94 |
|
95 | previousData: (_a = previous === null || previous === void 0 ? void 0 : previous.resultData.current) === null || _a === void 0 ? void 0 : _a.data,
|
96 | },
|
97 | };
|
98 | return internalState;
|
99 | }
|
100 | var _a = React.useState(createInternalState), internalState = _a[0], updateInternalState = _a[1];
|
101 | |
102 |
|
103 |
|
104 |
|
105 |
|
106 | function onQueryExecuted(watchQueryOptions) {
|
107 | var _a;
|
108 | var _b;
|
109 |
|
110 |
|
111 | Object.assign(internalState.observable, (_a = {},
|
112 | _a[lastWatchOptions] = watchQueryOptions,
|
113 | _a));
|
114 | var resultData = internalState.resultData;
|
115 | updateInternalState(__assign(__assign({}, internalState), {
|
116 |
|
117 | query: watchQueryOptions.query, resultData: Object.assign(resultData, {
|
118 |
|
119 |
|
120 | previousData: ((_b = resultData.current) === null || _b === void 0 ? void 0 : _b.data) || resultData.previousData,
|
121 | current: undefined,
|
122 | }) }));
|
123 | }
|
124 | if (client !== internalState.client || query !== internalState.query) {
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 | var newInternalState = createInternalState(internalState);
|
132 | updateInternalState(newInternalState);
|
133 | return [newInternalState, onQueryExecuted];
|
134 | }
|
135 | return [internalState, onQueryExecuted];
|
136 | }
|
137 | export function useQueryInternals(query, options) {
|
138 | var client = useApolloClient(options.client);
|
139 | var renderPromises = React.useContext(getApolloContext()).renderPromises;
|
140 | var isSyncSSR = !!renderPromises;
|
141 | var disableNetworkFetches = client.disableNetworkFetches;
|
142 | var ssrAllowed = options.ssr !== false && !options.skip;
|
143 | var partialRefetch = options.partialRefetch;
|
144 | var makeWatchQueryOptions = createMakeWatchQueryOptions(client, query, options, isSyncSSR);
|
145 | var _a = useInternalState(client, query, options, renderPromises, makeWatchQueryOptions), _b = _a[0], observable = _b.observable, resultData = _b.resultData, onQueryExecuted = _a[1];
|
146 | var watchQueryOptions = makeWatchQueryOptions(observable);
|
147 | useResubscribeIfNecessary(resultData,
|
148 | observable,
|
149 | client, options, watchQueryOptions);
|
150 | var obsQueryFields = React.useMemo(function () { return bindObservableMethods(observable); }, [observable]);
|
151 | useRegisterSSRObservable(observable, renderPromises, ssrAllowed);
|
152 | var result = useObservableSubscriptionResult(resultData, observable, client, options, watchQueryOptions, disableNetworkFetches, partialRefetch, isSyncSSR, {
|
153 | onCompleted: options.onCompleted || noop,
|
154 | onError: options.onError || noop,
|
155 | });
|
156 | return {
|
157 | result: result,
|
158 | obsQueryFields: obsQueryFields,
|
159 | observable: observable,
|
160 | resultData: resultData,
|
161 | client: client,
|
162 | onQueryExecuted: onQueryExecuted,
|
163 | };
|
164 | }
|
165 | function useObservableSubscriptionResult(resultData, observable, client, options, watchQueryOptions, disableNetworkFetches, partialRefetch, isSyncSSR, callbacks) {
|
166 | var callbackRef = React.useRef(callbacks);
|
167 | React.useEffect(function () {
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 | callbackRef.current = callbacks;
|
175 | });
|
176 | var resultOverride = ((isSyncSSR || disableNetworkFetches) &&
|
177 | options.ssr === false &&
|
178 | !options.skip) ?
|
179 |
|
180 |
|
181 | ssrDisabledResult
|
182 | : options.skip || watchQueryOptions.fetchPolicy === "standby" ?
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 |
|
192 |
|
193 | skipStandbyResult
|
194 | : void 0;
|
195 | var previousData = resultData.previousData;
|
196 | var currentResultOverride = React.useMemo(function () {
|
197 | return resultOverride &&
|
198 | toQueryResult(resultOverride, previousData, observable, client);
|
199 | }, [client, observable, resultOverride, previousData]);
|
200 | return useSyncExternalStore(React.useCallback(function (handleStoreChange) {
|
201 |
|
202 |
|
203 | disableNetworkFetches;
|
204 | if (isSyncSSR) {
|
205 | return function () { };
|
206 | }
|
207 | var onNext = function () {
|
208 | var previousResult = resultData.current;
|
209 |
|
210 |
|
211 |
|
212 | var result = observable.getCurrentResult();
|
213 |
|
214 | if (previousResult &&
|
215 | previousResult.loading === result.loading &&
|
216 | previousResult.networkStatus === result.networkStatus &&
|
217 | equal(previousResult.data, result.data)) {
|
218 | return;
|
219 | }
|
220 | setResult(result, resultData, observable, client, partialRefetch, handleStoreChange, callbackRef.current);
|
221 | };
|
222 | var onError = function (error) {
|
223 | subscription.current.unsubscribe();
|
224 | subscription.current = observable.resubscribeAfterError(onNext, onError);
|
225 | if (!hasOwnProperty.call(error, "graphQLErrors")) {
|
226 |
|
227 | throw error;
|
228 | }
|
229 | var previousResult = resultData.current;
|
230 | if (!previousResult ||
|
231 | (previousResult && previousResult.loading) ||
|
232 | !equal(error, previousResult.error)) {
|
233 | setResult({
|
234 | data: (previousResult && previousResult.data),
|
235 | error: error,
|
236 | loading: false,
|
237 | networkStatus: NetworkStatus.error,
|
238 | }, resultData, observable, client, partialRefetch, handleStoreChange, callbackRef.current);
|
239 | }
|
240 | };
|
241 |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 | var subscription = { current: observable.subscribe(onNext, onError) };
|
247 |
|
248 |
|
249 |
|
250 |
|
251 | return function () {
|
252 | setTimeout(function () { return subscription.current.unsubscribe(); });
|
253 | };
|
254 | }, [
|
255 | disableNetworkFetches,
|
256 | isSyncSSR,
|
257 | observable,
|
258 | resultData,
|
259 | partialRefetch,
|
260 | client,
|
261 | ]), function () {
|
262 | return currentResultOverride ||
|
263 | getCurrentResult(resultData, observable, callbackRef.current, partialRefetch, client);
|
264 | }, function () {
|
265 | return currentResultOverride ||
|
266 | getCurrentResult(resultData, observable, callbackRef.current, partialRefetch, client);
|
267 | });
|
268 | }
|
269 | function useRegisterSSRObservable(observable, renderPromises, ssrAllowed) {
|
270 | if (renderPromises && ssrAllowed) {
|
271 | renderPromises.registerSSRObservable(observable);
|
272 | if (observable.getCurrentResult().loading) {
|
273 |
|
274 | renderPromises.addObservableQueryPromise(observable);
|
275 | }
|
276 | }
|
277 | }
|
278 |
|
279 |
|
280 | function useResubscribeIfNecessary(
|
281 | /** this hook will mutate properties on `resultData` */
|
282 | resultData,
|
283 | /** this hook will mutate properties on `observable` */
|
284 | observable, client, options, watchQueryOptions) {
|
285 | var _a;
|
286 | if (observable[lastWatchOptions] &&
|
287 | !equal(observable[lastWatchOptions], watchQueryOptions)) {
|
288 |
|
289 |
|
290 |
|
291 |
|
292 |
|
293 |
|
294 |
|
295 |
|
296 | observable.reobserve(getObsQueryOptions(observable, client, options, watchQueryOptions));
|
297 |
|
298 |
|
299 |
|
300 | resultData.previousData =
|
301 | ((_a = resultData.current) === null || _a === void 0 ? void 0 : _a.data) || resultData.previousData;
|
302 | resultData.current = void 0;
|
303 | }
|
304 | observable[lastWatchOptions] = watchQueryOptions;
|
305 | }
|
306 |
|
307 |
|
308 |
|
309 |
|
310 |
|
311 | export function createMakeWatchQueryOptions(client, query, _a, isSyncSSR) {
|
312 | if (_a === void 0) { _a = {}; }
|
313 | var skip = _a.skip, ssr = _a.ssr, onCompleted = _a.onCompleted, onError = _a.onError, defaultOptions = _a.defaultOptions,
|
314 |
|
315 |
|
316 |
|
317 | otherOptions = __rest(_a, ["skip", "ssr", "onCompleted", "onError", "defaultOptions"]);
|
318 | return function (observable) {
|
319 |
|
320 |
|
321 | var watchQueryOptions = Object.assign(otherOptions, { query: query });
|
322 | if (isSyncSSR &&
|
323 | (watchQueryOptions.fetchPolicy === "network-only" ||
|
324 | watchQueryOptions.fetchPolicy === "cache-and-network")) {
|
325 |
|
326 |
|
327 | watchQueryOptions.fetchPolicy = "cache-first";
|
328 | }
|
329 | if (!watchQueryOptions.variables) {
|
330 | watchQueryOptions.variables = {};
|
331 | }
|
332 | if (skip) {
|
333 |
|
334 |
|
335 |
|
336 | watchQueryOptions.initialFetchPolicy =
|
337 | watchQueryOptions.initialFetchPolicy ||
|
338 | watchQueryOptions.fetchPolicy ||
|
339 | getDefaultFetchPolicy(defaultOptions, client.defaultOptions);
|
340 | watchQueryOptions.fetchPolicy = "standby";
|
341 | }
|
342 | else if (!watchQueryOptions.fetchPolicy) {
|
343 | watchQueryOptions.fetchPolicy =
|
344 | (observable === null || observable === void 0 ? void 0 : observable.options.initialFetchPolicy) ||
|
345 | getDefaultFetchPolicy(defaultOptions, client.defaultOptions);
|
346 | }
|
347 | return watchQueryOptions;
|
348 | };
|
349 | }
|
350 | export function getObsQueryOptions(observable, client, queryHookOptions, watchQueryOptions) {
|
351 | var toMerge = [];
|
352 | var globalDefaults = client.defaultOptions.watchQuery;
|
353 | if (globalDefaults)
|
354 | toMerge.push(globalDefaults);
|
355 | if (queryHookOptions.defaultOptions) {
|
356 | toMerge.push(queryHookOptions.defaultOptions);
|
357 | }
|
358 |
|
359 |
|
360 |
|
361 |
|
362 |
|
363 |
|
364 |
|
365 |
|
366 |
|
367 |
|
368 | toMerge.push(compact(observable && observable.options, watchQueryOptions));
|
369 | return toMerge.reduce(mergeOptions);
|
370 | }
|
371 | function setResult(nextResult, resultData, observable, client, partialRefetch, forceUpdate, callbacks) {
|
372 | var previousResult = resultData.current;
|
373 | if (previousResult && previousResult.data) {
|
374 | resultData.previousData = previousResult.data;
|
375 | }
|
376 | if (!nextResult.error && isNonEmptyArray(nextResult.errors)) {
|
377 |
|
378 |
|
379 |
|
380 |
|
381 | nextResult.error = new ApolloError({ graphQLErrors: nextResult.errors });
|
382 | }
|
383 | resultData.current = toQueryResult(unsafeHandlePartialRefetch(nextResult, observable, partialRefetch), resultData.previousData, observable, client);
|
384 |
|
385 |
|
386 | forceUpdate();
|
387 | handleErrorOrCompleted(nextResult, previousResult === null || previousResult === void 0 ? void 0 : previousResult.networkStatus, callbacks);
|
388 | }
|
389 | function handleErrorOrCompleted(result, previousNetworkStatus, callbacks) {
|
390 | if (!result.loading) {
|
391 | var error_1 = toApolloError(result);
|
392 |
|
393 | Promise.resolve()
|
394 | .then(function () {
|
395 | if (error_1) {
|
396 | callbacks.onError(error_1);
|
397 | }
|
398 | else if (result.data &&
|
399 | previousNetworkStatus !== result.networkStatus &&
|
400 | result.networkStatus === NetworkStatus.ready) {
|
401 | callbacks.onCompleted(result.data);
|
402 | }
|
403 | })
|
404 | .catch(function (error) {
|
405 | globalThis.__DEV__ !== false && invariant.warn(error);
|
406 | });
|
407 | }
|
408 | }
|
409 | function getCurrentResult(resultData, observable, callbacks, partialRefetch, client) {
|
410 |
|
411 |
|
412 |
|
413 | if (!resultData.current) {
|
414 |
|
415 |
|
416 | setResult(observable.getCurrentResult(), resultData, observable, client, partialRefetch, function () { }, callbacks);
|
417 | }
|
418 | return resultData.current;
|
419 | }
|
420 | export function getDefaultFetchPolicy(queryHookDefaultOptions, clientDefaultOptions) {
|
421 | var _a;
|
422 | return ((queryHookDefaultOptions === null || queryHookDefaultOptions === void 0 ? void 0 : queryHookDefaultOptions.fetchPolicy) ||
|
423 | ((_a = clientDefaultOptions === null || clientDefaultOptions === void 0 ? void 0 : clientDefaultOptions.watchQuery) === null || _a === void 0 ? void 0 : _a.fetchPolicy) ||
|
424 | "cache-first");
|
425 | }
|
426 | export function toApolloError(result) {
|
427 | return isNonEmptyArray(result.errors) ?
|
428 | new ApolloError({ graphQLErrors: result.errors })
|
429 | : result.error;
|
430 | }
|
431 | export function toQueryResult(result, previousData, observable, client) {
|
432 | var data = result.data, partial = result.partial, resultWithoutPartial = __rest(result, ["data", "partial"]);
|
433 | var queryResult = __assign(__assign({ data: data }, resultWithoutPartial), { client: client, observable: observable, variables: observable.variables, called: result !== ssrDisabledResult && result !== skipStandbyResult, previousData: previousData });
|
434 | return queryResult;
|
435 | }
|
436 | function unsafeHandlePartialRefetch(result, observable, partialRefetch) {
|
437 |
|
438 |
|
439 |
|
440 | if (result.partial &&
|
441 | partialRefetch &&
|
442 | !result.loading &&
|
443 | (!result.data || Object.keys(result.data).length === 0) &&
|
444 | observable.options.fetchPolicy !== "cache-only") {
|
445 | observable.refetch();
|
446 | return __assign(__assign({}, result), { loading: true, networkStatus: NetworkStatus.refetch });
|
447 | }
|
448 | return result;
|
449 | }
|
450 | var ssrDisabledResult = maybeDeepFreeze({
|
451 | loading: true,
|
452 | data: void 0,
|
453 | error: void 0,
|
454 | networkStatus: NetworkStatus.loading,
|
455 | });
|
456 | var skipStandbyResult = maybeDeepFreeze({
|
457 | loading: false,
|
458 | data: void 0,
|
459 | error: void 0,
|
460 | networkStatus: NetworkStatus.ready,
|
461 | });
|
462 | function bindObservableMethods(observable) {
|
463 | return {
|
464 | refetch: observable.refetch.bind(observable),
|
465 | reobserve: observable.reobserve.bind(observable),
|
466 | fetchMore: observable.fetchMore.bind(observable),
|
467 | updateQuery: observable.updateQuery.bind(observable),
|
468 | startPolling: observable.startPolling.bind(observable),
|
469 | stopPolling: observable.stopPolling.bind(observable),
|
470 | subscribeToMore: observable.subscribeToMore.bind(observable),
|
471 | };
|
472 | }
|
473 |
|
\ | No newline at end of file |