1 | import { __assign, __rest } from "tslib";
|
2 | import { invariant } from "../../utilities/globals/index.js";
|
3 | import { useCallback, useContext, useMemo, useRef, useState, } from 'react';
|
4 | import { useSyncExternalStore } from "./useSyncExternalStore.js";
|
5 | import { equal } from '@wry/equality';
|
6 | import { mergeOptions } from "../../core/index.js";
|
7 | import { getApolloContext } from "../context/index.js";
|
8 | import { ApolloError } from "../../errors/index.js";
|
9 | import { NetworkStatus, } from "../../core/index.js";
|
10 | import { DocumentType, verifyDocumentType } from "../parser/index.js";
|
11 | import { useApolloClient } from "./useApolloClient.js";
|
12 | import { canUseWeakMap, canUseWeakSet, compact, isNonEmptyArray, maybeDeepFreeze } from "../../utilities/index.js";
|
13 | var hasOwnProperty = Object.prototype.hasOwnProperty;
|
14 | export function useQuery(query, options) {
|
15 | if (options === void 0) { options = Object.create(null); }
|
16 | return useInternalState(useApolloClient(options.client), query).useQuery(options);
|
17 | }
|
18 | export function useInternalState(client, query) {
|
19 | var stateRef = useRef();
|
20 | if (!stateRef.current ||
|
21 | client !== stateRef.current.client ||
|
22 | query !== stateRef.current.query) {
|
23 | stateRef.current = new InternalState(client, query, stateRef.current);
|
24 | }
|
25 | var state = stateRef.current;
|
26 | var _a = useState(0), _tick = _a[0], setTick = _a[1];
|
27 | state.forceUpdate = function () {
|
28 | setTick(function (tick) { return tick + 1; });
|
29 | };
|
30 | return state;
|
31 | }
|
32 | var InternalState = (function () {
|
33 | function InternalState(client, query, previous) {
|
34 | this.client = client;
|
35 | this.query = query;
|
36 | this.asyncResolveFns = new Set();
|
37 | this.optionsToIgnoreOnce = new (canUseWeakSet ? WeakSet : Set)();
|
38 | this.ssrDisabledResult = maybeDeepFreeze({
|
39 | loading: true,
|
40 | data: void 0,
|
41 | error: void 0,
|
42 | networkStatus: NetworkStatus.loading,
|
43 | });
|
44 | this.skipStandbyResult = maybeDeepFreeze({
|
45 | loading: false,
|
46 | data: void 0,
|
47 | error: void 0,
|
48 | networkStatus: NetworkStatus.ready,
|
49 | });
|
50 | this.toQueryResultCache = new (canUseWeakMap ? WeakMap : Map)();
|
51 | verifyDocumentType(query, DocumentType.Query);
|
52 | var previousResult = previous && previous.result;
|
53 | var previousData = previousResult && previousResult.data;
|
54 | if (previousData) {
|
55 | this.previousData = previousData;
|
56 | }
|
57 | }
|
58 | InternalState.prototype.forceUpdate = function () {
|
59 | __DEV__ && invariant.warn("Calling default no-op implementation of InternalState#forceUpdate");
|
60 | };
|
61 | InternalState.prototype.asyncUpdate = function (signal) {
|
62 | var _this = this;
|
63 | return new Promise(function (resolve, reject) {
|
64 | var watchQueryOptions = _this.watchQueryOptions;
|
65 | var handleAborted = function () {
|
66 | _this.asyncResolveFns.delete(resolve);
|
67 | _this.optionsToIgnoreOnce.delete(watchQueryOptions);
|
68 | signal.removeEventListener('abort', handleAborted);
|
69 | reject(signal.reason);
|
70 | };
|
71 | _this.asyncResolveFns.add(resolve);
|
72 | _this.optionsToIgnoreOnce.add(watchQueryOptions);
|
73 | signal.addEventListener('abort', handleAborted);
|
74 | _this.forceUpdate();
|
75 | });
|
76 | };
|
77 | InternalState.prototype.useQuery = function (options) {
|
78 | var _this = this;
|
79 | this.renderPromises = useContext(getApolloContext()).renderPromises;
|
80 | this.useOptions(options);
|
81 | var obsQuery = this.useObservableQuery();
|
82 | var result = useSyncExternalStore(useCallback(function () {
|
83 | if (_this.renderPromises) {
|
84 | return function () { };
|
85 | }
|
86 | var onNext = function () {
|
87 | var previousResult = _this.result;
|
88 | var result = obsQuery.getCurrentResult();
|
89 | if (previousResult &&
|
90 | previousResult.loading === result.loading &&
|
91 | previousResult.networkStatus === result.networkStatus &&
|
92 | equal(previousResult.data, result.data)) {
|
93 | return;
|
94 | }
|
95 | _this.setResult(result);
|
96 | };
|
97 | var onError = function (error) {
|
98 | var last = obsQuery["last"];
|
99 | subscription.unsubscribe();
|
100 | try {
|
101 | obsQuery.resetLastResults();
|
102 | subscription = obsQuery.subscribe(onNext, onError);
|
103 | }
|
104 | finally {
|
105 | obsQuery["last"] = last;
|
106 | }
|
107 | if (!hasOwnProperty.call(error, 'graphQLErrors')) {
|
108 | throw error;
|
109 | }
|
110 | var previousResult = _this.result;
|
111 | if (!previousResult ||
|
112 | (previousResult && previousResult.loading) ||
|
113 | !equal(error, previousResult.error)) {
|
114 | _this.setResult({
|
115 | data: (previousResult && previousResult.data),
|
116 | error: error,
|
117 | loading: false,
|
118 | networkStatus: NetworkStatus.error,
|
119 | });
|
120 | }
|
121 | };
|
122 | var subscription = obsQuery.subscribe(onNext, onError);
|
123 | return function () { return subscription.unsubscribe(); };
|
124 | }, [
|
125 | obsQuery,
|
126 | this.renderPromises,
|
127 | this.client.disableNetworkFetches,
|
128 | ]), function () { return _this.getCurrentResult(); }, function () { return _this.getCurrentResult(); });
|
129 | this.unsafeHandlePartialRefetch(result);
|
130 | var queryResult = this.toQueryResult(result);
|
131 | if (!queryResult.loading && this.asyncResolveFns.size) {
|
132 | this.asyncResolveFns.forEach(function (resolve) { return resolve(queryResult); });
|
133 | this.asyncResolveFns.clear();
|
134 | }
|
135 | return queryResult;
|
136 | };
|
137 | InternalState.prototype.useOptions = function (options) {
|
138 | var _a;
|
139 | var watchQueryOptions = this.createWatchQueryOptions(this.queryHookOptions = options);
|
140 | var currentWatchQueryOptions = this.watchQueryOptions;
|
141 | if (this.optionsToIgnoreOnce.has(currentWatchQueryOptions) ||
|
142 | !equal(watchQueryOptions, currentWatchQueryOptions)) {
|
143 | this.watchQueryOptions = watchQueryOptions;
|
144 | if (currentWatchQueryOptions && this.observable) {
|
145 | this.optionsToIgnoreOnce.delete(currentWatchQueryOptions);
|
146 | this.observable.reobserve(this.getObsQueryOptions());
|
147 | this.previousData = ((_a = this.result) === null || _a === void 0 ? void 0 : _a.data) || this.previousData;
|
148 | this.result = void 0;
|
149 | }
|
150 | }
|
151 | this.onCompleted = options.onCompleted || InternalState.prototype.onCompleted;
|
152 | this.onError = options.onError || InternalState.prototype.onError;
|
153 | if ((this.renderPromises || this.client.disableNetworkFetches) &&
|
154 | this.queryHookOptions.ssr === false &&
|
155 | !this.queryHookOptions.skip) {
|
156 | this.result = this.ssrDisabledResult;
|
157 | }
|
158 | else if (this.queryHookOptions.skip ||
|
159 | this.watchQueryOptions.fetchPolicy === 'standby') {
|
160 | this.result = this.skipStandbyResult;
|
161 | }
|
162 | else if (this.result === this.ssrDisabledResult ||
|
163 | this.result === this.skipStandbyResult) {
|
164 | this.result = void 0;
|
165 | }
|
166 | };
|
167 | InternalState.prototype.getObsQueryOptions = function () {
|
168 | var toMerge = [];
|
169 | var globalDefaults = this.client.defaultOptions.watchQuery;
|
170 | if (globalDefaults)
|
171 | toMerge.push(globalDefaults);
|
172 | if (this.queryHookOptions.defaultOptions) {
|
173 | toMerge.push(this.queryHookOptions.defaultOptions);
|
174 | }
|
175 | toMerge.push(compact(this.observable && this.observable.options, this.watchQueryOptions));
|
176 | return toMerge.reduce(mergeOptions);
|
177 | };
|
178 | InternalState.prototype.createWatchQueryOptions = function (_a) {
|
179 | var _b;
|
180 | if (_a === void 0) { _a = {}; }
|
181 | var skip = _a.skip, ssr = _a.ssr, onCompleted = _a.onCompleted, onError = _a.onError, defaultOptions = _a.defaultOptions, otherOptions = __rest(_a, ["skip", "ssr", "onCompleted", "onError", "defaultOptions"]);
|
182 | var watchQueryOptions = Object.assign(otherOptions, { query: this.query });
|
183 | if (this.renderPromises &&
|
184 | (watchQueryOptions.fetchPolicy === 'network-only' ||
|
185 | watchQueryOptions.fetchPolicy === 'cache-and-network')) {
|
186 | watchQueryOptions.fetchPolicy = 'cache-first';
|
187 | }
|
188 | if (!watchQueryOptions.variables) {
|
189 | watchQueryOptions.variables = {};
|
190 | }
|
191 | if (skip) {
|
192 | var _c = watchQueryOptions.fetchPolicy, fetchPolicy = _c === void 0 ? this.getDefaultFetchPolicy() : _c, _d = watchQueryOptions.initialFetchPolicy, initialFetchPolicy = _d === void 0 ? fetchPolicy : _d;
|
193 | Object.assign(watchQueryOptions, {
|
194 | initialFetchPolicy: initialFetchPolicy,
|
195 | fetchPolicy: 'standby',
|
196 | });
|
197 | }
|
198 | else if (!watchQueryOptions.fetchPolicy) {
|
199 | watchQueryOptions.fetchPolicy =
|
200 | ((_b = this.observable) === null || _b === void 0 ? void 0 : _b.options.initialFetchPolicy) ||
|
201 | this.getDefaultFetchPolicy();
|
202 | }
|
203 | return watchQueryOptions;
|
204 | };
|
205 | InternalState.prototype.getDefaultFetchPolicy = function () {
|
206 | var _a, _b;
|
207 | return (((_a = this.queryHookOptions.defaultOptions) === null || _a === void 0 ? void 0 : _a.fetchPolicy) ||
|
208 | ((_b = this.client.defaultOptions.watchQuery) === null || _b === void 0 ? void 0 : _b.fetchPolicy) ||
|
209 | "cache-first");
|
210 | };
|
211 | InternalState.prototype.onCompleted = function (data) { };
|
212 | InternalState.prototype.onError = function (error) { };
|
213 | InternalState.prototype.useObservableQuery = function () {
|
214 | var obsQuery = this.observable =
|
215 | this.renderPromises
|
216 | && this.renderPromises.getSSRObservable(this.watchQueryOptions)
|
217 | || this.observable
|
218 | || this.client.watchQuery(this.getObsQueryOptions());
|
219 | this.obsQueryFields = useMemo(function () { return ({
|
220 | refetch: obsQuery.refetch.bind(obsQuery),
|
221 | reobserve: obsQuery.reobserve.bind(obsQuery),
|
222 | fetchMore: obsQuery.fetchMore.bind(obsQuery),
|
223 | updateQuery: obsQuery.updateQuery.bind(obsQuery),
|
224 | startPolling: obsQuery.startPolling.bind(obsQuery),
|
225 | stopPolling: obsQuery.stopPolling.bind(obsQuery),
|
226 | subscribeToMore: obsQuery.subscribeToMore.bind(obsQuery),
|
227 | }); }, [obsQuery]);
|
228 | var ssrAllowed = !(this.queryHookOptions.ssr === false ||
|
229 | this.queryHookOptions.skip);
|
230 | if (this.renderPromises && ssrAllowed) {
|
231 | this.renderPromises.registerSSRObservable(obsQuery);
|
232 | if (obsQuery.getCurrentResult().loading) {
|
233 | this.renderPromises.addObservableQueryPromise(obsQuery);
|
234 | }
|
235 | }
|
236 | return obsQuery;
|
237 | };
|
238 | InternalState.prototype.setResult = function (nextResult) {
|
239 | var previousResult = this.result;
|
240 | if (previousResult && previousResult.data) {
|
241 | this.previousData = previousResult.data;
|
242 | }
|
243 | this.result = nextResult;
|
244 | this.forceUpdate();
|
245 | this.handleErrorOrCompleted(nextResult);
|
246 | };
|
247 | InternalState.prototype.handleErrorOrCompleted = function (result) {
|
248 | var _this = this;
|
249 | if (!result.loading) {
|
250 | var error_1 = this.toApolloError(result);
|
251 | Promise.resolve().then(function () {
|
252 | if (error_1) {
|
253 | _this.onError(error_1);
|
254 | }
|
255 | else if (result.data) {
|
256 | _this.onCompleted(result.data);
|
257 | }
|
258 | }).catch(function (error) {
|
259 | __DEV__ && invariant.warn(error);
|
260 | });
|
261 | }
|
262 | };
|
263 | InternalState.prototype.toApolloError = function (result) {
|
264 | return isNonEmptyArray(result.errors)
|
265 | ? new ApolloError({ graphQLErrors: result.errors })
|
266 | : result.error;
|
267 | };
|
268 | InternalState.prototype.getCurrentResult = function () {
|
269 | if (!this.result) {
|
270 | this.handleErrorOrCompleted(this.result = this.observable.getCurrentResult());
|
271 | }
|
272 | return this.result;
|
273 | };
|
274 | InternalState.prototype.toQueryResult = function (result) {
|
275 | var queryResult = this.toQueryResultCache.get(result);
|
276 | if (queryResult)
|
277 | return queryResult;
|
278 | var data = result.data, partial = result.partial, resultWithoutPartial = __rest(result, ["data", "partial"]);
|
279 | this.toQueryResultCache.set(result, queryResult = __assign(__assign(__assign({ data: data }, resultWithoutPartial), this.obsQueryFields), { client: this.client, observable: this.observable, variables: this.observable.variables, called: !this.queryHookOptions.skip, previousData: this.previousData }));
|
280 | if (!queryResult.error && isNonEmptyArray(result.errors)) {
|
281 | queryResult.error = new ApolloError({ graphQLErrors: result.errors });
|
282 | }
|
283 | return queryResult;
|
284 | };
|
285 | InternalState.prototype.unsafeHandlePartialRefetch = function (result) {
|
286 | if (result.partial &&
|
287 | this.queryHookOptions.partialRefetch &&
|
288 | !result.loading &&
|
289 | (!result.data || Object.keys(result.data).length === 0) &&
|
290 | this.observable.options.fetchPolicy !== 'cache-only') {
|
291 | Object.assign(result, {
|
292 | loading: true,
|
293 | networkStatus: NetworkStatus.refetch,
|
294 | });
|
295 | this.observable.refetch();
|
296 | }
|
297 | };
|
298 | return InternalState;
|
299 | }());
|
300 |
|
\ | No newline at end of file |