react-relay 11.0.0 → 13.0.0-rc.0
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 +7 -8
- package/ReactRelayPaginationContainer.js.flow +111 -54
- package/ReactRelayQueryFetcher.js.flow +9 -10
- package/ReactRelayQueryRenderer.js.flow +115 -81
- package/ReactRelayRefetchContainer.js.flow +40 -35
- package/ReactRelayTestMocker.js.flow +16 -12
- 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 +12 -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 -3
- 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 +92 -30
- package/lib/ReactRelayQueryFetcher.js +3 -3
- package/lib/ReactRelayQueryRenderer.js +86 -53
- package/lib/ReactRelayRefetchContainer.js +36 -21
- package/lib/ReactRelayTestMocker.js +7 -6
- package/lib/RelayContext.js +3 -2
- package/lib/assertFragmentMap.js +3 -2
- package/lib/buildReactRelayContainer.js +14 -11
- 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 +351 -94
- 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 +6 -8
- 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 +12 -14
- 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 +376 -95
- 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 -27
- 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 -30
- 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 -66
- 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 -108
- package/relay-hooks/getRefetchMetadata.js.flow +0 -80
- package/relay-hooks/getValueAtPath.js.flow +0 -46
@@ -15,27 +15,40 @@ 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
|
36
47
|
// capacity, readSpec() will fail to find cached entries and break object
|
37
48
|
// identity even if data hasn't changed.
|
38
|
-
var CACHE_CAPACITY = 1000000;
|
49
|
+
var CACHE_CAPACITY = 1000000; // this is frozen so that users don't accidentally push data into the array
|
50
|
+
|
51
|
+
var CONSTANT_READONLY_EMPTY_ARRAY = Object.freeze([]);
|
39
52
|
|
40
53
|
function isMissingData(snapshot) {
|
41
54
|
if (Array.isArray(snapshot)) {
|
@@ -47,32 +60,133 @@ function isMissingData(snapshot) {
|
|
47
60
|
return snapshot.isMissingData;
|
48
61
|
}
|
49
62
|
|
50
|
-
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) {
|
51
86
|
if (Array.isArray(snapshot)) {
|
52
87
|
return {
|
53
88
|
cacheKey: cacheKey,
|
54
89
|
snapshot: snapshot,
|
55
90
|
data: snapshot.map(function (s) {
|
56
91
|
return s.data;
|
57
|
-
})
|
92
|
+
}),
|
93
|
+
isMissingData: isMissingData(snapshot),
|
94
|
+
storeEpoch: storeEpoch
|
58
95
|
};
|
59
96
|
}
|
60
97
|
|
61
98
|
return {
|
62
99
|
cacheKey: cacheKey,
|
63
100
|
snapshot: snapshot,
|
64
|
-
data: snapshot.data
|
101
|
+
data: snapshot.data,
|
102
|
+
isMissingData: isMissingData(snapshot),
|
103
|
+
storeEpoch: storeEpoch
|
65
104
|
};
|
66
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
|
+
*/
|
67
112
|
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
+
}();
|
71
181
|
|
72
182
|
var FragmentResourceImpl = /*#__PURE__*/function () {
|
73
183
|
function FragmentResourceImpl(environment) {
|
74
184
|
this._environment = environment;
|
75
185
|
this._cache = LRUCache.create(CACHE_CAPACITY);
|
186
|
+
|
187
|
+
if (RelayFeatureFlags.ENABLE_CLIENT_EDGES) {
|
188
|
+
this._clientEdgeQueryResultsCache = new ClientEdgeQueryResultsCache(environment);
|
189
|
+
}
|
76
190
|
}
|
77
191
|
/**
|
78
192
|
* This function should be called during a Component's render function,
|
@@ -81,9 +195,9 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
81
195
|
*/
|
82
196
|
|
83
197
|
|
84
|
-
var
|
198
|
+
var _proto2 = FragmentResourceImpl.prototype;
|
85
199
|
|
86
|
-
|
200
|
+
_proto2.read = function read(fragmentNode, fragmentRef, componentDisplayName, fragmentKey) {
|
87
201
|
return this.readWithIdentifier(fragmentNode, fragmentRef, getFragmentIdentifier(fragmentNode, fragmentRef), componentDisplayName, fragmentKey);
|
88
202
|
}
|
89
203
|
/**
|
@@ -93,8 +207,10 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
93
207
|
*/
|
94
208
|
;
|
95
209
|
|
96
|
-
|
97
|
-
var
|
210
|
+
_proto2.readWithIdentifier = function readWithIdentifier(fragmentNode, fragmentRef, fragmentIdentifier, componentDisplayName, fragmentKey) {
|
211
|
+
var _this3 = this;
|
212
|
+
|
213
|
+
var _fragmentNode$metadat, _clientEdgePromises;
|
98
214
|
|
99
215
|
var environment = this._environment; // If fragmentRef is null or undefined, pass it directly through.
|
100
216
|
// This is a convenience when consuming fragments via a HOC API, when the
|
@@ -104,11 +220,14 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
104
220
|
return {
|
105
221
|
cacheKey: fragmentIdentifier,
|
106
222
|
data: null,
|
107
|
-
|
223
|
+
isMissingData: false,
|
224
|
+
snapshot: null,
|
225
|
+
storeEpoch: 0
|
108
226
|
};
|
109
|
-
}
|
110
|
-
// If it's empty, return the empty array directly before doing any more work.
|
227
|
+
}
|
111
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.
|
112
231
|
|
113
232
|
if ((fragmentNode === null || fragmentNode === void 0 ? void 0 : (_fragmentNode$metadat = fragmentNode.metadata) === null || _fragmentNode$metadat === void 0 ? void 0 : _fragmentNode$metadat.plural) === true) {
|
114
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;
|
@@ -116,8 +235,10 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
116
235
|
if (fragmentRef.length === 0) {
|
117
236
|
return {
|
118
237
|
cacheKey: fragmentIdentifier,
|
119
|
-
data:
|
120
|
-
|
238
|
+
data: CONSTANT_READONLY_EMPTY_ARRAY,
|
239
|
+
isMissingData: false,
|
240
|
+
snapshot: CONSTANT_READONLY_EMPTY_ARRAY,
|
241
|
+
storeEpoch: storeEpoch
|
121
242
|
};
|
122
243
|
}
|
123
244
|
} // Now we actually attempt to read the fragment:
|
@@ -127,14 +248,24 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
127
248
|
var cachedValue = this._cache.get(fragmentIdentifier);
|
128
249
|
|
129
250
|
if (cachedValue != null) {
|
130
|
-
if (isPromise(cachedValue)) {
|
131
|
-
|
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;
|
132
263
|
}
|
133
264
|
|
134
|
-
if (cachedValue.snapshot) {
|
135
|
-
this._reportMissingRequiredFieldsInSnapshot(cachedValue.snapshot);
|
265
|
+
if (cachedValue.kind === 'done' && cachedValue.result.snapshot) {
|
266
|
+
this._reportMissingRequiredFieldsInSnapshot(cachedValue.result.snapshot);
|
136
267
|
|
137
|
-
return cachedValue;
|
268
|
+
return cachedValue.result;
|
138
269
|
}
|
139
270
|
} // 2. If not, try reading the fragment from the Relay store.
|
140
271
|
// If the snapshot has data, return it and save it in cache
|
@@ -145,41 +276,120 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
145
276
|
var snapshot = fragmentSelector.kind === 'PluralReaderSelector' ? fragmentSelector.selectors.map(function (s) {
|
146
277
|
return environment.lookup(s);
|
147
278
|
}) : environment.lookup(fragmentSelector);
|
148
|
-
var
|
279
|
+
var fragmentResult = getFragmentResult(fragmentIdentifier, snapshot, storeEpoch);
|
149
280
|
|
150
|
-
if (!isMissingData
|
281
|
+
if (!fragmentResult.isMissingData) {
|
151
282
|
this._reportMissingRequiredFieldsInSnapshot(snapshot);
|
152
283
|
|
153
|
-
|
154
|
-
|
155
|
-
|
284
|
+
this._cache.set(fragmentIdentifier, {
|
285
|
+
kind: 'done',
|
286
|
+
result: fragmentResult
|
287
|
+
});
|
156
288
|
|
157
289
|
return fragmentResult;
|
158
|
-
} // 3. If we don't have data in the store,
|
159
|
-
//
|
160
|
-
//
|
161
|
-
//
|
162
|
-
//
|
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
|
+
}
|
163
330
|
|
331
|
+
var clientEdgePromises = null;
|
164
332
|
|
165
|
-
|
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;
|
166
343
|
|
167
|
-
|
168
|
-
|
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;
|
169
362
|
}
|
170
363
|
|
171
364
|
this._reportMissingRequiredFieldsInSnapshot(snapshot);
|
172
365
|
|
173
|
-
return getFragmentResult(fragmentIdentifier, snapshot);
|
366
|
+
return getFragmentResult(fragmentIdentifier, snapshot, storeEpoch);
|
174
367
|
};
|
175
368
|
|
176
|
-
|
177
|
-
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;
|
178
388
|
|
179
389
|
if (Array.isArray(snapshot)) {
|
180
390
|
snapshot.forEach(function (s) {
|
181
391
|
if (s.missingRequiredFields != null) {
|
182
|
-
reportMissingRequiredFields(
|
392
|
+
reportMissingRequiredFields(_this4._environment, s.missingRequiredFields);
|
183
393
|
}
|
184
394
|
});
|
185
395
|
} else {
|
@@ -189,17 +399,18 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
189
399
|
}
|
190
400
|
};
|
191
401
|
|
192
|
-
|
193
|
-
var
|
402
|
+
_proto2.readSpec = function readSpec(fragmentNodes, fragmentRefs, componentDisplayName) {
|
403
|
+
var result = {};
|
194
404
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
405
|
+
for (var _key in fragmentNodes) {
|
406
|
+
result[_key] = this.read(fragmentNodes[_key], fragmentRefs[_key], componentDisplayName, _key);
|
407
|
+
}
|
408
|
+
|
409
|
+
return result;
|
199
410
|
};
|
200
411
|
|
201
|
-
|
202
|
-
var
|
412
|
+
_proto2.subscribe = function subscribe(fragmentResult, callback) {
|
413
|
+
var _this5 = this;
|
203
414
|
|
204
415
|
var environment = this._environment;
|
205
416
|
var cacheKey = fragmentResult.cacheKey;
|
@@ -224,42 +435,62 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
224
435
|
} // 3. Establish subscriptions on the snapshot(s)
|
225
436
|
|
226
437
|
|
227
|
-
var
|
438
|
+
var disposables = [];
|
228
439
|
|
229
440
|
if (Array.isArray(renderedSnapshot)) {
|
230
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;
|
231
442
|
currentSnapshot.forEach(function (snapshot, idx) {
|
232
|
-
|
233
|
-
|
443
|
+
disposables.push(environment.subscribe(snapshot, function (latestSnapshot) {
|
444
|
+
var storeEpoch = environment.getStore().getEpoch();
|
445
|
+
|
446
|
+
_this5._updatePluralSnapshot(cacheKey, currentSnapshot, latestSnapshot, idx, storeEpoch);
|
234
447
|
|
235
448
|
callback();
|
236
449
|
}));
|
237
450
|
});
|
238
451
|
} else {
|
239
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;
|
240
|
-
|
241
|
-
|
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
|
+
});
|
242
460
|
|
243
461
|
callback();
|
244
462
|
}));
|
245
463
|
}
|
246
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
|
+
|
247
478
|
return {
|
248
479
|
dispose: function dispose() {
|
249
|
-
|
480
|
+
disposables.forEach(function (s) {
|
250
481
|
return s.dispose();
|
251
482
|
});
|
252
483
|
|
253
|
-
|
484
|
+
_this5._cache["delete"](cacheKey);
|
254
485
|
}
|
255
486
|
};
|
256
487
|
};
|
257
488
|
|
258
|
-
|
259
|
-
var
|
489
|
+
_proto2.subscribeSpec = function subscribeSpec(fragmentResults, callback) {
|
490
|
+
var _this6 = this;
|
260
491
|
|
261
492
|
var disposables = Object.keys(fragmentResults).map(function (key) {
|
262
|
-
return
|
493
|
+
return _this6.subscribe(fragmentResults[key], callback);
|
263
494
|
});
|
264
495
|
return {
|
265
496
|
dispose: function dispose() {
|
@@ -270,18 +501,26 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
270
501
|
};
|
271
502
|
};
|
272
503
|
|
273
|
-
|
504
|
+
_proto2.checkMissedUpdates = function checkMissedUpdates(fragmentResult) {
|
274
505
|
var environment = this._environment;
|
275
|
-
var cacheKey = fragmentResult.cacheKey;
|
276
506
|
var renderedSnapshot = fragmentResult.snapshot;
|
277
507
|
|
278
508
|
if (!renderedSnapshot) {
|
279
509
|
return [false, null];
|
280
510
|
}
|
281
511
|
|
282
|
-
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;
|
283
521
|
|
284
522
|
if (Array.isArray(renderedSnapshot)) {
|
523
|
+
var didMissUpdates = false;
|
285
524
|
var currentSnapshots = [];
|
286
525
|
renderedSnapshot.forEach(function (snapshot, idx) {
|
287
526
|
var currentSnapshot = environment.lookup(snapshot.selector);
|
@@ -297,10 +536,14 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
297
536
|
}
|
298
537
|
|
299
538
|
currentSnapshots[idx] = currentSnapshot;
|
300
|
-
});
|
539
|
+
}); // Only update the cache when the data is changed to avoid
|
540
|
+
// returning different `data` instances
|
301
541
|
|
302
542
|
if (didMissUpdates) {
|
303
|
-
this._cache.set(cacheKey,
|
543
|
+
this._cache.set(cacheKey, {
|
544
|
+
kind: 'done',
|
545
|
+
result: getFragmentResult(cacheKey, currentSnapshots, storeEpoch)
|
546
|
+
});
|
304
547
|
}
|
305
548
|
|
306
549
|
return [didMissUpdates, currentSnapshots];
|
@@ -310,60 +553,71 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
310
553
|
var renderData = renderedSnapshot.data;
|
311
554
|
var currentData = currentSnapshot.data;
|
312
555
|
var updatedData = recycleNodesInto(renderData, currentData);
|
313
|
-
|
556
|
+
var updatedCurrentSnapshot = {
|
314
557
|
data: updatedData,
|
315
558
|
isMissingData: currentSnapshot.isMissingData,
|
559
|
+
missingClientEdges: currentSnapshot.missingClientEdges,
|
316
560
|
seenRecords: currentSnapshot.seenRecords,
|
317
561
|
selector: currentSnapshot.selector,
|
318
562
|
missingRequiredFields: currentSnapshot.missingRequiredFields
|
319
563
|
};
|
320
564
|
|
321
565
|
if (updatedData !== renderData) {
|
322
|
-
this._cache.set(cacheKey,
|
323
|
-
|
324
|
-
|
566
|
+
this._cache.set(cacheKey, {
|
567
|
+
kind: 'done',
|
568
|
+
result: getFragmentResult(cacheKey, updatedCurrentSnapshot, storeEpoch)
|
569
|
+
});
|
325
570
|
}
|
326
571
|
|
327
|
-
return [
|
572
|
+
return [updatedData !== renderData, updatedCurrentSnapshot];
|
328
573
|
};
|
329
574
|
|
330
|
-
|
331
|
-
var
|
575
|
+
_proto2.checkMissedUpdatesSpec = function checkMissedUpdatesSpec(fragmentResults) {
|
576
|
+
var _this7 = this;
|
332
577
|
|
333
578
|
return Object.keys(fragmentResults).some(function (key) {
|
334
|
-
return
|
579
|
+
return _this7.checkMissedUpdates(fragmentResults[key])[0];
|
335
580
|
});
|
336
581
|
};
|
337
582
|
|
338
|
-
|
339
|
-
var
|
583
|
+
_proto2._getAndSavePromiseForFragmentRequestInFlight = function _getAndSavePromiseForFragmentRequestInFlight(cacheKey, fragmentNode, fragmentOwner, fragmentResult) {
|
584
|
+
var _this8 = this;
|
340
585
|
|
341
|
-
var
|
586
|
+
var pendingOperationsResult = getPendingOperationsForFragment(this._environment, fragmentNode, fragmentOwner);
|
342
587
|
|
343
|
-
|
344
|
-
var networkPromise = (_getPromiseForActiveR = getPromiseForActiveRequest(environment, fragmentOwner)) !== null && _getPromiseForActiveR !== void 0 ? _getPromiseForActiveR : getPromiseForPendingOperationAffectingOwner(environment, fragmentOwner);
|
345
|
-
|
346
|
-
if (!networkPromise) {
|
588
|
+
if (pendingOperationsResult == null) {
|
347
589
|
return null;
|
348
590
|
} // When the Promise for the request resolves, we need to make sure to
|
349
591
|
// update the cache with the latest data available in the store before
|
350
592
|
// resolving the Promise
|
351
593
|
|
352
594
|
|
595
|
+
var networkPromise = pendingOperationsResult.promise;
|
596
|
+
var pendingOperations = pendingOperationsResult.pendingOperations;
|
353
597
|
var promise = networkPromise.then(function () {
|
354
|
-
|
598
|
+
_this8._cache["delete"](cacheKey);
|
355
599
|
})["catch"](function (error) {
|
356
|
-
|
357
|
-
});
|
600
|
+
_this8._cache["delete"](cacheKey);
|
601
|
+
}); // $FlowExpectedError[prop-missing] Expando to annotate Promises.
|
358
602
|
|
359
|
-
|
603
|
+
promise.displayName = networkPromise.displayName;
|
360
604
|
|
605
|
+
this._cache.set(cacheKey, {
|
606
|
+
kind: 'pending',
|
607
|
+
pendingOperations: pendingOperations,
|
608
|
+
promise: promise,
|
609
|
+
result: fragmentResult
|
610
|
+
});
|
361
611
|
|
362
|
-
|
363
|
-
|
612
|
+
return {
|
613
|
+
promise: promise,
|
614
|
+
pendingOperations: pendingOperations
|
615
|
+
};
|
364
616
|
};
|
365
617
|
|
366
|
-
|
618
|
+
_proto2._updatePluralSnapshot = function _updatePluralSnapshot(cacheKey, baseSnapshots, latestSnapshot, idx, storeEpoch) {
|
619
|
+
var _currentFragmentResul;
|
620
|
+
|
367
621
|
var currentFragmentResult = this._cache.get(cacheKey);
|
368
622
|
|
369
623
|
if (isPromise(currentFragmentResult)) {
|
@@ -371,7 +625,7 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
371
625
|
return;
|
372
626
|
}
|
373
627
|
|
374
|
-
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;
|
375
629
|
|
376
630
|
if (currentSnapshot && !Array.isArray(currentSnapshot)) {
|
377
631
|
reportInvalidCachedData(latestSnapshot.selector.node.name);
|
@@ -381,7 +635,10 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
|
|
381
635
|
var nextSnapshots = currentSnapshot ? (0, _toConsumableArray2["default"])(currentSnapshot) : (0, _toConsumableArray2["default"])(baseSnapshots);
|
382
636
|
nextSnapshots[idx] = latestSnapshot;
|
383
637
|
|
384
|
-
this._cache.set(cacheKey,
|
638
|
+
this._cache.set(cacheKey, {
|
639
|
+
kind: 'done',
|
640
|
+
result: getFragmentResult(cacheKey, nextSnapshots, storeEpoch)
|
641
|
+
});
|
385
642
|
};
|
386
643
|
|
387
644
|
return FragmentResourceImpl;
|