relay-hooks
Version:
1,499 lines (1,219 loc) • 52.8 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('relay-runtime'), require('react'), require('fbjs/lib/areEqual'), require('fbjs/lib/warning'), require('fbjs/lib/invariant'), require('@restart/hooks/useMounted')) :
typeof define === 'function' && define.amd ? define(['exports', 'relay-runtime', 'react', 'fbjs/lib/areEqual', 'fbjs/lib/warning', 'fbjs/lib/invariant', '@restart/hooks/useMounted'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global['relay-hooks'] = {}, global.relayRuntime, global.React, global.areEqual, global.warning, global.invariant, global.useMounted));
}(this, (function (exports, relayRuntime, React, areEqual, warning, invariant, useMounted) { 'use strict';
var React__default = 'default' in React ? React['default'] : React;
areEqual = areEqual && Object.prototype.hasOwnProperty.call(areEqual, 'default') ? areEqual['default'] : areEqual;
warning = warning && Object.prototype.hasOwnProperty.call(warning, 'default') ? warning['default'] : warning;
invariant = invariant && Object.prototype.hasOwnProperty.call(invariant, 'default') ? invariant['default'] : invariant;
useMounted = useMounted && Object.prototype.hasOwnProperty.call(useMounted, 'default') ? useMounted['default'] : useMounted;
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
var createRelayContext = relayRuntime.__internal.createRelayContext;
var ReactRelayContext = createRelayContext(React__default);
var NETWORK_ONLY = 'network-only';
var STORE_THEN_NETWORK = 'store-and-network';
var STORE_OR_NETWORK = 'store-or-network';
var STORE_ONLY = 'store-only';
var PAGINATION_NAME = 'usePagination';
var REFETCHABLE_NAME = 'useRefetchable';
var FRAGMENT_NAME = 'useFragment'; // pagination
var FORWARD = 'forward';
var isNetworkPolicy = function (policy, full) {
return policy === NETWORK_ONLY || policy === STORE_THEN_NETWORK || policy === STORE_OR_NETWORK && !full;
};
var isStorePolicy = function (policy) {
return policy !== NETWORK_ONLY;
};
var forceCache = {
force: true
}; // Fetcher
function createOperation(gqlQuery, variables, cacheConfig) {
return relayRuntime.createOperationDescriptor(relayRuntime.getRequest(gqlQuery), variables, cacheConfig);
}
var fetchQuery = relayRuntime.__internal.fetchQuery;
var DATA_RETENTION_TIMEOUT = 30 * 1000;
function fetchResolver(_a) {
var _b = _a.doRetain,
doRetain = _b === void 0 ? true : _b,
disposeTemporary = _a.disposeTemporary;
var _refetchSubscription = null;
var disposable = null;
var releaseQueryTimeout;
var isLoading = false;
var query;
var promise;
var error = null;
var env;
var update = function (loading, e) {
if (e === void 0) {
e = null;
}
isLoading = loading;
error = e;
};
var lookupInStore = function (environment, operation, fetchPolicy, renderPolicy) {
if (isStorePolicy(fetchPolicy)) {
var check = environment.check(operation);
var queryStatus = check.status;
var hasFullQuery = queryStatus === 'available';
var canPartialRender = hasFullQuery || renderPolicy === 'partial' && queryStatus !== 'stale';
if (canPartialRender) {
return {
snapshot: environment.lookup(operation.fragment),
full: hasFullQuery
};
}
}
return {
snapshot: null,
full: false
};
};
var dispose = function () {
clearTemporaryRetain();
disposable && disposable.dispose();
disposeRequest();
disposable = null;
env = null;
query = null;
};
var clearTemporaryRetain = function () {
clearTimeout(releaseQueryTimeout);
releaseQueryTimeout = null;
};
var temporaryRetain = function () {
var localReleaseTemporaryRetain = function () {
clearTemporaryRetain();
dispose();
disposeTemporary && disposeTemporary();
};
releaseQueryTimeout = setTimeout(localReleaseTemporaryRetain, DATA_RETENTION_TIMEOUT);
};
var disposeRequest = function () {
_refetchSubscription && _refetchSubscription.unsubscribe();
error = null;
isLoading = false;
};
var fetch = function (environment, operation, fetchPolicy, onComplete, onNext, onResponse, renderPolicy) {
if (fetchPolicy === void 0) {
fetchPolicy = 'network-only';
}
if (onComplete === void 0) {
onComplete = function (_e, _u) {
return undefined;
};
}
var fetchHasReturned = false;
if (env != environment || query.request.identifier !== operation.request.identifier) {
dispose();
if (doRetain) {
disposable = environment.retain(operation);
}
}
env = environment;
query = operation;
disposeRequest();
var _a = lookupInStore(environment, operation, fetchPolicy, renderPolicy),
snapshot = _a.snapshot,
full = _a.full;
var isNetwork = isNetworkPolicy(fetchPolicy, full);
if (snapshot != null) {
var onlyStore = !isNetwork;
onNext(operation, snapshot, fetchHasReturned && !onlyStore);
if (onlyStore) {
onComplete(null, fetchHasReturned);
}
} // Cancel any previously running refetch.
_refetchSubscription && _refetchSubscription.unsubscribe();
var refetchSubscription;
if (isNetwork) {
var resolveNetworkPromise_1 = function () {}; // Declare refetchSubscription before assigning it in .start(), since
// synchronous completion may call callbacks .subscribe() returns.
var cleanup_1 = function () {
if (_refetchSubscription === refetchSubscription) {
_refetchSubscription = null;
}
isLoading = false;
promise = null;
};
var complete_1 = function (error) {
if (error === void 0) {
error = null;
}
resolveNetworkPromise_1();
update(false, error);
cleanup_1();
onComplete(error, fetchHasReturned);
};
fetchQuery(environment, operation).subscribe({
unsubscribe: function () {
cleanup_1();
},
complete: complete_1,
error: function (e) {
return complete_1(e);
},
next: function (response) {
var store = environment.lookup(operation.fragment);
promise = null;
var responses = Array.isArray(response) ? response : [response];
var cacheConfig = operation.request.cacheConfig;
var isQueryPolling = !!cacheConfig && !!cacheConfig.poll;
var isIncremental = responses.some(function (x) {
return x != null && x.hasNext === true;
});
isQueryPolling && update(false);
resolveNetworkPromise_1();
onResponse && onResponse(response);
onNext(operation, store, fetchHasReturned && (isIncremental || isQueryPolling));
},
start: function (subscription) {
refetchSubscription = subscription;
_refetchSubscription = refetchSubscription;
update(true);
}
});
if (!snapshot) {
promise = new Promise(function (resolve) {
resolveNetworkPromise_1 = resolve;
});
}
}
fetchHasReturned = true;
return {
dispose: function () {
refetchSubscription && refetchSubscription.unsubscribe();
}
};
};
var checkAndSuspense = function (suspense, useLazy) {
clearTemporaryRetain();
var toThrow = promise || error;
if (suspense && toThrow) {
if (promise && useLazy) {
temporaryRetain();
}
throw toThrow;
}
return toThrow;
};
var getData = function () {
return {
isLoading: isLoading,
error: error
};
};
return {
fetch: fetch,
getData: getData,
dispose: dispose,
checkAndSuspense: checkAndSuspense
};
}
var defaultPolicy = 'store-or-network';
var cache = new Map();
function getOrCreateQueryFetcher(useLazy, gqlQuery, variables, networkCacheConfig) {
var query = createOperation(gqlQuery, variables, networkCacheConfig);
var toGet = useLazy && cache.has(query.request.identifier);
var queryFetcher = toGet ? cache.get(query.request.identifier) : new QueryFetcher();
queryFetcher.setQuery(gqlQuery, variables, networkCacheConfig, query);
return queryFetcher;
}
var emptyforceUpdate = function () {
return undefined;
};
var QueryFetcher =
/** @class */
function () {
function QueryFetcher() {
var _this = this;
this.forceUpdate = emptyforceUpdate;
this.result = null;
this.retry = function (cacheConfigOverride, options) {
if (options === void 0) {
options = {};
}
var _a = options.fetchPolicy,
fetchPolicy = _a === void 0 ? 'network-only' : _a;
/* eslint-disable indent */
var query = cacheConfigOverride ? createOperation(_this.query.request.node, _this.query.request.variables, cacheConfigOverride) : _this.query;
_this.fetch(query, fetchPolicy, options);
_this.resolveResult();
_this.forceUpdate();
};
this.result = {
retry: this.retry,
error: null,
data: null,
isLoading: false
};
this.fetcher = fetchResolver({
disposeTemporary: function () {
_this.dispose();
_this.query && cache.delete(_this.query.request.identifier);
}
});
}
QueryFetcher.prototype.setQuery = function (gqlQuery, variables, networkCacheConfig, query) {
this.gqlQuery = gqlQuery;
this.variables = variables;
this.query = query;
this.cacheConfig = networkCacheConfig;
};
QueryFetcher.prototype.getForceUpdate = function () {
return this.forceUpdate;
};
QueryFetcher.prototype.setForceUpdate = function (forceUpdate) {
this.forceUpdate = forceUpdate;
};
QueryFetcher.prototype.dispose = function () {
this.fetcher.dispose();
this.disposeSnapshot();
};
QueryFetcher.prototype.disposeSnapshot = function () {
this.snapshot = null;
if (this.rootSubscription) {
this.rootSubscription.dispose();
this.rootSubscription = null;
}
};
QueryFetcher.prototype.fetch = function (query, fetchPolicy, options, skip) {
var _this = this;
this.disposeSnapshot();
if (skip) {
this.fetcher.dispose();
return;
}
var onComplete = options.onComplete,
onResponse = options.onResponse;
var resolveUpdate = function (doUpdate) {
_this.resolveResult();
if (doUpdate) {
_this.forceUpdate();
}
};
var onNext = function (operation, snapshot, doUpdate) {
if (!_this.snapshot) {
_this.snapshot = snapshot;
_this.subscribe(snapshot);
resolveUpdate(doUpdate);
}
};
var complete = function (error, doUpdate) {
// doUpdate is False only if fetch is Sync
resolveUpdate(doUpdate);
onComplete && onComplete(error);
};
this.fetcher.fetch(this.environment, query, fetchPolicy, complete, onNext, onResponse, options.UNSTABLE_renderPolicy);
};
QueryFetcher.prototype.getQuery = function (gqlQuery, variables, networkCacheConfig) {
if (gqlQuery != this.gqlQuery || networkCacheConfig != this.cacheConfig || variables != this.variables || !areEqual(variables, this.variables)) {
this.variables = variables;
this.gqlQuery = gqlQuery;
this.cacheConfig = networkCacheConfig;
return createOperation(gqlQuery, variables, networkCacheConfig);
}
return this.query;
};
QueryFetcher.prototype.resolveEnvironment = function (environment) {
this.resolve(environment, this.gqlQuery, this.variables, this.options);
};
QueryFetcher.prototype.resolve = function (environment, gqlQuery, variables, options) {
var query = this.getQuery(gqlQuery, variables, options.networkCacheConfig);
var _a = options.fetchPolicy,
fetchPolicy = _a === void 0 ? defaultPolicy : _a,
fetchKey = options.fetchKey,
skip = options.skip;
this.options = options;
var diffQuery = !this.query || query.request.identifier !== this.query.request.identifier;
if (diffQuery || environment !== this.environment || fetchPolicy !== this.fetchPolicy || fetchKey !== this.fetchKey || skip !== this.skip) {
this.environment = environment;
this.query = query;
this.skip = skip;
this.fetchPolicy = fetchPolicy;
this.fetchKey = fetchKey;
this.fetch(query, fetchPolicy, options, skip);
this.resolveResult();
}
};
QueryFetcher.prototype.checkAndSuspense = function (suspense, useLazy) {
if (useLazy) {
this.setForceUpdate(emptyforceUpdate);
cache.set(this.query.request.identifier, this);
}
var result = this.fetcher.checkAndSuspense(suspense, useLazy);
if (useLazy) {
cache.delete(this.query.request.identifier);
}
return result;
};
QueryFetcher.prototype.getData = function () {
return this.result;
};
QueryFetcher.prototype.resolveResult = function () {
var _a = this.fetcher.getData(),
error = _a.error,
isLoading = _a.isLoading;
var snapshot = this.snapshot;
if (snapshot && snapshot.missingRequiredFields) {
relayRuntime.handlePotentialSnapshotErrors(this.environment, snapshot.missingRequiredFields, snapshot.relayResolverErrors);
}
this.result = {
retry: this.retry,
error: error,
data: snapshot ? snapshot.data : null,
isLoading: isLoading
};
};
QueryFetcher.prototype.subscribe = function (snapshot) {
var _this = this;
if (this.rootSubscription) {
this.rootSubscription.dispose();
}
this.rootSubscription = this.environment.subscribe(snapshot, function (snapshot) {
// Read from this._fetchOptions in case onDataChange() was lazily added.
_this.snapshot = snapshot; //this.error = null;
_this.resolveResult();
_this.forceUpdate();
});
};
return QueryFetcher;
}();
function useForceUpdate() {
var _a = React.useState([]),
forceUpdate = _a[1];
var mountState = React.useRef({
mounted: false,
pending: false
});
React.useEffect(function () {
mountState.current.mounted = true;
if (mountState.current.pending) {
mountState.current.pending = false;
forceUpdate([]);
}
return function () {
mountState.current = {
mounted: false,
pending: false
};
};
}, []);
var update = React.useCallback(function () {
if (mountState.current.mounted) {
forceUpdate([]);
} else {
mountState.current.pending = true;
}
}, [forceUpdate]);
return update;
}
function useRelayEnvironment() {
var environment = React__default.useContext(ReactRelayContext).environment;
return environment;
}
var useInternalQuery = function (gqlQuery, variables, options, suspense) {
var environment = useRelayEnvironment();
var forceUpdate = useForceUpdate();
var ref = React.useRef(undefined);
var maybeHiddenOrFastRefresh = React.useRef(false);
if (ref.current === null || ref.current === undefined || maybeHiddenOrFastRefresh.current == true) {
ref.current = {
queryFetcher: getOrCreateQueryFetcher(suspense, gqlQuery, variables, options.networkCacheConfig)
};
maybeHiddenOrFastRefresh.current = false;
}
React.useEffect(function () {
if (maybeHiddenOrFastRefresh.current == true) {
forceUpdate();
}
return function () {
ref.current.queryFetcher.dispose();
maybeHiddenOrFastRefresh.current = true;
}; // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
var queryFetcher = ref.current.queryFetcher;
queryFetcher.resolve(environment, gqlQuery, variables, options);
queryFetcher.checkAndSuspense(suspense, suspense);
queryFetcher.setForceUpdate(forceUpdate);
return queryFetcher.getData();
};
var useQuery = function (gqlQuery, variables, options) {
if (variables === void 0) {
variables = {};
}
if (options === void 0) {
options = {};
}
return useInternalQuery(gqlQuery, variables, options, false);
};
var useLazyLoadQuery = function (gqlQuery, variables, options) {
var _a;
if (variables === void 0) {
variables = {};
}
if (options === void 0) {
options = {};
}
options.networkCacheConfig = (_a = options.networkCacheConfig) !== null && _a !== void 0 ? _a : forceCache;
return useInternalQuery(gqlQuery, variables, options, true);
};
var emptyFunction = function () {
return undefined;
};
var internalLoadQuery = function (promise) {
if (promise === void 0) {
promise = false;
}
var queryFetcher = new QueryFetcher();
var dispose = function () {
queryFetcher.dispose();
queryFetcher.setForceUpdate(emptyFunction);
queryFetcher = new QueryFetcher();
};
var next = function (environment, gqlQuery, variables, options) {
var _a;
if (variables === void 0) {
variables = {};
}
if (options === void 0) {
options = {};
}
options.networkCacheConfig = (_a = options.networkCacheConfig) !== null && _a !== void 0 ? _a : forceCache;
queryFetcher.resolve(environment, gqlQuery, variables, options);
var toThrow = queryFetcher.checkAndSuspense();
return toThrow ? toThrow instanceof Error ? Promise.reject(toThrow) : toThrow : Promise.resolve();
};
var getValue = function (environment) {
queryFetcher.resolveEnvironment(environment);
queryFetcher.checkAndSuspense(promise);
return queryFetcher.getData();
};
var subscribe = function (callback) {
queryFetcher.setForceUpdate(callback);
return function () {
if (queryFetcher.getForceUpdate() === callback) {
queryFetcher.setForceUpdate(emptyFunction);
}
};
};
return {
next: next,
subscribe: subscribe,
getValue: getValue,
dispose: dispose
};
};
var loadLazyQuery = function () {
return internalLoadQuery(true);
};
var loadQuery = function () {
return internalLoadQuery(false);
};
var usePreloadedQuery = function (loadQuery) {
var forceUpdate = useForceUpdate();
var environment = useRelayEnvironment();
React.useEffect(function () {
return loadQuery.subscribe(forceUpdate); // eslint-disable-next-line react-hooks/exhaustive-deps
}, [loadQuery]);
return loadQuery.getValue(environment);
};
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function getStateFromConnection(direction, fragmentNode, connection) {
var _a, _b;
if (connection == null) {
return {
cursor: null,
hasMore: false
};
}
var _c = relayRuntime.ConnectionInterface.get(),
EDGES = _c.EDGES,
PAGE_INFO = _c.PAGE_INFO,
HAS_NEXT_PAGE = _c.HAS_NEXT_PAGE,
HAS_PREV_PAGE = _c.HAS_PREV_PAGE,
END_CURSOR = _c.END_CURSOR,
START_CURSOR = _c.START_CURSOR;
!(typeof connection === 'object') ? invariant(false, 'Relay: Expected connection in fragment `%s` to have been `null`, or ' + 'a plain object with %s and %s properties. Instead got `%s`.', fragmentNode.name, EDGES, PAGE_INFO, connection) : void 0;
var edges = connection[EDGES];
var pageInfo = connection[PAGE_INFO];
if (edges == null || pageInfo == null) {
return {
cursor: null,
hasMore: false
};
}
!Array.isArray(edges) ? invariant(false, 'Relay: Expected connection in fragment `%s` to have a plural `%s` field. ' + 'Instead got `%s`.', fragmentNode.name, EDGES, edges) : void 0;
!(typeof pageInfo === 'object') ? invariant(false, 'Relay: Expected connection in fragment `%s` to have a `%s` field. ' + 'Instead got `%s`.', fragmentNode.name, PAGE_INFO, pageInfo) : void 0;
var cursor = direction === 'forward' ? (_a = pageInfo[END_CURSOR]) !== null && _a !== void 0 ? _a : null : (_b = pageInfo[START_CURSOR]) !== null && _b !== void 0 ? _b : null;
!(cursor === null || typeof cursor === 'string') ? invariant(false, 'Relay: Expected page info for connection in fragment `%s` to have a ' + 'valid `%s`. Instead got `%s`.', fragmentNode.name, START_CURSOR, cursor) : void 0;
var hasMore;
if (direction === 'forward') {
hasMore = cursor != null && pageInfo[HAS_NEXT_PAGE] === true;
} else {
hasMore = cursor != null && pageInfo[HAS_PREV_PAGE] === true;
}
return {
cursor: cursor,
hasMore: hasMore
};
}
function getConnectionState(direction, fragmentNode, fragmentData, connectionPathInFragmentData) {
var connection = relayRuntime.getValueAtPath(fragmentData, connectionPathInFragmentData);
return getStateFromConnection(direction, fragmentNode, connection);
}
var getPromiseForActiveRequest = relayRuntime.__internal.getPromiseForActiveRequest; // eslint-disable-next-line @typescript-eslint/no-empty-function
function emptyVoid() {}
function lookupFragment(environment, selector) {
return selector.kind === 'PluralReaderSelector' ? selector.selectors.map(function (s) {
return environment.lookup(s);
}) : environment.lookup(selector);
}
function getFragmentResult(snapshot) {
var missData = isMissingData(snapshot);
if (Array.isArray(snapshot)) {
return {
snapshot: snapshot,
data: snapshot.map(function (s) {
return s.data;
}),
isMissingData: missData
};
}
return {
snapshot: snapshot,
data: snapshot.data,
isMissingData: missData
};
}
function isMissingData(snapshot) {
if (Array.isArray(snapshot)) {
return snapshot.some(function (s) {
return s.isMissingData;
});
}
return snapshot.isMissingData;
}
function _getAndSavePromiseForFragmentRequestInFlight(fragmentNode, fragmentOwner, env) {
var _a, _b;
var networkPromise = getPromiseForActiveRequest(env, fragmentOwner);
var pendingOperationName;
if (networkPromise != null) {
pendingOperationName = fragmentOwner.node.params.name;
} else {
var result = env.getOperationTracker().getPendingOperationsAffectingOwner(fragmentOwner);
var pendingOperations = result === null || result === void 0 ? void 0 : result.pendingOperations;
networkPromise = (_a = result === null || result === void 0 ? void 0 : result.promise) !== null && _a !== void 0 ? _a : null;
pendingOperationName = (_b = pendingOperations === null || pendingOperations === void 0 ? void 0 : pendingOperations.map(function (op) {
return op.node.params.name;
}).join(',')) !== null && _b !== void 0 ? _b : null;
}
if (!networkPromise) {
return null;
}
if (pendingOperationName == null || pendingOperationName.length === 0) {
pendingOperationName = 'Unknown pending operation';
} // When the Promise for the request resolves, we need to make sure to
// update the cache with the latest data available in the store before
// resolving the Promise
var fragmentName = fragmentNode.name;
var promiseDisplayName = pendingOperationName === fragmentName ? "Relay(".concat(pendingOperationName, ")") : "Relay(".concat(pendingOperationName, ":").concat(fragmentName, ")");
networkPromise.displayName = promiseDisplayName;
return networkPromise;
}
var FragmentResolver =
/** @class */
function () {
function FragmentResolver(name) {
var _this = this;
this.unmounted = false;
this.refetchable = false;
this.pagination = false;
this.refetch = function (variables, options) {
var _a, _b, _c, _d;
if (options === void 0) {
options = {};
}
var name = _this.name;
if (_this.unmounted === true) {
warning(false, 'Relay: Unexpected call to `refetch` on unmounted component for fragment ' + '`%s` in `%s`. It looks like some instances of your component are ' + 'still trying to fetch data but they already unmounted. ' + 'Please make sure you clear all timers, intervals, ' + 'async calls, etc that may trigger a fetch.', _this._fragment.name, name) ;
return {
dispose: emptyVoid
};
}
if (_this._selector == null) {
warning(false, 'Relay: Unexpected call to `refetch` while using a null fragment ref ' + 'for fragment `%s` in `%s`. When calling `refetch`, we expect ' + "initial fragment data to be non-null. Please make sure you're " + 'passing a valid fragment ref to `%s` before calling ' + '`refetch`, or make sure you pass all required variables to `refetch`.', _this._fragment.name, name, name) ;
}
var _e = relayRuntime.getRefetchMetadata(_this._fragment, name),
fragmentRefPathInResponse = _e.fragmentRefPathInResponse,
identifierInfo = _e.identifierInfo,
refetchableRequest = _e.refetchableRequest;
var fragmentData = _this.getData().data;
var identifierValue = (identifierInfo === null || identifierInfo === void 0 ? void 0 : identifierInfo.identifierField) != null && fragmentData != null && typeof fragmentData === 'object' ? fragmentData[identifierInfo.identifierField] : null;
var parentVariables;
var fragmentVariables;
if (_this._selector == null) {
parentVariables = {};
fragmentVariables = {};
} else if (_this._selector.kind === 'PluralReaderSelector') {
parentVariables = (_b = (_a = _this._selector.selectors[0]) === null || _a === void 0 ? void 0 : _a.owner.variables) !== null && _b !== void 0 ? _b : {};
fragmentVariables = (_d = (_c = _this._selector.selectors[0]) === null || _c === void 0 ? void 0 : _c.variables) !== null && _d !== void 0 ? _d : {};
} else {
parentVariables = _this._selector.owner.variables;
fragmentVariables = _this._selector.variables;
} // NOTE: A user of `useRefetchableFragment()` may pass a subset of
// all variables required by the fragment when calling `refetch()`.
// We fill in any variables not passed by the call to `refetch()` with the
// variables from the original parent fragment owner.
/* $FlowFixMe[cannot-spread-indexer] (>=0.123.0) This comment suppresses
* an error found when Flow v0.123.0 was deployed. To see the error
* delete this comment and run Flow. */
var refetchVariables = __assign(__assign(__assign({}, parentVariables), fragmentVariables), variables);
if (identifierInfo != null && !variables.hasOwnProperty(identifierInfo.identifierQueryVariableName)) {
// @refetchable fragments are guaranteed to have an `id` selection
// if the type is Node, implements Node, or is @fetchable. Double-check
// that there actually is a value at runtime.
if (typeof identifierValue !== 'string') {
warning(false, 'Relay: Expected result to have a string ' + '`%s` in order to refetch, got `%s`.', identifierInfo, identifierValue) ;
}
refetchVariables[identifierInfo.identifierQueryVariableName] = identifierValue;
}
var onNext = function (operation, snapshot, doUpdate) {
var fragmentRef = relayRuntime.getValueAtPath(snapshot.data, fragmentRefPathInResponse);
var isEquals = _this.isEqualsFragmentRef(_this._fragmentRefRefetch || _this._fragmentRef, fragmentRef);
var missData = isMissingData(snapshot); //fromStore && isMissingData(snapshot);
if (!isEquals || missData) {
_this._fragmentRefRefetch = fragmentRef;
_this._idfragmentrefetch = relayRuntime.getFragmentIdentifier(_this._fragment, fragmentRef);
_this.lookup(_this._fragment, fragmentRef);
_this.subscribe();
/*if (!missData) {
this.subscribe();
}*/
_this.resolverData.isMissingData = missData;
_this.resolverData.owner = operation.request;
doUpdate && _this.refreshHooks();
}
};
if (_this.pagination) {
_this.fetcherNext.dispose();
_this.fetcherPrevious.dispose();
}
var complete = function (error, doUpdate) {
doUpdate && _this.refreshHooks();
options.onComplete && options.onComplete(error);
};
var operation = createOperation(refetchableRequest, refetchVariables, forceCache);
var disposable = _this.fetcherRefecth.fetch(_this._environment, operation, options.fetchPolicy, complete, onNext, options.onResponse, options.UNSTABLE_renderPolicy);
_this.refreshHooks();
return disposable;
};
this.loadPrevious = function (count, options) {
return _this.loadMore('backward', count, options);
};
this.loadNext = function (count, options) {
return _this.loadMore('forward', count, options);
};
this.loadMore = function (direction, count, options) {
var _a;
if (options === void 0) {
options = {};
}
var onComplete = (_a = options.onComplete) !== null && _a !== void 0 ? _a : emptyVoid;
var fragmentData = _this.getData().data;
var emptyDispose = {
dispose: emptyVoid
};
var fetcher = direction === 'backward' ? _this.fetcherPrevious : _this.fetcherNext;
if (_this.unmounted === true) {
// Bail out and warn if we're trying to paginate after the component
// has unmounted
warning(false, 'Relay: Unexpected fetch on unmounted component for fragment ' + '`%s` in `%s`. It looks like some instances of your component are ' + 'still trying to fetch data but they already unmounted. ' + 'Please make sure you clear all timers, intervals, ' + 'async calls, etc that may trigger a fetch.', _this._fragment.name, _this.name) ;
return emptyDispose;
}
if (_this._selector == null) {
warning(false, 'Relay: Unexpected fetch while using a null fragment ref ' + 'for fragment `%s` in `%s`. When fetching more items, we expect ' + "initial fragment data to be non-null. Please make sure you're " + 'passing a valid fragment ref to `%s` before paginating.', _this._fragment.name, _this.name, _this.name) ;
onComplete(null);
return emptyDispose;
}
var isRequestActive = _this._environment.isRequestActive(_this._selector.owner.identifier);
if (isRequestActive || fetcher.getData().isLoading === true || fragmentData == null) {
onComplete(null);
return emptyDispose;
}
!(_this._selector != null && _this._selector.kind !== 'PluralReaderSelector') ? invariant(false, 'Relay: Expected to be able to find a non-plural fragment owner for ' + "fragment `%s` when using `%s`. If you're seeing this, " + 'this is likely a bug in Relay.', _this._fragment.name, _this.name) : void 0;
var _b = relayRuntime.getPaginationMetadata(_this._fragment, _this.name),
paginationRequest = _b.paginationRequest,
paginationMetadata = _b.paginationMetadata,
connectionPathInFragmentData = _b.connectionPathInFragmentData;
var identifierInfo = relayRuntime.getRefetchMetadata(_this._fragment, _this._fragment.name).identifierInfo;
var identifierValue = identifierInfo != null && fragmentData != null && typeof fragmentData === 'object' ? fragmentData[identifierInfo.identifierField] : null;
var parentVariables = _this._selector.owner.variables;
var fragmentVariables = _this._selector.variables;
var extraVariables = options.UNSTABLE_extraVariables;
var baseVariables = __assign(__assign({}, parentVariables), fragmentVariables);
var cursor = getConnectionState(direction, _this._fragment, fragmentData, connectionPathInFragmentData).cursor;
var paginationVariables = relayRuntime.getPaginationVariables(direction, count, cursor, baseVariables, __assign({}, extraVariables), paginationMetadata); // If the query needs an identifier value ('id' or similar) and one
// was not explicitly provided, read it from the fragment data.
if (identifierInfo != null) {
// @refetchable fragments are guaranteed to have an `id` selection
// if the type is Node, implements Node, or is @fetchable. Double-check
// that there actually is a value at runtime.
if (typeof identifierValue !== 'string') {
warning(false, 'Relay: Expected result to have a string ' + '`%s` in order to refetch, got `%s`.', identifierInfo, identifierValue) ;
}
paginationVariables[identifierInfo.identifierQueryVariableName] = identifierValue;
}
var complete = function (error, doUpdate) {
if (doUpdate) _this.refreshHooks();
onComplete(error);
};
var operation = createOperation(paginationRequest, paginationVariables, forceCache);
var disposable = fetcher.fetch(_this._environment, operation, undefined, //options?.fetchPolicy,
complete, emptyVoid, options.onResponse);
_this.refreshHooks();
return disposable;
};
this.name = name;
this.pagination = name === PAGINATION_NAME;
this.refetchable = name === REFETCHABLE_NAME || this.pagination;
if (this.refetchable) {
this.fetcherRefecth = fetchResolver({
doRetain: true
});
}
if (this.pagination) {
this.fetcherNext = fetchResolver({});
this.fetcherPrevious = fetchResolver({});
}
this.setForceUpdate();
this.refreshHooks = function () {
_this.resolveResult();
_this.forceUpdate();
};
}
FragmentResolver.prototype.setForceUpdate = function (forceUpdate) {
if (forceUpdate === void 0) {
forceUpdate = emptyVoid;
}
this.forceUpdate = forceUpdate;
};
FragmentResolver.prototype.subscribeResolve = function (subscribeResolve) {
if (this._subscribeResolve && this._subscribeResolve != subscribeResolve) {
subscribeResolve(this.getData());
}
this._subscribeResolve = subscribeResolve;
};
FragmentResolver.prototype.setUnmounted = function () {
this.unmounted = true;
};
FragmentResolver.prototype.isEqualsFragmentRef = function (prevFragment, fragmentRef) {
if (this._fragmentRef !== fragmentRef) {
var prevIDs = relayRuntime.getDataIDsFromFragment(this._fragment, prevFragment);
var nextIDs = relayRuntime.getDataIDsFromFragment(this._fragment, fragmentRef);
if (!areEqual(prevIDs, nextIDs) || !areEqual(this.getFragmentVariables(fragmentRef), this.getFragmentVariables(prevFragment))) {
return false;
}
}
return true;
};
FragmentResolver.prototype.dispose = function () {
this.unsubscribe();
this.fetcherNext && this.fetcherNext.dispose();
this.fetcherPrevious && this.fetcherPrevious.dispose();
this._idfragmentrefetch = null;
this._fragmentRefRefetch = null;
this.fetcherRefecth && this.fetcherRefecth.dispose();
};
FragmentResolver.prototype.getFragmentVariables = function (fRef) {
if (fRef === void 0) {
fRef = this._fragmentRef;
}
return relayRuntime.getVariablesFromFragment(this._fragment, fRef);
};
FragmentResolver.prototype.resolve = function (environment, idfragment, fragment, fragmentRef) {
if (!this.resolverData || this._environment !== environment || idfragment !== this._idfragment && (!this._idfragmentrefetch || this._idfragmentrefetch && idfragment !== this._idfragmentrefetch)) {
this._fragment = fragment;
this._fragmentRef = fragmentRef;
this._idfragment = idfragment;
this._selector = null;
this.dispose();
this._environment = environment;
this.lookup(fragment, this._fragmentRef);
this.resolveResult();
}
};
FragmentResolver.prototype.lookup = function (fragment, fragmentRef) {
if (fragmentRef == null) {
this.resolverData = {
data: null
};
return;
}
var isPlural = fragment.metadata && fragment.metadata.plural && fragment.metadata.plural === true;
if (isPlural) {
if (fragmentRef.length === 0) {
this.resolverData = {
data: []
};
return;
}
}
this._selector = relayRuntime.getSelector(fragment, fragmentRef);
var snapshot = lookupFragment(this._environment, this._selector);
this.resolverData = getFragmentResult(snapshot);
var owner = this._selector ? this._selector.kind === 'PluralReaderSelector' ? this._selector.selectors[0].owner : this._selector.owner : null;
this.resolverData.owner = owner; //this.subscribe();
};
FragmentResolver.prototype.checkAndSuspense = function (suspense) {
var _this = this;
var _a;
if (suspense && this.resolverData.isMissingData && this.resolverData.owner) {
var fragmentOwner = this.resolverData.owner;
var networkPromise = _getAndSavePromiseForFragmentRequestInFlight(this._fragment, fragmentOwner, this._environment);
var parentQueryName = (_a = fragmentOwner.node.params.name) !== null && _a !== void 0 ? _a : 'Unknown Parent Query';
if (networkPromise != null) {
// When the Promise for the request resolves, we need to make sure to
// update the cache with the latest data available in the store before
// resolving the Promise
var promise = networkPromise.then(function () {
if (_this._idfragmentrefetch) {
_this.resolveResult();
} else {
_this._idfragment = null;
_this.dispose();
} //;
}).catch(function (_error) {
if (_this._idfragmentrefetch) {
_this.resolveResult();
} else {
_this._idfragment = null;
_this.dispose();
}
}); // $FlowExpectedError[prop-missing] Expando to annotate Promises.
promise.displayName = 'Relay(' + parentQueryName + ')';
this.unsubscribe();
this.refreshHooks = emptyVoid;
throw promise;
}
warning(false, 'Relay: Tried reading fragment `%s` declared in ' + '`%s`, but it has missing data and its parent query `%s` is not ' + 'being fetched.\n' + 'This might be fixed by by re-running the Relay Compiler. ' + ' Otherwise, make sure of the following:\n' + '* You are correctly fetching `%s` if you are using a ' + '"store-only" `fetchPolicy`.\n' + "* Other queries aren't accidentally fetching and overwriting " + 'the data for this fragment.\n' + '* Any related mutations or subscriptions are fetching all of ' + 'the data for this fragment.\n' + "* Any related store updaters aren't accidentally deleting " + 'data for this fragment.', this._fragment.name, this.name, parentQueryName, parentQueryName) ;
}
this.fetcherRefecth && this.fetcherRefecth.checkAndSuspense(suspense);
};
FragmentResolver.prototype.getData = function () {
return this.result;
};
FragmentResolver.prototype.resolveResult = function () {
var data = this.resolverData.data;
if (this.refetchable || this.pagination) {
var _a = this.fetcherRefecth.getData(),
isLoading = _a.isLoading,
error = _a.error;
var refetch = this.refetch;
if (!this.pagination) {
// useRefetchable
{
relayRuntime.getRefetchMetadata(this._fragment, this.name);
}
this.result = {
data: data,
isLoading: isLoading,
error: error,
refetch: refetch
};
} else {
// usePagination
var connectionPathInFragmentData = relayRuntime.getPaginationMetadata(this._fragment, this.name).connectionPathInFragmentData;
var connection = relayRuntime.getValueAtPath(data, connectionPathInFragmentData);
var hasNext = getStateFromConnection('forward', this._fragment, connection).hasMore;
var hasPrevious = getStateFromConnection('backward', this._fragment, connection).hasMore;
var _b = this.fetcherNext.getData(),
isLoadingNext = _b.isLoading,
errorNext = _b.error;
var _c = this.fetcherPrevious.getData(),
isLoadingPrevious = _c.isLoading,
errorPrevious = _c.error;
this.result = {
data: data,
hasNext: hasNext,
isLoadingNext: isLoadingNext,
hasPrevious: hasPrevious,
isLoadingPrevious: isLoadingPrevious,
isLoading: isLoading,
errorNext: errorNext,
errorPrevious: errorPrevious,
error: error,
refetch: refetch,
loadNext: this.loadNext,
loadPrevious: this.loadPrevious
};
}
} else {
// useFragment
this.result = data;
}
var snap = this.resolverData.snapshot;
if (snap) {
this._throwOrLogErrorsInSnapshot(snap);
}
this._subscribeResolve && this._subscribeResolve(this.result);
};
FragmentResolver.prototype.unsubscribe = function () {
this._disposable && this._disposable.dispose();
};
FragmentResolver.prototype.subscribe = function () {
var _this = this;
var environment = this._environment;
var renderedSnapshot = this.resolverData.snapshot;
this.unsubscribe();
var dataSubscriptions = [];
if (renderedSnapshot) {
if (Array.isArray(renderedSnapshot)) {
renderedSnapshot.forEach(function (snapshot, idx) {
dataSubscriptions.push(environment.subscribe(snapshot, function (latestSnapshot) {
_this.resolverData.snapshot[idx] = latestSnapshot;
_this.resolverData.data[idx] = latestSnapshot.data;
_this.resolverData.isMissingData = isMissingData(_this.resolverData.snapshot);
_this.refreshHooks();
}));
});
} else {
dataSubscriptions.push(environment.subscribe(renderedSnapshot, function (latestSnapshot) {
_this.resolverData = getFragmentResult(latestSnapshot);
_this.refreshHooks();
}));
}
}
this._disposable = {
dispose: function () {
dataSubscriptions.map(function (s) {
return s.dispose();
});
_this._disposable = undefined;
}
};
};
FragmentResolver.prototype._throwOrLogErrorsInSnapshot = function (snapshot) {
var _this = this;
if (Array.isArray(snapshot)) {
snapshot.forEach(function (s) {
if (s.missingRequiredFields) {
relayRuntime.handlePotentialSnapshotErrors(_this._environment, s.missingRequiredFields, s.relayResolverErrors);
}
});
} else {
if (snapshot.missingRequiredFields) {
relayRuntime.handlePotentialSnapshotErrors(this._environment, snapshot.missingRequiredFields, snapshot.relayResolverErrors);
}
}
};
return FragmentResolver;
}();
function useOssFragment(fragmentNode, fragmentRef, suspense, name, subscribeResolve) {
var environment = useRelayEnvironment();
var forceUpdate = useForceUpdate();
var ref = React.useRef(null);
var maybeHiddenOrFastRefresh = React.useRef(false);
if (ref.current === null || ref.current === undefined || maybeHiddenOrFastRefresh.current) {
ref.current = {
resolver: new FragmentResolver(name)
};
maybeHiddenOrFastRefresh.current = false;
}
var resolver = ref.current.resolver;
React.useEffect(function () {
if (maybeHiddenOrFastRefresh.current == true) {
forceUpdate();
}
return function () {
ref.current.resolver.setUnmounted();
maybeHiddenOrFastRefresh.current = true;
}; // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
React.useEffect(function () {
return function () {
resolver.dispose();
};
}, [resolver]);
var fragment = React.useMemo(function () {
return relayRuntime.getFragment(fragmentNode);
}, [fragmentNode]);
var idfragment = React.useMemo(function () {
return relayRuntime.getFragmentIdentifier(fragment, fragmentRef);
}, [fragment, fragmentRef]);
React.useEffect(function () {
resolver.subscribe();
return function () {
resolver.unsubscribe();
};
}, [resolver, idfragment, environment]);
resolver.subscribeResolve(subscribeResolve);
resolver.resolve(environment, idfragment, fragment, fragmentRef);
if (subscribeResolve) {
return;
}
resolver.checkAndSuspense(suspense);
resolver.setForceUpdate(forceUpdate);
var data = resolver.getData();
{
if (fragmentRef != null && (data === undefined || Array.isArray(data) && data.length > 0 && data.every(function (data) {
return data === undefined;
}))) {
warning(false, 'Relay: Expected to have been able to read non-null data for ' + 'fragment `%s` declared in ' + '`%s`, since fragment reference was non-null. ' + "Make sure that that `%s`'s parent isn't " + 'holding on to and/or passing a fragment reference for data that ' + 'has been deleted.', fragment, name, name) ;
}
}
return [data, resolver];
}
function useFragment(fragmentNode, fragmentRef) {
var data = useOssFragment(fragmentNode, fragmentRef, false, FRAGMENT_NAME)[0];
return data;
}
function useSuspenseFragment(fragmentNode, fragmentRef) {
var data = useOssFragment(fragmentNode, fragmentRef, true, FRAGMENT_NAME)[0];
return data;
}
function useFragmentSubscription(fragmentNode, fragmentRef, callback) {
useOssFragment(fragmentNode, fragmentRef, false, FRAGMENT_NAME, callback);
}
var useCallback = React__default.useCallback,
useState = React__default.useState;
function useMutation(mutation, userConfig,
/** if not provided, the context environment will be used. */
environment) {
if (userConfig === void 0) {
userConfig = {};
}
var _a = useState({
loading: false,
data: null,
error: null
}),
state = _a[0],
setState = _a[1];
var isMounted = useMounted();
var relayEnvironment = useRelayEnvironment();
var resolvedEnvironment = environment || relayEnvironment;
var configs = userConfig.configs,
variables = userConfig.variables,
uploadables = userConfig.uploadables,
onCompleted = userConfig.onCompleted,
onError = userConfig.onError,
optimisticUpdater = userConfig.optimisticUpdater,
optimisticResponse = userConfig.optimisticResponse,
updater = userConfig.updater;
var mutate = useCallback(function (config) {
var mergedConfig = __assign({
configs: configs,
variables: variables,
uploadables: uploadables,
onCompleted: onCompleted,
onError: onError,
optimisticUpdater: optimisticUpdater,
optimisticResponse: optimisticResponse,
updater: updater
}, config);
!mergedConfig.variables ? invariant(false, 'you must specify variables') : void 0;
if (isMounted()) {
setState({
loading: true,
data: mergedConfig.optimisticResponse,
error: null
});
}
return new Promise(function (resolve, reject) {
function handleError(error) {
if (isMounted()) {
setState({
loading: false,
data: null,
error: error
});
}
if (mergedConfig.onError) {
mergedConfig.onError(error);
resolve(null);
} else {
reject(error);
}
}
relayRuntime.commitMutation(resolvedEnvironment, __assign(__assign({}, mergedConfig), {
mutation: mutation,
variables: mergedConfig.variables,
onCompleted: function (response, errors) {
if (errors) {
// FIXME: This isn't right. onError expects a single error.
handleError(errors);
return;
}
if (isMounted()) {
setState({
loading: false,
data: response,
error: null
});
}
if (mergedConfig.onCompleted) {
mergedConfig.onCompleted(response);
}
resolve(response);
},
onError: handleError
}));
});
}, [resolvedEnvironment, configs, mutation, variables, uploadables, onCompleted, onError, optimisticUpdater, optimisticResponse, updater, isMounted]);
return [mutate, state];
}
function useSubscription(config, opts) {
var environment = useRelayEnvironment();
var skip = opts && opts.skip;
React.useEffect(function () {
if (skip) {
return;
}
var dispose = relayRuntime.requestSubscription(environment, config).dispose;
return dispose;
}, [environment, config, skip]);
}
function usePagination(fragmentNode, fragmentRef) {
var data = useOssFragment(fragmentNode, fragmentRef, false, PAGINATION_NAME)[0];
return data;
}
function usePaginationFragment(fragmentNode, fragmentRef) {
var data = useOssFragment(fragmentNode, fragmentRef, true, PAGINATION_NAME)[0];
return data;
}
function usePaginationSubscription(fragmentNode, fragmentRef, callback) {
useOssFragment(fragmentNode, fragmentRef, false, PAGINATION_NAME, callback);
}
function useRefetchable(fragmentInput, fragmentRef) {
var data = useOssFragment(fragmentInput, fragmentRef, false, REF