react-relay 11.0.1 → 13.0.0-rc.1
Sign up to get free protection for your applications and to get access to all the features.
- package/ReactRelayContext.js +1 -1
- package/ReactRelayContext.js.flow +2 -3
- package/ReactRelayFragmentContainer.js.flow +24 -24
- package/ReactRelayFragmentMockRenderer.js.flow +1 -1
- package/ReactRelayLocalQueryRenderer.js.flow +6 -7
- package/ReactRelayPaginationContainer.js.flow +111 -58
- package/ReactRelayQueryFetcher.js.flow +9 -10
- package/ReactRelayQueryRenderer.js.flow +115 -81
- package/ReactRelayRefetchContainer.js.flow +41 -38
- package/ReactRelayTestMocker.js.flow +16 -14
- package/ReactRelayTypes.js.flow +10 -10
- package/RelayContext.js.flow +3 -3
- package/__flowtests__/ReactRelayFragmentContainer-flowtest.js.flow +1 -2
- package/__flowtests__/ReactRelayPaginationContainer-flowtest.js.flow +11 -7
- package/__flowtests__/ReactRelayRefetchContainer-flowtest.js.flow +10 -6
- package/__flowtests__/RelayModern-flowtest.js.flow +78 -46
- package/__flowtests__/RelayModernFlowtest_badref.graphql.js.flow +5 -4
- package/__flowtests__/RelayModernFlowtest_notref.graphql.js.flow +5 -4
- package/__flowtests__/RelayModernFlowtest_user.graphql.js.flow +4 -3
- package/__flowtests__/RelayModernFlowtest_users.graphql.js.flow +4 -3
- package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer.graphql.js.flow +72 -0
- package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer2.graphql.js.flow +72 -0
- package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtestQuery.graphql.js.flow +227 -0
- package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtest_viewer.graphql.js.flow +164 -0
- package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtestQuery.graphql.js.flow +227 -0
- package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtest_viewer.graphql.js.flow +164 -0
- package/__flowtests__/__generated__/RelayModernFlowtest_badref.graphql.js.flow +66 -0
- package/__flowtests__/__generated__/RelayModernFlowtest_notref.graphql.js.flow +66 -0
- package/__flowtests__/__generated__/RelayModernFlowtest_user.graphql.js.flow +59 -0
- package/__flowtests__/__generated__/RelayModernFlowtest_users.graphql.js.flow +61 -0
- package/assertFragmentMap.js.flow +2 -2
- package/buildReactRelayContainer.js.flow +15 -12
- package/getRootVariablesForFragments.js.flow +2 -4
- package/hooks.js +1 -1
- package/hooks.js.flow +5 -6
- package/index.js +1 -1
- package/index.js.flow +6 -7
- package/jest-react/enqueueTask.js.flow +56 -0
- package/jest-react/index.js.flow +12 -0
- package/jest-react/internalAct.js.flow +139 -0
- package/legacy.js +1 -1
- package/lib/ReactRelayFragmentContainer.js +21 -15
- package/lib/ReactRelayFragmentMockRenderer.js +2 -2
- package/lib/ReactRelayLocalQueryRenderer.js +7 -8
- package/lib/ReactRelayPaginationContainer.js +96 -38
- package/lib/ReactRelayQueryFetcher.js +3 -3
- package/lib/ReactRelayQueryRenderer.js +86 -53
- package/lib/ReactRelayRefetchContainer.js +38 -25
- package/lib/ReactRelayTestMocker.js +8 -9
- package/lib/RelayContext.js +3 -2
- package/lib/assertFragmentMap.js +3 -2
- package/lib/buildReactRelayContainer.js +14 -11
- package/lib/getRootVariablesForFragments.js +1 -2
- package/lib/hooks.js +5 -5
- package/lib/index.js +7 -7
- package/lib/jest-react/enqueueTask.js +53 -0
- package/lib/jest-react/index.js +13 -0
- package/lib/jest-react/internalAct.js +116 -0
- package/lib/multi-actor/ActorChange.js +30 -0
- package/lib/multi-actor/index.js +11 -0
- package/lib/multi-actor/useRelayActorEnvironment.js +29 -0
- package/lib/relay-hooks/EntryPointContainer.react.js +3 -3
- package/lib/relay-hooks/FragmentResource.js +347 -92
- package/lib/relay-hooks/LRUCache.js +1 -1
- package/lib/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js +4 -4
- package/lib/relay-hooks/MatchContainer.js +1 -1
- package/lib/relay-hooks/QueryResource.js +172 -29
- package/lib/relay-hooks/RelayEnvironmentProvider.js +5 -3
- package/lib/relay-hooks/SuspenseResource.js +130 -0
- package/lib/relay-hooks/loadQuery.js +42 -20
- package/lib/relay-hooks/preloadQuery_DEPRECATED.js +24 -15
- package/lib/relay-hooks/useBlockingPaginationFragment.js +4 -5
- package/lib/relay-hooks/useEntryPointLoader.js +2 -2
- package/lib/relay-hooks/useFetchTrackingRef.js +2 -1
- package/lib/relay-hooks/useFragment.js +8 -7
- package/lib/relay-hooks/useFragmentNode.js +4 -4
- package/lib/relay-hooks/useIsOperationNodeActive.js +3 -3
- package/lib/relay-hooks/useLazyLoadQuery.js +3 -3
- package/lib/relay-hooks/useLazyLoadQueryNode.js +10 -4
- package/lib/relay-hooks/useLoadMoreFunction.js +8 -12
- package/lib/relay-hooks/useMemoOperationDescriptor.js +2 -2
- package/lib/relay-hooks/useMemoVariables.js +2 -2
- package/lib/relay-hooks/useMutation.js +17 -6
- package/lib/relay-hooks/usePaginationFragment.js +2 -3
- package/lib/relay-hooks/usePreloadedQuery.js +8 -7
- package/lib/relay-hooks/useQueryLoader.js +30 -10
- package/lib/relay-hooks/useRefetchableFragmentNode.js +13 -17
- package/lib/relay-hooks/useRelayEnvironment.js +3 -3
- package/lib/relay-hooks/useStaticFragmentNodeWarning.js +2 -2
- package/lib/relay-hooks/useSubscribeToInvalidationState.js +2 -1
- package/lib/relay-hooks/useSubscription.js +10 -7
- package/multi-actor/ActorChange.js.flow +58 -0
- package/multi-actor/index.js.flow +14 -0
- package/multi-actor/useRelayActorEnvironment.js.flow +49 -0
- package/package.json +3 -2
- package/react-relay-hooks.js +2 -2
- package/react-relay-hooks.min.js +2 -2
- package/react-relay-legacy.js +2 -2
- package/react-relay-legacy.min.js +2 -2
- package/react-relay.js +2 -2
- package/react-relay.min.js +2 -2
- package/relay-hooks/EntryPointContainer.react.js.flow +8 -15
- package/relay-hooks/EntryPointTypes.flow.js.flow +24 -25
- package/relay-hooks/FragmentResource.js.flow +368 -94
- package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +32 -46
- package/relay-hooks/MatchContainer.js.flow +3 -2
- package/relay-hooks/QueryResource.js.flow +216 -25
- package/relay-hooks/RelayEnvironmentProvider.js.flow +14 -4
- package/relay-hooks/SuspenseResource.js.flow +115 -0
- package/relay-hooks/__flowtests__/EntryPointTypes/EntryPointElementConfig-flowtest.js.flow +4 -3
- package/relay-hooks/__flowtests__/EntryPointTypes/NestedEntrypoints-flowtest.js.flow +1 -1
- package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +10 -9
- package/relay-hooks/__flowtests__/useFragment-flowtest.js.flow +8 -7
- package/relay-hooks/__flowtests__/usePaginationFragment-flowtest.js.flow +10 -9
- package/relay-hooks/__flowtests__/useRefetchableFragment-flowtest.js.flow +10 -9
- package/relay-hooks/__flowtests__/utils.js.flow +8 -12
- package/relay-hooks/loadEntryPoint.js.flow +6 -12
- package/relay-hooks/loadQuery.js.flow +49 -31
- package/relay-hooks/preloadQuery_DEPRECATED.js.flow +30 -21
- package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +6 -12
- package/relay-hooks/useBlockingPaginationFragment.js.flow +13 -11
- package/relay-hooks/useEntryPointLoader.js.flow +7 -10
- package/relay-hooks/useFetchTrackingRef.js.flow +2 -2
- package/relay-hooks/useFragment.js.flow +26 -46
- package/relay-hooks/useFragmentNode.js.flow +5 -7
- package/relay-hooks/useIsOperationNodeActive.js.flow +3 -5
- package/relay-hooks/useIsParentQueryActive.js.flow +3 -4
- package/relay-hooks/useLazyLoadQuery.js.flow +9 -10
- package/relay-hooks/useLazyLoadQueryNode.js.flow +19 -13
- package/relay-hooks/useLoadMoreFunction.js.flow +20 -29
- package/relay-hooks/useMemoOperationDescriptor.js.flow +5 -7
- package/relay-hooks/useMemoVariables.js.flow +6 -6
- package/relay-hooks/useMutation.js.flow +26 -26
- package/relay-hooks/usePaginationFragment.js.flow +38 -44
- package/relay-hooks/usePreloadedQuery.js.flow +18 -14
- package/relay-hooks/useQueryLoader.js.flow +41 -22
- package/relay-hooks/useRefetchableFragment.js.flow +7 -8
- package/relay-hooks/useRefetchableFragmentNode.js.flow +24 -32
- package/relay-hooks/useRelayEnvironment.js.flow +2 -4
- package/relay-hooks/useStaticFragmentNodeWarning.js.flow +2 -3
- package/relay-hooks/useSubscribeToInvalidationState.js.flow +3 -6
- package/relay-hooks/useSubscription.js.flow +20 -10
- package/lib/relay-hooks/getPaginationMetadata.js +0 -41
- package/lib/relay-hooks/getPaginationVariables.js +0 -67
- package/lib/relay-hooks/getRefetchMetadata.js +0 -36
- package/lib/relay-hooks/getValueAtPath.js +0 -51
- package/relay-hooks/getPaginationMetadata.js.flow +0 -74
- package/relay-hooks/getPaginationVariables.js.flow +0 -110
- package/relay-hooks/getRefetchMetadata.js.flow +0 -80
- package/relay-hooks/getValueAtPath.js.flow +0 -46
@@ -15,21 +15,32 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
15
15
|
|
16
16
|
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
|
17
17
|
|
18
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
19
|
+
|
18
20
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
19
21
|
|
20
22
|
var LRUCache = require('./LRUCache');
|
21
23
|
|
22
|
-
var
|
24
|
+
var _require = require('./QueryResource'),
|
25
|
+
getQueryResourceForEnvironment = _require.getQueryResourceForEnvironment;
|
26
|
+
|
27
|
+
var SuspenseResource = require('./SuspenseResource');
|
23
28
|
|
24
|
-
var
|
29
|
+
var invariant = require('invariant');
|
25
30
|
|
26
|
-
var
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
var _require2 = require('relay-runtime'),
|
32
|
+
RelayFeatureFlags = _require2.RelayFeatureFlags,
|
33
|
+
_require2$__internal = _require2.__internal,
|
34
|
+
fetchQuery = _require2$__internal.fetchQuery,
|
35
|
+
getPromiseForActiveRequest = _require2$__internal.getPromiseForActiveRequest,
|
36
|
+
createOperationDescriptor = _require2.createOperationDescriptor,
|
37
|
+
getFragmentIdentifier = _require2.getFragmentIdentifier,
|
38
|
+
getPendingOperationsForFragment = _require2.getPendingOperationsForFragment,
|
39
|
+
getSelector = _require2.getSelector,
|
40
|
+
getVariablesFromFragment = _require2.getVariablesFromFragment,
|
41
|
+
isPromise = _require2.isPromise,
|
42
|
+
recycleNodesInto = _require2.recycleNodesInto,
|
43
|
+
reportMissingRequiredFields = _require2.reportMissingRequiredFields;
|
33
44
|
|
34
45
|
var WEAKMAP_SUPPORTED = typeof WeakMap === 'function';
|
35
46
|
// TODO: Fix to not rely on LRU. If the number of active fragments exceeds this
|
@@ -49,32 +60,133 @@ function isMissingData(snapshot) {
|
|
49
60
|
return snapshot.isMissingData;
|
50
61
|
}
|
51
62
|
|
52
|
-
function
|
63
|
+
function hasMissingClientEdges(snapshot) {
|
64
|
+
var _snapshot$missingClie, _snapshot$missingClie2;
|
65
|
+
|
66
|
+
if (Array.isArray(snapshot)) {
|
67
|
+
return snapshot.some(function (s) {
|
68
|
+
var _s$missingClientEdges, _s$missingClientEdges2;
|
69
|
+
|
70
|
+
return ((_s$missingClientEdges = (_s$missingClientEdges2 = s.missingClientEdges) === null || _s$missingClientEdges2 === void 0 ? void 0 : _s$missingClientEdges2.length) !== null && _s$missingClientEdges !== void 0 ? _s$missingClientEdges : 0) > 0;
|
71
|
+
});
|
72
|
+
}
|
73
|
+
|
74
|
+
return ((_snapshot$missingClie = (_snapshot$missingClie2 = snapshot.missingClientEdges) === null || _snapshot$missingClie2 === void 0 ? void 0 : _snapshot$missingClie2.length) !== null && _snapshot$missingClie !== void 0 ? _snapshot$missingClie : 0) > 0;
|
75
|
+
}
|
76
|
+
|
77
|
+
function singularOrPluralForEach(snapshot, f) {
|
78
|
+
if (Array.isArray(snapshot)) {
|
79
|
+
snapshot.forEach(f);
|
80
|
+
} else {
|
81
|
+
f(snapshot);
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
function getFragmentResult(cacheKey, snapshot, storeEpoch) {
|
53
86
|
if (Array.isArray(snapshot)) {
|
54
87
|
return {
|
55
88
|
cacheKey: cacheKey,
|
56
89
|
snapshot: snapshot,
|
57
90
|
data: snapshot.map(function (s) {
|
58
91
|
return s.data;
|
59
|
-
})
|
92
|
+
}),
|
93
|
+
isMissingData: isMissingData(snapshot),
|
94
|
+
storeEpoch: storeEpoch
|
60
95
|
};
|
61
96
|
}
|
62
97
|
|
63
98
|
return {
|
64
99
|
cacheKey: cacheKey,
|
65
100
|
snapshot: snapshot,
|
66
|
-
data: snapshot.data
|
101
|
+
data: snapshot.data,
|
102
|
+
isMissingData: isMissingData(snapshot),
|
103
|
+
storeEpoch: storeEpoch
|
67
104
|
};
|
68
105
|
}
|
106
|
+
/**
|
107
|
+
* The purpose of this cache is to allow information to be passed from an
|
108
|
+
* initial read which suspends through to the commit that follows a subsequent
|
109
|
+
* successful read. Specifically, the QueryResource result for the data fetch
|
110
|
+
* is passed through so that that query can be retained on commit.
|
111
|
+
*/
|
69
112
|
|
70
|
-
|
71
|
-
|
72
|
-
|
113
|
+
|
114
|
+
var ClientEdgeQueryResultsCache = /*#__PURE__*/function () {
|
115
|
+
function ClientEdgeQueryResultsCache(environment) {
|
116
|
+
(0, _defineProperty2["default"])(this, "_cache", new Map());
|
117
|
+
(0, _defineProperty2["default"])(this, "_retainCounts", new Map());
|
118
|
+
this._environment = environment;
|
119
|
+
}
|
120
|
+
|
121
|
+
var _proto = ClientEdgeQueryResultsCache.prototype;
|
122
|
+
|
123
|
+
_proto.get = function get(fragmentIdentifier) {
|
124
|
+
var _this$_cache$get$, _this$_cache$get;
|
125
|
+
|
126
|
+
return (_this$_cache$get$ = (_this$_cache$get = this._cache.get(fragmentIdentifier)) === null || _this$_cache$get === void 0 ? void 0 : _this$_cache$get[0]) !== null && _this$_cache$get$ !== void 0 ? _this$_cache$get$ : undefined;
|
127
|
+
};
|
128
|
+
|
129
|
+
_proto.recordQueryResults = function recordQueryResults(fragmentIdentifier, value) {
|
130
|
+
var _this = this;
|
131
|
+
|
132
|
+
var existing = this._cache.get(fragmentIdentifier);
|
133
|
+
|
134
|
+
if (!existing) {
|
135
|
+
var suspenseResource = new SuspenseResource(function () {
|
136
|
+
return _this._retain(fragmentIdentifier);
|
137
|
+
});
|
138
|
+
|
139
|
+
this._cache.set(fragmentIdentifier, [value, suspenseResource]);
|
140
|
+
|
141
|
+
suspenseResource.temporaryRetain(this._environment);
|
142
|
+
} else {
|
143
|
+
var existingResults = existing[0],
|
144
|
+
_suspenseResource = existing[1];
|
145
|
+
value.forEach(function (queryResult) {
|
146
|
+
existingResults.push(queryResult);
|
147
|
+
});
|
148
|
+
|
149
|
+
_suspenseResource.temporaryRetain(this._environment);
|
150
|
+
}
|
151
|
+
};
|
152
|
+
|
153
|
+
_proto._retain = function _retain(id) {
|
154
|
+
var _this2 = this;
|
155
|
+
|
156
|
+
var _this$_retainCounts$g;
|
157
|
+
|
158
|
+
var retainCount = ((_this$_retainCounts$g = this._retainCounts.get(id)) !== null && _this$_retainCounts$g !== void 0 ? _this$_retainCounts$g : 0) + 1;
|
159
|
+
|
160
|
+
this._retainCounts.set(id, retainCount);
|
161
|
+
|
162
|
+
return {
|
163
|
+
dispose: function dispose() {
|
164
|
+
var _this$_retainCounts$g2;
|
165
|
+
|
166
|
+
var newRetainCount = ((_this$_retainCounts$g2 = _this2._retainCounts.get(id)) !== null && _this$_retainCounts$g2 !== void 0 ? _this$_retainCounts$g2 : 0) - 1;
|
167
|
+
|
168
|
+
if (newRetainCount > 0) {
|
169
|
+
_this2._retainCounts.set(id, newRetainCount);
|
170
|
+
} else {
|
171
|
+
_this2._retainCounts["delete"](id);
|
172
|
+
|
173
|
+
_this2._cache["delete"](id);
|
174
|
+
}
|
175
|
+
}
|
176
|
+
};
|
177
|
+
};
|
178
|
+
|
179
|
+
return ClientEdgeQueryResultsCache;
|
180
|
+
}();
|
73
181
|
|
74
182
|
var FragmentResourceImpl = /*#__PURE__*/function () {
|
75
183
|
function FragmentResourceImpl(environment) {
|
76
184
|
this._environment = environment;
|
77
185
|
this._cache = LRUCache.create(CACHE_CAPACITY);
|
186
|
+
|
187
|
+
if (RelayFeatureFlags.ENABLE_CLIENT_EDGES) {
|
188
|
+
this._clientEdgeQueryResultsCache = new ClientEdgeQueryResultsCache(environment);
|
189
|
+
}
|
78
190
|
}
|
79
191
|
/**
|
80
192
|
* This function should be called during a Component's render function,
|
@@ -83,9 +195,9 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
83
195
|
*/
|
84
196
|
|
85
197
|
|
86
|
-
var
|
198
|
+
var _proto2 = FragmentResourceImpl.prototype;
|
87
199
|
|
88
|
-
|
200
|
+
_proto2.read = function read(fragmentNode, fragmentRef, componentDisplayName, fragmentKey) {
|
89
201
|
return this.readWithIdentifier(fragmentNode, fragmentRef, getFragmentIdentifier(fragmentNode, fragmentRef), componentDisplayName, fragmentKey);
|
90
202
|
}
|
91
203
|
/**
|
@@ -95,8 +207,10 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
95
207
|
*/
|
96
208
|
;
|
97
209
|
|
98
|
-
|
99
|
-
var
|
210
|
+
_proto2.readWithIdentifier = function readWithIdentifier(fragmentNode, fragmentRef, fragmentIdentifier, componentDisplayName, fragmentKey) {
|
211
|
+
var _this3 = this;
|
212
|
+
|
213
|
+
var _fragmentNode$metadat, _clientEdgePromises;
|
100
214
|
|
101
215
|
var environment = this._environment; // If fragmentRef is null or undefined, pass it directly through.
|
102
216
|
// This is a convenience when consuming fragments via a HOC API, when the
|
@@ -106,11 +220,14 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
106
220
|
return {
|
107
221
|
cacheKey: fragmentIdentifier,
|
108
222
|
data: null,
|
109
|
-
|
223
|
+
isMissingData: false,
|
224
|
+
snapshot: null,
|
225
|
+
storeEpoch: 0
|
110
226
|
};
|
111
|
-
}
|
112
|
-
// If it's empty, return the empty array directly before doing any more work.
|
227
|
+
}
|
113
228
|
|
229
|
+
var storeEpoch = environment.getStore().getEpoch(); // If fragmentRef is plural, ensure that it is an array.
|
230
|
+
// If it's empty, return the empty array directly before doing any more work.
|
114
231
|
|
115
232
|
if ((fragmentNode === null || fragmentNode === void 0 ? void 0 : (_fragmentNode$metadat = fragmentNode.metadata) === null || _fragmentNode$metadat === void 0 ? void 0 : _fragmentNode$metadat.plural) === true) {
|
116
233
|
!Array.isArray(fragmentRef) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected fragment pointer%s for fragment `%s` to be ' + 'an array, instead got `%s`. Remove `@relay(plural: true)` ' + 'from fragment `%s` to allow the prop to be an object.', fragmentKey != null ? " for key `".concat(fragmentKey, "`") : '', fragmentNode.name, typeof fragmentRef, fragmentNode.name) : invariant(false) : void 0;
|
@@ -119,7 +236,9 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
119
236
|
return {
|
120
237
|
cacheKey: fragmentIdentifier,
|
121
238
|
data: CONSTANT_READONLY_EMPTY_ARRAY,
|
122
|
-
|
239
|
+
isMissingData: false,
|
240
|
+
snapshot: CONSTANT_READONLY_EMPTY_ARRAY,
|
241
|
+
storeEpoch: storeEpoch
|
123
242
|
};
|
124
243
|
}
|
125
244
|
} // Now we actually attempt to read the fragment:
|
@@ -129,14 +248,24 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
129
248
|
var cachedValue = this._cache.get(fragmentIdentifier);
|
130
249
|
|
131
250
|
if (cachedValue != null) {
|
132
|
-
if (isPromise(cachedValue)) {
|
133
|
-
|
251
|
+
if (cachedValue.kind === 'pending' && isPromise(cachedValue.promise)) {
|
252
|
+
environment.__log({
|
253
|
+
name: 'suspense.fragment',
|
254
|
+
data: cachedValue.result.data,
|
255
|
+
fragment: fragmentNode,
|
256
|
+
isRelayHooks: true,
|
257
|
+
isMissingData: cachedValue.result.isMissingData,
|
258
|
+
isPromiseCached: true,
|
259
|
+
pendingOperations: cachedValue.pendingOperations
|
260
|
+
});
|
261
|
+
|
262
|
+
throw cachedValue.promise;
|
134
263
|
}
|
135
264
|
|
136
|
-
if (cachedValue.snapshot) {
|
137
|
-
this._reportMissingRequiredFieldsInSnapshot(cachedValue.snapshot);
|
265
|
+
if (cachedValue.kind === 'done' && cachedValue.result.snapshot) {
|
266
|
+
this._reportMissingRequiredFieldsInSnapshot(cachedValue.result.snapshot);
|
138
267
|
|
139
|
-
return cachedValue;
|
268
|
+
return cachedValue.result;
|
140
269
|
}
|
141
270
|
} // 2. If not, try reading the fragment from the Relay store.
|
142
271
|
// If the snapshot has data, return it and save it in cache
|
@@ -147,41 +276,120 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
147
276
|
var snapshot = fragmentSelector.kind === 'PluralReaderSelector' ? fragmentSelector.selectors.map(function (s) {
|
148
277
|
return environment.lookup(s);
|
149
278
|
}) : environment.lookup(fragmentSelector);
|
150
|
-
var
|
279
|
+
var fragmentResult = getFragmentResult(fragmentIdentifier, snapshot, storeEpoch);
|
151
280
|
|
152
|
-
if (!isMissingData
|
281
|
+
if (!fragmentResult.isMissingData) {
|
153
282
|
this._reportMissingRequiredFieldsInSnapshot(snapshot);
|
154
283
|
|
155
|
-
|
156
|
-
|
157
|
-
|
284
|
+
this._cache.set(fragmentIdentifier, {
|
285
|
+
kind: 'done',
|
286
|
+
result: fragmentResult
|
287
|
+
});
|
158
288
|
|
159
289
|
return fragmentResult;
|
160
|
-
} // 3. If we don't have data in the store,
|
161
|
-
//
|
162
|
-
//
|
163
|
-
//
|
164
|
-
//
|
290
|
+
} // 3. If we don't have data in the store, there's two cases where we should
|
291
|
+
// suspend to await the data: First if any client edges were traversed where
|
292
|
+
// the destination record was missing data; in that case we initiate a query
|
293
|
+
// here to fetch the missing data. Second, there may already be a request
|
294
|
+
// in flight for the fragment's parent query, or for another operation that
|
295
|
+
// may affect the parent's query data, such as a mutation or subscription.
|
296
|
+
// For any of these cases we can get a promise, which we will cache and
|
297
|
+
// suspend on.
|
298
|
+
// First, initiate a query for any client edges that were missing data:
|
299
|
+
|
300
|
+
|
301
|
+
var clientEdgeRequests = null;
|
302
|
+
|
303
|
+
if (RelayFeatureFlags.ENABLE_CLIENT_EDGES && hasMissingClientEdges(snapshot)) {
|
304
|
+
clientEdgeRequests = [];
|
305
|
+
var queryResource = getQueryResourceForEnvironment(this._environment);
|
306
|
+
var queryResults = [];
|
307
|
+
singularOrPluralForEach(snapshot, function (snap) {
|
308
|
+
var _snap$missingClientEd;
|
309
|
+
|
310
|
+
(_snap$missingClientEd = snap.missingClientEdges) === null || _snap$missingClientEd === void 0 ? void 0 : _snap$missingClientEd.forEach(function (_ref) {
|
311
|
+
var _clientEdgeRequests;
|
312
|
+
|
313
|
+
var request = _ref.request,
|
314
|
+
clientEdgeDestinationID = _ref.clientEdgeDestinationID;
|
315
|
+
|
316
|
+
var _this3$_performClient = _this3._performClientEdgeQuery(queryResource, fragmentNode, fragmentRef, request, clientEdgeDestinationID),
|
317
|
+
queryResult = _this3$_performClient.queryResult,
|
318
|
+
requestDescriptor = _this3$_performClient.requestDescriptor;
|
319
|
+
|
320
|
+
queryResults.push(queryResult);
|
321
|
+
(_clientEdgeRequests = clientEdgeRequests) === null || _clientEdgeRequests === void 0 ? void 0 : _clientEdgeRequests.push(requestDescriptor);
|
322
|
+
});
|
323
|
+
}); // Store the query so that it can be retained when our own fragment is
|
324
|
+
// subscribed to. This merges with any existing query results:
|
325
|
+
|
326
|
+
!(this._clientEdgeQueryResultsCache != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Client edge query result cache should exist when ENABLE_CLIENT_EDGES is on.') : invariant(false) : void 0;
|
327
|
+
|
328
|
+
this._clientEdgeQueryResultsCache.recordQueryResults(fragmentIdentifier, queryResults);
|
329
|
+
}
|
165
330
|
|
331
|
+
var clientEdgePromises = null;
|
166
332
|
|
167
|
-
|
333
|
+
if (RelayFeatureFlags.ENABLE_CLIENT_EDGES && clientEdgeRequests) {
|
334
|
+
clientEdgePromises = clientEdgeRequests.map(function (request) {
|
335
|
+
return getPromiseForActiveRequest(_this3._environment, request);
|
336
|
+
}).filter(function (p) {
|
337
|
+
return p != null;
|
338
|
+
});
|
339
|
+
} // Finally look for operations in flight for our parent query:
|
340
|
+
|
341
|
+
|
342
|
+
var fragmentOwner = fragmentSelector.kind === 'PluralReaderSelector' ? fragmentSelector.selectors[0].owner : fragmentSelector.owner;
|
168
343
|
|
169
|
-
|
170
|
-
|
344
|
+
var parentQueryPromiseResult = this._getAndSavePromiseForFragmentRequestInFlight(fragmentIdentifier, fragmentNode, fragmentOwner, fragmentResult);
|
345
|
+
|
346
|
+
var parentQueryPromiseResultPromise = parentQueryPromiseResult === null || parentQueryPromiseResult === void 0 ? void 0 : parentQueryPromiseResult.promise; // for refinement
|
347
|
+
|
348
|
+
if (((_clientEdgePromises = clientEdgePromises) === null || _clientEdgePromises === void 0 ? void 0 : _clientEdgePromises.length) || isPromise(parentQueryPromiseResultPromise)) {
|
349
|
+
var _parentQueryPromiseRe, _clientEdgeRequests2, _clientEdgePromises2;
|
350
|
+
|
351
|
+
environment.__log({
|
352
|
+
name: 'suspense.fragment',
|
353
|
+
data: fragmentResult.data,
|
354
|
+
fragment: fragmentNode,
|
355
|
+
isRelayHooks: true,
|
356
|
+
isPromiseCached: false,
|
357
|
+
isMissingData: fragmentResult.isMissingData,
|
358
|
+
pendingOperations: [].concat((0, _toConsumableArray2["default"])((_parentQueryPromiseRe = parentQueryPromiseResult === null || parentQueryPromiseResult === void 0 ? void 0 : parentQueryPromiseResult.pendingOperations) !== null && _parentQueryPromiseRe !== void 0 ? _parentQueryPromiseRe : []), (0, _toConsumableArray2["default"])((_clientEdgeRequests2 = clientEdgeRequests) !== null && _clientEdgeRequests2 !== void 0 ? _clientEdgeRequests2 : []))
|
359
|
+
});
|
360
|
+
|
361
|
+
throw ((_clientEdgePromises2 = clientEdgePromises) === null || _clientEdgePromises2 === void 0 ? void 0 : _clientEdgePromises2.length) ? Promise.all([parentQueryPromiseResultPromise].concat((0, _toConsumableArray2["default"])(clientEdgePromises))) : parentQueryPromiseResultPromise;
|
171
362
|
}
|
172
363
|
|
173
364
|
this._reportMissingRequiredFieldsInSnapshot(snapshot);
|
174
365
|
|
175
|
-
return getFragmentResult(fragmentIdentifier, snapshot);
|
366
|
+
return getFragmentResult(fragmentIdentifier, snapshot, storeEpoch);
|
176
367
|
};
|
177
368
|
|
178
|
-
|
179
|
-
var
|
369
|
+
_proto2._performClientEdgeQuery = function _performClientEdgeQuery(queryResource, fragmentNode, fragmentRef, request, clientEdgeDestinationID) {
|
370
|
+
var originalVariables = getVariablesFromFragment(fragmentNode, fragmentRef);
|
371
|
+
var variables = (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, originalVariables), {}, {
|
372
|
+
id: clientEdgeDestinationID // TODO should be a reserved name
|
373
|
+
|
374
|
+
});
|
375
|
+
var operation = createOperationDescriptor(request, variables, {} // TODO cacheConfig should probably inherent from parent operation
|
376
|
+
);
|
377
|
+
var fetchObservable = fetchQuery(this._environment, operation);
|
378
|
+
var queryResult = queryResource.prepare(operation, fetchObservable // TODO should inherent render policy etc. from parent operation
|
379
|
+
);
|
380
|
+
return {
|
381
|
+
requestDescriptor: operation.request,
|
382
|
+
queryResult: queryResult
|
383
|
+
};
|
384
|
+
};
|
385
|
+
|
386
|
+
_proto2._reportMissingRequiredFieldsInSnapshot = function _reportMissingRequiredFieldsInSnapshot(snapshot) {
|
387
|
+
var _this4 = this;
|
180
388
|
|
181
389
|
if (Array.isArray(snapshot)) {
|
182
390
|
snapshot.forEach(function (s) {
|
183
391
|
if (s.missingRequiredFields != null) {
|
184
|
-
reportMissingRequiredFields(
|
392
|
+
reportMissingRequiredFields(_this4._environment, s.missingRequiredFields);
|
185
393
|
}
|
186
394
|
});
|
187
395
|
} else {
|
@@ -191,17 +399,18 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
191
399
|
}
|
192
400
|
};
|
193
401
|
|
194
|
-
|
195
|
-
var
|
402
|
+
_proto2.readSpec = function readSpec(fragmentNodes, fragmentRefs, componentDisplayName) {
|
403
|
+
var result = {};
|
196
404
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
405
|
+
for (var _key in fragmentNodes) {
|
406
|
+
result[_key] = this.read(fragmentNodes[_key], fragmentRefs[_key], componentDisplayName, _key);
|
407
|
+
}
|
408
|
+
|
409
|
+
return result;
|
201
410
|
};
|
202
411
|
|
203
|
-
|
204
|
-
var
|
412
|
+
_proto2.subscribe = function subscribe(fragmentResult, callback) {
|
413
|
+
var _this5 = this;
|
205
414
|
|
206
415
|
var environment = this._environment;
|
207
416
|
var cacheKey = fragmentResult.cacheKey;
|
@@ -226,42 +435,62 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
226
435
|
} // 3. Establish subscriptions on the snapshot(s)
|
227
436
|
|
228
437
|
|
229
|
-
var
|
438
|
+
var disposables = [];
|
230
439
|
|
231
440
|
if (Array.isArray(renderedSnapshot)) {
|
232
441
|
!Array.isArray(currentSnapshot) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected snapshots to be plural. ' + "If you're seeing this, this is likely a bug in Relay.") : invariant(false) : void 0;
|
233
442
|
currentSnapshot.forEach(function (snapshot, idx) {
|
234
|
-
|
235
|
-
|
443
|
+
disposables.push(environment.subscribe(snapshot, function (latestSnapshot) {
|
444
|
+
var storeEpoch = environment.getStore().getEpoch();
|
445
|
+
|
446
|
+
_this5._updatePluralSnapshot(cacheKey, currentSnapshot, latestSnapshot, idx, storeEpoch);
|
236
447
|
|
237
448
|
callback();
|
238
449
|
}));
|
239
450
|
});
|
240
451
|
} else {
|
241
452
|
!(currentSnapshot != null && !Array.isArray(currentSnapshot)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected snapshot to be singular. ' + "If you're seeing this, this is likely a bug in Relay.") : invariant(false) : void 0;
|
242
|
-
|
243
|
-
|
453
|
+
disposables.push(environment.subscribe(currentSnapshot, function (latestSnapshot) {
|
454
|
+
var storeEpoch = environment.getStore().getEpoch();
|
455
|
+
|
456
|
+
_this5._cache.set(cacheKey, {
|
457
|
+
kind: 'done',
|
458
|
+
result: getFragmentResult(cacheKey, latestSnapshot, storeEpoch)
|
459
|
+
});
|
244
460
|
|
245
461
|
callback();
|
246
462
|
}));
|
247
463
|
}
|
248
464
|
|
465
|
+
if (RelayFeatureFlags.ENABLE_CLIENT_EDGES) {
|
466
|
+
var _this$_clientEdgeQuer, _this$_clientEdgeQuer2;
|
467
|
+
|
468
|
+
var clientEdgeQueryResults = (_this$_clientEdgeQuer = (_this$_clientEdgeQuer2 = this._clientEdgeQueryResultsCache) === null || _this$_clientEdgeQuer2 === void 0 ? void 0 : _this$_clientEdgeQuer2.get(cacheKey)) !== null && _this$_clientEdgeQuer !== void 0 ? _this$_clientEdgeQuer : undefined;
|
469
|
+
|
470
|
+
if (clientEdgeQueryResults === null || clientEdgeQueryResults === void 0 ? void 0 : clientEdgeQueryResults.length) {
|
471
|
+
var queryResource = getQueryResourceForEnvironment(this._environment);
|
472
|
+
clientEdgeQueryResults.forEach(function (queryResult) {
|
473
|
+
disposables.push(queryResource.retain(queryResult));
|
474
|
+
});
|
475
|
+
}
|
476
|
+
}
|
477
|
+
|
249
478
|
return {
|
250
479
|
dispose: function dispose() {
|
251
|
-
|
480
|
+
disposables.forEach(function (s) {
|
252
481
|
return s.dispose();
|
253
482
|
});
|
254
483
|
|
255
|
-
|
484
|
+
_this5._cache["delete"](cacheKey);
|
256
485
|
}
|
257
486
|
};
|
258
487
|
};
|
259
488
|
|
260
|
-
|
261
|
-
var
|
489
|
+
_proto2.subscribeSpec = function subscribeSpec(fragmentResults, callback) {
|
490
|
+
var _this6 = this;
|
262
491
|
|
263
492
|
var disposables = Object.keys(fragmentResults).map(function (key) {
|
264
|
-
return
|
493
|
+
return _this6.subscribe(fragmentResults[key], callback);
|
265
494
|
});
|
266
495
|
return {
|
267
496
|
dispose: function dispose() {
|
@@ -272,18 +501,26 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
272
501
|
};
|
273
502
|
};
|
274
503
|
|
275
|
-
|
504
|
+
_proto2.checkMissedUpdates = function checkMissedUpdates(fragmentResult) {
|
276
505
|
var environment = this._environment;
|
277
|
-
var cacheKey = fragmentResult.cacheKey;
|
278
506
|
var renderedSnapshot = fragmentResult.snapshot;
|
279
507
|
|
280
508
|
if (!renderedSnapshot) {
|
281
509
|
return [false, null];
|
282
510
|
}
|
283
511
|
|
284
|
-
var
|
512
|
+
var storeEpoch = null; // Bail out if the store hasn't been written since last read
|
513
|
+
|
514
|
+
storeEpoch = environment.getStore().getEpoch();
|
515
|
+
|
516
|
+
if (fragmentResult.storeEpoch === storeEpoch) {
|
517
|
+
return [false, fragmentResult.snapshot];
|
518
|
+
}
|
519
|
+
|
520
|
+
var cacheKey = fragmentResult.cacheKey;
|
285
521
|
|
286
522
|
if (Array.isArray(renderedSnapshot)) {
|
523
|
+
var didMissUpdates = false;
|
287
524
|
var currentSnapshots = [];
|
288
525
|
renderedSnapshot.forEach(function (snapshot, idx) {
|
289
526
|
var currentSnapshot = environment.lookup(snapshot.selector);
|
@@ -299,10 +536,14 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
299
536
|
}
|
300
537
|
|
301
538
|
currentSnapshots[idx] = currentSnapshot;
|
302
|
-
});
|
539
|
+
}); // Only update the cache when the data is changed to avoid
|
540
|
+
// returning different `data` instances
|
303
541
|
|
304
542
|
if (didMissUpdates) {
|
305
|
-
this._cache.set(cacheKey,
|
543
|
+
this._cache.set(cacheKey, {
|
544
|
+
kind: 'done',
|
545
|
+
result: getFragmentResult(cacheKey, currentSnapshots, storeEpoch)
|
546
|
+
});
|
306
547
|
}
|
307
548
|
|
308
549
|
return [didMissUpdates, currentSnapshots];
|
@@ -312,60 +553,71 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
312
553
|
var renderData = renderedSnapshot.data;
|
313
554
|
var currentData = currentSnapshot.data;
|
314
555
|
var updatedData = recycleNodesInto(renderData, currentData);
|
315
|
-
|
556
|
+
var updatedCurrentSnapshot = {
|
316
557
|
data: updatedData,
|
317
558
|
isMissingData: currentSnapshot.isMissingData,
|
559
|
+
missingClientEdges: currentSnapshot.missingClientEdges,
|
318
560
|
seenRecords: currentSnapshot.seenRecords,
|
319
561
|
selector: currentSnapshot.selector,
|
320
562
|
missingRequiredFields: currentSnapshot.missingRequiredFields
|
321
563
|
};
|
322
564
|
|
323
565
|
if (updatedData !== renderData) {
|
324
|
-
this._cache.set(cacheKey,
|
325
|
-
|
326
|
-
|
566
|
+
this._cache.set(cacheKey, {
|
567
|
+
kind: 'done',
|
568
|
+
result: getFragmentResult(cacheKey, updatedCurrentSnapshot, storeEpoch)
|
569
|
+
});
|
327
570
|
}
|
328
571
|
|
329
|
-
return [
|
572
|
+
return [updatedData !== renderData, updatedCurrentSnapshot];
|
330
573
|
};
|
331
574
|
|
332
|
-
|
333
|
-
var
|
575
|
+
_proto2.checkMissedUpdatesSpec = function checkMissedUpdatesSpec(fragmentResults) {
|
576
|
+
var _this7 = this;
|
334
577
|
|
335
578
|
return Object.keys(fragmentResults).some(function (key) {
|
336
|
-
return
|
579
|
+
return _this7.checkMissedUpdates(fragmentResults[key])[0];
|
337
580
|
});
|
338
581
|
};
|
339
582
|
|
340
|
-
|
341
|
-
var
|
583
|
+
_proto2._getAndSavePromiseForFragmentRequestInFlight = function _getAndSavePromiseForFragmentRequestInFlight(cacheKey, fragmentNode, fragmentOwner, fragmentResult) {
|
584
|
+
var _this8 = this;
|
342
585
|
|
343
|
-
var
|
586
|
+
var pendingOperationsResult = getPendingOperationsForFragment(this._environment, fragmentNode, fragmentOwner);
|
344
587
|
|
345
|
-
|
346
|
-
var networkPromise = (_getPromiseForActiveR = getPromiseForActiveRequest(environment, fragmentOwner)) !== null && _getPromiseForActiveR !== void 0 ? _getPromiseForActiveR : getPromiseForPendingOperationAffectingOwner(environment, fragmentOwner);
|
347
|
-
|
348
|
-
if (!networkPromise) {
|
588
|
+
if (pendingOperationsResult == null) {
|
349
589
|
return null;
|
350
590
|
} // When the Promise for the request resolves, we need to make sure to
|
351
591
|
// update the cache with the latest data available in the store before
|
352
592
|
// resolving the Promise
|
353
593
|
|
354
594
|
|
595
|
+
var networkPromise = pendingOperationsResult.promise;
|
596
|
+
var pendingOperations = pendingOperationsResult.pendingOperations;
|
355
597
|
var promise = networkPromise.then(function () {
|
356
|
-
|
598
|
+
_this8._cache["delete"](cacheKey);
|
357
599
|
})["catch"](function (error) {
|
358
|
-
|
359
|
-
});
|
600
|
+
_this8._cache["delete"](cacheKey);
|
601
|
+
}); // $FlowExpectedError[prop-missing] Expando to annotate Promises.
|
360
602
|
|
361
|
-
|
603
|
+
promise.displayName = networkPromise.displayName;
|
362
604
|
|
605
|
+
this._cache.set(cacheKey, {
|
606
|
+
kind: 'pending',
|
607
|
+
pendingOperations: pendingOperations,
|
608
|
+
promise: promise,
|
609
|
+
result: fragmentResult
|
610
|
+
});
|
363
611
|
|
364
|
-
|
365
|
-
|
612
|
+
return {
|
613
|
+
promise: promise,
|
614
|
+
pendingOperations: pendingOperations
|
615
|
+
};
|
366
616
|
};
|
367
617
|
|
368
|
-
|
618
|
+
_proto2._updatePluralSnapshot = function _updatePluralSnapshot(cacheKey, baseSnapshots, latestSnapshot, idx, storeEpoch) {
|
619
|
+
var _currentFragmentResul;
|
620
|
+
|
369
621
|
var currentFragmentResult = this._cache.get(cacheKey);
|
370
622
|
|
371
623
|
if (isPromise(currentFragmentResult)) {
|
@@ -373,7 +625,7 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
373
625
|
return;
|
374
626
|
}
|
375
627
|
|
376
|
-
var currentSnapshot = currentFragmentResult === null || currentFragmentResult === void 0 ? void 0 : currentFragmentResult.snapshot;
|
628
|
+
var currentSnapshot = currentFragmentResult === null || currentFragmentResult === void 0 ? void 0 : (_currentFragmentResul = currentFragmentResult.result) === null || _currentFragmentResul === void 0 ? void 0 : _currentFragmentResul.snapshot;
|
377
629
|
|
378
630
|
if (currentSnapshot && !Array.isArray(currentSnapshot)) {
|
379
631
|
reportInvalidCachedData(latestSnapshot.selector.node.name);
|
@@ -383,7 +635,10 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
383
635
|
var nextSnapshots = currentSnapshot ? (0, _toConsumableArray2["default"])(currentSnapshot) : (0, _toConsumableArray2["default"])(baseSnapshots);
|
384
636
|
nextSnapshots[idx] = latestSnapshot;
|
385
637
|
|
386
|
-
this._cache.set(cacheKey,
|
638
|
+
this._cache.set(cacheKey, {
|
639
|
+
kind: 'done',
|
640
|
+
result: getFragmentResult(cacheKey, nextSnapshots, storeEpoch)
|
641
|
+
});
|
387
642
|
};
|
388
643
|
|
389
644
|
return FragmentResourceImpl;
|