found-relay
Version:
Relay integration for found
183 lines (145 loc) • 6.54 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _awaitAsyncGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/awaitAsyncGenerator"));
var _wrapAsyncGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/wrapAsyncGenerator"));
var _dequal = require("dequal");
var _ResolverUtils = require("found/ResolverUtils");
var _isPromise = _interopRequireDefault(require("is-promise"));
var _react = _interopRequireDefault(require("react"));
var _QuerySubscription = _interopRequireDefault(require("./QuerySubscription"));
var _ReadyStateRenderer = _interopRequireDefault(require("./ReadyStateRenderer"));
var _renderElement = _interopRequireDefault(require("./renderElement"));
class Resolver {
constructor(environment) {
this.environment = environment;
this.lastQuerySubscriptions = [];
}
createQuerySubscription(options) {
return new _QuerySubscription.default(options);
}
resolveElements(match) {
var _this = this;
return (0, _wrapAsyncGenerator2.default)(function* () {
const routeMatches = (0, _ResolverUtils.getRouteMatches)(match);
const Components = (0, _ResolverUtils.getComponents)(routeMatches);
const queries = (0, _ResolverUtils.getRouteValues)(routeMatches, route => route.getQuery, route => route.query);
const cacheConfigs = (0, _ResolverUtils.getRouteValues)(routeMatches, route => route.getCacheConfig, route => route.cacheConfig);
const fetchPolicies = (0, _ResolverUtils.getRouteValues)(routeMatches, route => route.getFetchPolicy, route => route.fetchPolicy);
const routeVariables = _this.getRouteVariables(match, routeMatches);
const querySubscriptions = _this.updateQuerySubscriptions(queries, routeVariables, cacheConfigs, fetchPolicies);
const fetches = querySubscriptions.map(querySubscription => querySubscription == null ? void 0 : querySubscription.fetch());
const earlyComponents = Components.some(_isPromise.default) ? yield (0, _awaitAsyncGenerator2.default)(Promise.all(Components.map(_ResolverUtils.checkResolved))) : Components;
const earlyData = yield (0, _awaitAsyncGenerator2.default)(Promise.all(fetches.map(_ResolverUtils.checkResolved)));
let fetchedComponents;
if (!earlyComponents.every(_ResolverUtils.isResolved) || !earlyData.every(_ResolverUtils.isResolved)) {
const pendingElements = _this.createElements(routeMatches, earlyComponents, querySubscriptions, false);
yield pendingElements.every(element => element !== undefined) ? pendingElements : undefined;
fetchedComponents = yield (0, _awaitAsyncGenerator2.default)(Promise.all(Components));
yield (0, _awaitAsyncGenerator2.default)(Promise.all(fetches));
} else {
fetchedComponents = earlyComponents;
}
yield _this.createElements(routeMatches, fetchedComponents, querySubscriptions, true);
})();
}
getRouteVariables(match, routeMatches) {
return (0, _ResolverUtils.accumulateRouteValues)(routeMatches, match.routeIndices, (variables, routeMatch) => {
const {
route,
routeParams
} = routeMatch; // We need to always run this to make sure we don't miss route params.
let nextVariables = Object.assign({}, variables, routeParams);
if (route.prepareVariables) {
nextVariables = route.prepareVariables(nextVariables, routeMatch);
}
return nextVariables;
}, null);
}
updateQuerySubscriptions(queries, routeVariables, cacheConfigs, fetchPolicies) {
const querySubscriptions = queries.map((query, i) => {
if (!query) {
return null;
}
const variables = routeVariables[i];
const cacheConfig = cacheConfigs[i];
const fetchPolicy = fetchPolicies[i];
const lastQuerySubscription = this.lastQuerySubscriptions[i]; // Match the logic in <QueryRenderer> for not refetching.
if (lastQuerySubscription && lastQuerySubscription.query === query && (0, _dequal.dequal)(lastQuerySubscription.variables, variables) && (0, _dequal.dequal)(lastQuerySubscription.cacheConfig, cacheConfig)) {
this.lastQuerySubscriptions[i] = null;
lastQuerySubscription.fetchPolicy = fetchPolicy;
return lastQuerySubscription;
}
return this.createQuerySubscription({
environment: this.environment,
query,
variables,
cacheConfig,
fetchPolicy
});
});
this.lastQuerySubscriptions.forEach(querySubscription => {
if (querySubscription) {
querySubscription.dispose();
}
});
this.lastQuerySubscriptions = [...querySubscriptions];
return querySubscriptions;
}
createElements(routeMatches, Components, querySubscriptions, fetched) {
return routeMatches.map((match, i) => {
const {
route,
router
} = match;
const Component = Components[i];
const querySubscription = querySubscriptions[i];
const isComponentResolved = (0, _ResolverUtils.isResolved)(Component); // Handle non-Relay routes.
if (!querySubscription) {
if (route.render) {
return route.render({
match,
Component: isComponentResolved ? Component : null,
props: {
match,
router
}
});
}
if (!isComponentResolved) {
return undefined;
}
return Component ? /*#__PURE__*/_react.default.createElement(Component, {
match: match,
router: router
}) : null;
}
const resolvedComponent = isComponentResolved ? Component : null;
const hasComponent = Component != null;
const element = (0, _renderElement.default)({
match,
Component: resolvedComponent,
isComponentResolved,
hasComponent,
querySubscription,
resolving: true
});
if (!element) {
return element;
}
return routeChildren => /*#__PURE__*/_react.default.createElement(_ReadyStateRenderer.default, {
match: match,
Component: resolvedComponent,
isComponentResolved: isComponentResolved,
hasComponent: hasComponent,
element: element,
routeChildren: routeChildren,
querySubscription: querySubscription,
fetched: fetched
});
});
}
}
exports.default = Resolver;
module.exports = exports.default;
;