1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | 'use strict';
|
12 |
|
13 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
14 |
|
15 | var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));
|
16 |
|
17 | var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
18 |
|
19 | var LRUCache = require('./LRUCache');
|
20 |
|
21 | var invariant = require("fbjs/lib/invariant");
|
22 |
|
23 | var mapObject = require("fbjs/lib/mapObject");
|
24 |
|
25 | var warning = require("fbjs/lib/warning");
|
26 |
|
27 | var _require = require('relay-runtime'),
|
28 | getPromiseForRequestInFlight = _require.__internal.getPromiseForRequestInFlight,
|
29 | getFragmentIdentifier = _require.getFragmentIdentifier,
|
30 | getSelector = _require.getSelector,
|
31 | isPromise = _require.isPromise,
|
32 | recycleNodesInto = _require.recycleNodesInto;
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | var CACHE_CAPACITY = 1000000;
|
38 |
|
39 | function isMissingData(snapshot) {
|
40 | if (Array.isArray(snapshot)) {
|
41 | return snapshot.some(function (s) {
|
42 | return s.isMissingData;
|
43 | });
|
44 | }
|
45 |
|
46 | return snapshot.isMissingData;
|
47 | }
|
48 |
|
49 | function getFragmentResult(cacheKey, snapshot) {
|
50 | if (Array.isArray(snapshot)) {
|
51 | return {
|
52 | cacheKey: cacheKey,
|
53 | snapshot: snapshot,
|
54 | data: snapshot.map(function (s) {
|
55 | return s.data;
|
56 | })
|
57 | };
|
58 | }
|
59 |
|
60 | return {
|
61 | cacheKey: cacheKey,
|
62 | snapshot: snapshot,
|
63 | data: snapshot.data
|
64 | };
|
65 | }
|
66 |
|
67 | function getPromiseForPendingOperationAffectingOwner(environment, request) {
|
68 | return environment.getOperationTracker().getPromiseForPendingOperationsAffectingOwner(request);
|
69 | }
|
70 |
|
71 | var FragmentResourceImpl =
|
72 |
|
73 | function () {
|
74 | function FragmentResourceImpl(environment) {
|
75 | this._environment = environment;
|
76 | this._cache = LRUCache.create(CACHE_CAPACITY);
|
77 | }
|
78 | |
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 | var _proto = FragmentResourceImpl.prototype;
|
86 |
|
87 | _proto.read = function read(fragmentNode, fragmentRef, componentDisplayName, fragmentKey) {
|
88 | return this.readWithIdentifier(fragmentNode, fragmentRef, getFragmentIdentifier(fragmentNode, fragmentRef), componentDisplayName, fragmentKey);
|
89 | }
|
90 | |
91 |
|
92 |
|
93 |
|
94 |
|
95 | ;
|
96 |
|
97 | _proto.readWithIdentifier = function readWithIdentifier(fragmentNode, fragmentRef, fragmentIdentifier, componentDisplayName, fragmentKey) {
|
98 | var _fragmentNode$metadat, _fragmentOwner$node$p;
|
99 |
|
100 | var environment = this._environment;
|
101 |
|
102 |
|
103 |
|
104 | if (fragmentRef == null) {
|
105 | return {
|
106 | cacheKey: fragmentIdentifier,
|
107 | data: null,
|
108 | snapshot: null
|
109 | };
|
110 | }
|
111 |
|
112 |
|
113 |
|
114 | if ((fragmentNode === null || fragmentNode === void 0 ? void 0 : (_fragmentNode$metadat = fragmentNode.metadata) === null || _fragmentNode$metadat === void 0 ? void 0 : _fragmentNode$metadat.plural) === true) {
|
115 | !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 |
|
117 | if (fragmentRef.length === 0) {
|
118 | return {
|
119 | cacheKey: fragmentIdentifier,
|
120 | data: [],
|
121 | snapshot: []
|
122 | };
|
123 | }
|
124 | }
|
125 |
|
126 |
|
127 |
|
128 | var cachedValue = this._cache.get(fragmentIdentifier);
|
129 |
|
130 | if (cachedValue != null) {
|
131 | if (isPromise(cachedValue) || cachedValue instanceof Error) {
|
132 | throw cachedValue;
|
133 | }
|
134 |
|
135 | return getFragmentResult(fragmentIdentifier, cachedValue);
|
136 | }
|
137 |
|
138 |
|
139 |
|
140 | var fragmentSelector = getSelector(fragmentNode, fragmentRef);
|
141 | !(fragmentSelector != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected to have received a valid ' + 'fragment reference for fragment `%s` declared in `%s`. Make sure ' + "that `%s`'s parent is passing the right fragment reference prop.", fragmentNode.name, componentDisplayName, componentDisplayName) : invariant(false) : void 0;
|
142 | var snapshot = fragmentSelector.kind === 'PluralReaderSelector' ? fragmentSelector.selectors.map(function (s) {
|
143 | return environment.lookup(s);
|
144 | }) : environment.lookup(fragmentSelector);
|
145 | var fragmentOwner = fragmentSelector.kind === 'PluralReaderSelector' ? fragmentSelector.selectors[0].owner : fragmentSelector.owner;
|
146 | var parentQueryName = (_fragmentOwner$node$p = fragmentOwner.node.params.name) !== null && _fragmentOwner$node$p !== void 0 ? _fragmentOwner$node$p : 'Unknown Parent Query';
|
147 |
|
148 | if (!isMissingData(snapshot)) {
|
149 | this._cache.set(fragmentIdentifier, snapshot);
|
150 |
|
151 | return getFragmentResult(fragmentIdentifier, snapshot);
|
152 | }
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 | var networkPromise = this._getAndSavePromiseForFragmentRequestInFlight(fragmentIdentifier, fragmentOwner);
|
160 |
|
161 | if (networkPromise != null) {
|
162 | throw networkPromise;
|
163 | }
|
164 |
|
165 |
|
166 |
|
167 |
|
168 | process.env.NODE_ENV !== "production" ? 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.', fragmentNode.name, componentDisplayName, parentQueryName, parentQueryName) : void 0;
|
169 | return getFragmentResult(fragmentIdentifier, snapshot);
|
170 | };
|
171 |
|
172 | _proto.readSpec = function readSpec(fragmentNodes, fragmentRefs, componentDisplayName) {
|
173 | var _this = this;
|
174 |
|
175 | return mapObject(fragmentNodes, function (fragmentNode, fragmentKey) {
|
176 | var fragmentRef = fragmentRefs[fragmentKey];
|
177 | return _this.read(fragmentNode, fragmentRef, componentDisplayName, fragmentKey);
|
178 | });
|
179 | };
|
180 |
|
181 | _proto.subscribe = function subscribe(fragmentResult, callback) {
|
182 | var _this2 = this;
|
183 |
|
184 | var environment = this._environment;
|
185 | var cacheKey = fragmentResult.cacheKey;
|
186 | var renderedSnapshot = fragmentResult.snapshot;
|
187 |
|
188 | if (!renderedSnapshot) {
|
189 | return {
|
190 | dispose: function dispose() {}
|
191 | };
|
192 | }
|
193 |
|
194 |
|
195 |
|
196 | var _this$checkMissedUpda = this.checkMissedUpdates(fragmentResult),
|
197 | didMissUpdates = _this$checkMissedUpda[0],
|
198 | currentSnapshot = _this$checkMissedUpda[1];
|
199 |
|
200 |
|
201 |
|
202 | if (didMissUpdates) {
|
203 | callback();
|
204 | }
|
205 |
|
206 |
|
207 | var dataSubscriptions = [];
|
208 |
|
209 | if (Array.isArray(renderedSnapshot)) {
|
210 | !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;
|
211 | currentSnapshot.forEach(function (snapshot, idx) {
|
212 | dataSubscriptions.push(environment.subscribe(snapshot, function (latestSnapshot) {
|
213 | _this2._updatePluralSnapshot(cacheKey, latestSnapshot, idx);
|
214 |
|
215 | callback();
|
216 | }));
|
217 | });
|
218 | } else {
|
219 | !(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;
|
220 | dataSubscriptions.push(environment.subscribe(currentSnapshot, function (latestSnapshot) {
|
221 | _this2._cache.set(cacheKey, latestSnapshot);
|
222 |
|
223 | callback();
|
224 | }));
|
225 | }
|
226 |
|
227 | return {
|
228 | dispose: function dispose() {
|
229 | dataSubscriptions.map(function (s) {
|
230 | return s.dispose();
|
231 | });
|
232 |
|
233 | _this2._cache["delete"](cacheKey);
|
234 | }
|
235 | };
|
236 | };
|
237 |
|
238 | _proto.subscribeSpec = function subscribeSpec(fragmentResults, callback) {
|
239 | var _this3 = this;
|
240 |
|
241 | var disposables = Object.keys(fragmentResults).map(function (key) {
|
242 | return _this3.subscribe(fragmentResults[key], callback);
|
243 | });
|
244 | return {
|
245 | dispose: function dispose() {
|
246 | disposables.forEach(function (disposable) {
|
247 | disposable.dispose();
|
248 | });
|
249 | }
|
250 | };
|
251 | };
|
252 |
|
253 | _proto.checkMissedUpdates = function checkMissedUpdates(fragmentResult) {
|
254 | var environment = this._environment;
|
255 | var cacheKey = fragmentResult.cacheKey;
|
256 | var renderedSnapshot = fragmentResult.snapshot;
|
257 |
|
258 | if (!renderedSnapshot) {
|
259 | return [false, null];
|
260 | }
|
261 |
|
262 | var didMissUpdates = false;
|
263 |
|
264 | if (Array.isArray(renderedSnapshot)) {
|
265 | var currentSnapshots = [];
|
266 | renderedSnapshot.forEach(function (snapshot, idx) {
|
267 | var currentSnapshot = environment.lookup(snapshot.selector);
|
268 | var renderData = snapshot.data;
|
269 | var currentData = currentSnapshot.data;
|
270 | var updatedData = recycleNodesInto(renderData, currentData);
|
271 |
|
272 | if (updatedData !== renderData) {
|
273 | currentSnapshot = (0, _objectSpread2["default"])({}, currentSnapshot, {
|
274 | data: updatedData
|
275 | });
|
276 | didMissUpdates = true;
|
277 | }
|
278 |
|
279 | currentSnapshots[idx] = currentSnapshot;
|
280 | });
|
281 |
|
282 | if (didMissUpdates) {
|
283 | this._cache.set(cacheKey, currentSnapshots);
|
284 | }
|
285 |
|
286 | return [didMissUpdates, currentSnapshots];
|
287 | }
|
288 |
|
289 | var currentSnapshot = environment.lookup(renderedSnapshot.selector);
|
290 | var renderData = renderedSnapshot.data;
|
291 | var currentData = currentSnapshot.data;
|
292 | var updatedData = recycleNodesInto(renderData, currentData);
|
293 |
|
294 | if (updatedData !== renderData) {
|
295 | currentSnapshot = (0, _objectSpread2["default"])({}, currentSnapshot, {
|
296 | data: updatedData
|
297 | });
|
298 |
|
299 | this._cache.set(cacheKey, currentSnapshot);
|
300 |
|
301 | didMissUpdates = true;
|
302 | }
|
303 |
|
304 | return [didMissUpdates, currentSnapshot];
|
305 | };
|
306 |
|
307 | _proto.checkMissedUpdatesSpec = function checkMissedUpdatesSpec(fragmentResults) {
|
308 | var _this4 = this;
|
309 |
|
310 | return Object.keys(fragmentResults).some(function (key) {
|
311 | return _this4.checkMissedUpdates(fragmentResults[key])[0];
|
312 | });
|
313 | };
|
314 |
|
315 | _proto._getAndSavePromiseForFragmentRequestInFlight = function _getAndSavePromiseForFragmentRequestInFlight(cacheKey, fragmentOwner) {
|
316 | var _this5 = this;
|
317 |
|
318 | var _getPromiseForRequest;
|
319 |
|
320 | var environment = this._environment;
|
321 | var networkPromise = (_getPromiseForRequest = getPromiseForRequestInFlight(environment, fragmentOwner)) !== null && _getPromiseForRequest !== void 0 ? _getPromiseForRequest : getPromiseForPendingOperationAffectingOwner(environment, fragmentOwner);
|
322 |
|
323 | if (!networkPromise) {
|
324 | return null;
|
325 | }
|
326 |
|
327 |
|
328 |
|
329 |
|
330 | var promise = networkPromise.then(function () {
|
331 | _this5._cache["delete"](cacheKey);
|
332 | })["catch"](function (error) {
|
333 | _this5._cache.set(cacheKey, error);
|
334 | });
|
335 |
|
336 | this._cache.set(cacheKey, promise);
|
337 |
|
338 |
|
339 | promise.displayName = 'Relay(' + fragmentOwner.node.params.name + ')';
|
340 | return promise;
|
341 | };
|
342 |
|
343 | _proto._updatePluralSnapshot = function _updatePluralSnapshot(cacheKey, latestSnapshot, idx) {
|
344 | var currentSnapshots = this._cache.get(cacheKey);
|
345 |
|
346 | !Array.isArray(currentSnapshots) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected to find cached data for plural fragment when ' + 'recieving a subscription. ' + "If you're seeing this, this is likely a bug in Relay.") : invariant(false) : void 0;
|
347 | var nextSnapshots = (0, _toConsumableArray2["default"])(currentSnapshots);
|
348 | nextSnapshots[idx] = latestSnapshot;
|
349 |
|
350 | this._cache.set(cacheKey, nextSnapshots);
|
351 | };
|
352 |
|
353 | return FragmentResourceImpl;
|
354 | }();
|
355 |
|
356 | function createFragmentResource(environment) {
|
357 | return new FragmentResourceImpl(environment);
|
358 | }
|
359 |
|
360 | var dataResources = new Map();
|
361 |
|
362 | function getFragmentResourceForEnvironment(environment) {
|
363 | var cached = dataResources.get(environment);
|
364 |
|
365 | if (cached) {
|
366 | return cached;
|
367 | }
|
368 |
|
369 | var newDataResource = createFragmentResource(environment);
|
370 | dataResources.set(environment, newDataResource);
|
371 | return newDataResource;
|
372 | }
|
373 |
|
374 | module.exports = {
|
375 | createFragmentResource: createFragmentResource,
|
376 | getFragmentResourceForEnvironment: getFragmentResourceForEnvironment
|
377 | }; |
\ | No newline at end of file |