1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | 'use strict';
|
13 |
|
14 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
15 |
|
16 | var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
17 |
|
18 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
19 |
|
20 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
21 |
|
22 | var LRUCache = require('./LRUCache');
|
23 |
|
24 | var invariant = require("fbjs/lib/invariant");
|
25 |
|
26 | var _require = require('relay-runtime'),
|
27 | isPromise = _require.isPromise;
|
28 |
|
29 | var CACHE_CAPACITY = 1000;
|
30 | var DEFAULT_FETCH_POLICY = 'store-or-network';
|
31 | var DATA_RETENTION_TIMEOUT = 30 * 1000;
|
32 | var WEAKMAP_SUPPORTED = typeof WeakMap === 'function';
|
33 |
|
34 | function getQueryCacheKey(operation, fetchPolicy, renderPolicy) {
|
35 | return "".concat(fetchPolicy, "-").concat(renderPolicy, "-").concat(operation.request.identifier);
|
36 | }
|
37 |
|
38 | function getQueryResult(operation, cacheKey) {
|
39 | var rootFragmentRef = {
|
40 | __id: operation.fragment.dataID,
|
41 | __fragments: (0, _defineProperty2["default"])({}, operation.fragment.node.name, operation.request.variables),
|
42 | __fragmentOwner: operation.request
|
43 | };
|
44 | return {
|
45 | cacheKey: cacheKey,
|
46 | fragmentNode: operation.request.node.fragment,
|
47 | fragmentRef: rootFragmentRef,
|
48 | operation: operation
|
49 | };
|
50 | }
|
51 |
|
52 | var nextID = 200000;
|
53 |
|
54 | function createCacheEntry(cacheKey, operation, value, networkSubscription, onDispose) {
|
55 | var currentValue = value;
|
56 | var retainCount = 0;
|
57 | var permanentlyRetained = false;
|
58 | var retainDisposable = null;
|
59 | var releaseTemporaryRetain = null;
|
60 | var currentNetworkSubscription = networkSubscription;
|
61 |
|
62 | var retain = function retain(environment) {
|
63 | retainCount++;
|
64 |
|
65 | if (retainCount === 1) {
|
66 | retainDisposable = environment.retain(operation);
|
67 | }
|
68 |
|
69 | return {
|
70 | dispose: function dispose() {
|
71 | retainCount = Math.max(0, retainCount - 1);
|
72 |
|
73 | if (retainCount === 0) {
|
74 | !(retainDisposable != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected disposable to release query to be defined.' + "If you're seeing this, this is likely a bug in Relay.") : invariant(false) : void 0;
|
75 | retainDisposable.dispose();
|
76 | retainDisposable = null;
|
77 | }
|
78 |
|
79 | onDispose(cacheEntry);
|
80 | }
|
81 | };
|
82 | };
|
83 |
|
84 | var cacheEntry = {
|
85 | cacheKey: cacheKey,
|
86 | id: nextID++,
|
87 | getValue: function getValue() {
|
88 | return currentValue;
|
89 | },
|
90 | setValue: function setValue(val) {
|
91 | currentValue = val;
|
92 | },
|
93 | getRetainCount: function getRetainCount() {
|
94 | return retainCount;
|
95 | },
|
96 | getNetworkSubscription: function getNetworkSubscription() {
|
97 | return currentNetworkSubscription;
|
98 | },
|
99 | setNetworkSubscription: function setNetworkSubscription(subscription) {
|
100 | if (currentNetworkSubscription != null) {
|
101 | currentNetworkSubscription.unsubscribe();
|
102 | }
|
103 |
|
104 | currentNetworkSubscription = subscription;
|
105 | },
|
106 | temporaryRetain: function temporaryRetain(environment) {
|
107 |
|
108 |
|
109 | if (environment.isServer()) {
|
110 | return {
|
111 | dispose: function dispose() {}
|
112 | };
|
113 | }
|
114 |
|
115 | if (permanentlyRetained === true) {
|
116 | return {
|
117 | dispose: function dispose() {}
|
118 | };
|
119 | }
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 | var disposable = retain(environment);
|
128 | var releaseQueryTimeout = null;
|
129 |
|
130 | var localReleaseTemporaryRetain = function localReleaseTemporaryRetain() {
|
131 | clearTimeout(releaseQueryTimeout);
|
132 | releaseQueryTimeout = null;
|
133 | releaseTemporaryRetain = null;
|
134 | disposable.dispose();
|
135 | };
|
136 |
|
137 | releaseQueryTimeout = setTimeout(localReleaseTemporaryRetain, DATA_RETENTION_TIMEOUT);
|
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 | if (releaseTemporaryRetain != null) {
|
146 | releaseTemporaryRetain();
|
147 | }
|
148 |
|
149 | releaseTemporaryRetain = localReleaseTemporaryRetain;
|
150 | return {
|
151 | dispose: function dispose() {
|
152 | if (permanentlyRetained === true) {
|
153 | return;
|
154 | }
|
155 |
|
156 | releaseTemporaryRetain && releaseTemporaryRetain();
|
157 | }
|
158 | };
|
159 | },
|
160 | permanentRetain: function permanentRetain(environment) {
|
161 | var disposable = retain(environment);
|
162 |
|
163 | if (releaseTemporaryRetain != null) {
|
164 | releaseTemporaryRetain();
|
165 | releaseTemporaryRetain = null;
|
166 | }
|
167 |
|
168 | permanentlyRetained = true;
|
169 | return {
|
170 | dispose: function dispose() {
|
171 | disposable.dispose();
|
172 |
|
173 | if (retainCount <= 0 && currentNetworkSubscription != null) {
|
174 | currentNetworkSubscription.unsubscribe();
|
175 | }
|
176 |
|
177 | permanentlyRetained = false;
|
178 | }
|
179 | };
|
180 | }
|
181 | };
|
182 | return cacheEntry;
|
183 | }
|
184 |
|
185 | var QueryResourceImpl = function () {
|
186 | function QueryResourceImpl(environment) {
|
187 | var _this = this;
|
188 |
|
189 | (0, _defineProperty2["default"])(this, "_clearCacheEntry", function (cacheEntry) {
|
190 | if (cacheEntry.getRetainCount() <= 0) {
|
191 | _this._cache["delete"](cacheEntry.cacheKey);
|
192 | }
|
193 | });
|
194 | this._environment = environment;
|
195 | this._cache = LRUCache.create(CACHE_CAPACITY);
|
196 | }
|
197 | |
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 | var _proto = QueryResourceImpl.prototype;
|
205 |
|
206 | _proto.prepare = function prepare(operation, fetchObservable, maybeFetchPolicy, maybeRenderPolicy, observer, cacheKeyBuster, profilerContext) {
|
207 | var environment = this._environment;
|
208 | var fetchPolicy = maybeFetchPolicy !== null && maybeFetchPolicy !== void 0 ? maybeFetchPolicy : DEFAULT_FETCH_POLICY;
|
209 | var renderPolicy = maybeRenderPolicy !== null && maybeRenderPolicy !== void 0 ? maybeRenderPolicy : environment.UNSTABLE_getDefaultRenderPolicy();
|
210 | var cacheKey = getQueryCacheKey(operation, fetchPolicy, renderPolicy);
|
211 |
|
212 | if (cacheKeyBuster != null) {
|
213 | cacheKey += "-".concat(cacheKeyBuster);
|
214 | }
|
215 |
|
216 |
|
217 |
|
218 | var cacheEntry = this._cache.get(cacheKey);
|
219 |
|
220 | var temporaryRetainDisposable = null;
|
221 |
|
222 | if (cacheEntry == null) {
|
223 |
|
224 |
|
225 |
|
226 | cacheEntry = this._fetchAndSaveQuery(cacheKey, operation, fetchObservable, fetchPolicy, renderPolicy, profilerContext, _objectSpread({}, observer, {
|
227 | unsubscribe: function unsubscribe(subscription) {
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 | if (temporaryRetainDisposable != null) {
|
234 | temporaryRetainDisposable.dispose();
|
235 | }
|
236 |
|
237 | var observerUnsubscribe = observer === null || observer === void 0 ? void 0 : observer.unsubscribe;
|
238 | observerUnsubscribe && observerUnsubscribe(subscription);
|
239 | }
|
240 | }));
|
241 | }
|
242 |
|
243 |
|
244 |
|
245 |
|
246 |
|
247 |
|
248 | temporaryRetainDisposable = cacheEntry.temporaryRetain(environment);
|
249 | var cachedValue = cacheEntry.getValue();
|
250 |
|
251 | if (isPromise(cachedValue) || cachedValue instanceof Error) {
|
252 | throw cachedValue;
|
253 | }
|
254 |
|
255 | return cachedValue;
|
256 | }
|
257 | |
258 |
|
259 |
|
260 |
|
261 |
|
262 | ;
|
263 |
|
264 | _proto.retain = function retain(queryResult, profilerContext) {
|
265 | var environment = this._environment;
|
266 | var cacheKey = queryResult.cacheKey,
|
267 | operation = queryResult.operation;
|
268 |
|
269 | var cacheEntry = this._getOrCreateCacheEntry(cacheKey, operation, queryResult, null);
|
270 |
|
271 | var disposable = cacheEntry.permanentRetain(environment);
|
272 |
|
273 | environment.__log({
|
274 | name: 'queryresource.retain',
|
275 | profilerContext: profilerContext,
|
276 | resourceID: cacheEntry.id
|
277 | });
|
278 |
|
279 | return {
|
280 | dispose: function dispose() {
|
281 | disposable.dispose();
|
282 | }
|
283 | };
|
284 | };
|
285 |
|
286 | _proto.getCacheEntry = function getCacheEntry(operation, fetchPolicy, maybeRenderPolicy) {
|
287 | var environment = this._environment;
|
288 | var renderPolicy = maybeRenderPolicy !== null && maybeRenderPolicy !== void 0 ? maybeRenderPolicy : environment.UNSTABLE_getDefaultRenderPolicy();
|
289 | var cacheKey = getQueryCacheKey(operation, fetchPolicy, renderPolicy);
|
290 | return this._cache.get(cacheKey);
|
291 | };
|
292 |
|
293 | _proto._getOrCreateCacheEntry = function _getOrCreateCacheEntry(cacheKey, operation, value, networkSubscription) {
|
294 | var cacheEntry = this._cache.get(cacheKey);
|
295 |
|
296 | if (cacheEntry == null) {
|
297 | cacheEntry = createCacheEntry(cacheKey, operation, value, networkSubscription, this._clearCacheEntry);
|
298 |
|
299 | this._cache.set(cacheKey, cacheEntry);
|
300 | }
|
301 |
|
302 | return cacheEntry;
|
303 | };
|
304 |
|
305 | _proto._fetchAndSaveQuery = function _fetchAndSaveQuery(cacheKey, operation, fetchObservable, fetchPolicy, renderPolicy, profilerContext, observer) {
|
306 | var _this2 = this;
|
307 |
|
308 | var environment = this._environment;
|
309 |
|
310 |
|
311 |
|
312 |
|
313 | var queryAvailability = environment.check(operation);
|
314 | var queryStatus = queryAvailability.status;
|
315 | var hasFullQuery = queryStatus === 'available';
|
316 | var canPartialRender = hasFullQuery || renderPolicy === 'partial' && queryStatus !== 'stale';
|
317 | var shouldFetch;
|
318 | var shouldAllowRender;
|
319 |
|
320 | var resolveNetworkPromise = function resolveNetworkPromise() {};
|
321 |
|
322 | switch (fetchPolicy) {
|
323 | case 'store-only':
|
324 | {
|
325 | shouldFetch = false;
|
326 | shouldAllowRender = true;
|
327 | break;
|
328 | }
|
329 |
|
330 | case 'store-or-network':
|
331 | {
|
332 | shouldFetch = !hasFullQuery;
|
333 | shouldAllowRender = canPartialRender;
|
334 | break;
|
335 | }
|
336 |
|
337 | case 'store-and-network':
|
338 | {
|
339 | shouldFetch = true;
|
340 | shouldAllowRender = canPartialRender;
|
341 | break;
|
342 | }
|
343 |
|
344 | case 'network-only':
|
345 | default:
|
346 | {
|
347 | shouldFetch = true;
|
348 | shouldAllowRender = false;
|
349 | break;
|
350 | }
|
351 | }
|
352 |
|
353 |
|
354 |
|
355 |
|
356 |
|
357 | if (shouldAllowRender) {
|
358 | var queryResult = getQueryResult(operation, cacheKey);
|
359 |
|
360 | var _cacheEntry = createCacheEntry(cacheKey, operation, queryResult, null, this._clearCacheEntry);
|
361 |
|
362 | this._cache.set(cacheKey, _cacheEntry);
|
363 | }
|
364 |
|
365 | if (shouldFetch) {
|
366 | var _queryResult = getQueryResult(operation, cacheKey);
|
367 |
|
368 | var networkSubscription;
|
369 | fetchObservable.subscribe({
|
370 | start: function start(subscription) {
|
371 | networkSubscription = subscription;
|
372 |
|
373 | var cacheEntry = _this2._cache.get(cacheKey);
|
374 |
|
375 | if (cacheEntry) {
|
376 | cacheEntry.setNetworkSubscription(networkSubscription);
|
377 | }
|
378 |
|
379 | var observerStart = observer === null || observer === void 0 ? void 0 : observer.start;
|
380 | observerStart && observerStart(subscription);
|
381 | },
|
382 | next: function next() {
|
383 | var snapshot = environment.lookup(operation.fragment);
|
384 |
|
385 | var cacheEntry = _this2._getOrCreateCacheEntry(cacheKey, operation, _queryResult, networkSubscription);
|
386 |
|
387 | cacheEntry.setValue(_queryResult);
|
388 | resolveNetworkPromise();
|
389 | var observerNext = observer === null || observer === void 0 ? void 0 : observer.next;
|
390 | observerNext && observerNext(snapshot);
|
391 | },
|
392 | error: function error(_error) {
|
393 | var cacheEntry = _this2._getOrCreateCacheEntry(cacheKey, operation, _error, networkSubscription);
|
394 |
|
395 | cacheEntry.setValue(_error);
|
396 | resolveNetworkPromise();
|
397 | networkSubscription = null;
|
398 | cacheEntry.setNetworkSubscription(null);
|
399 | var observerError = observer === null || observer === void 0 ? void 0 : observer.error;
|
400 | observerError && observerError(_error);
|
401 | },
|
402 | complete: function complete() {
|
403 | resolveNetworkPromise();
|
404 | networkSubscription = null;
|
405 |
|
406 | var cacheEntry = _this2._cache.get(cacheKey);
|
407 |
|
408 | if (cacheEntry) {
|
409 | cacheEntry.setNetworkSubscription(null);
|
410 | }
|
411 |
|
412 | var observerComplete = observer === null || observer === void 0 ? void 0 : observer.complete;
|
413 | observerComplete && observerComplete();
|
414 | },
|
415 | unsubscribe: observer === null || observer === void 0 ? void 0 : observer.unsubscribe
|
416 | });
|
417 |
|
418 | var _cacheEntry2 = this._cache.get(cacheKey);
|
419 |
|
420 | if (!_cacheEntry2) {
|
421 | var networkPromise = new Promise(function (resolve) {
|
422 | resolveNetworkPromise = resolve;
|
423 | });
|
424 |
|
425 | networkPromise.displayName = 'Relay(' + operation.fragment.node.name + ')';
|
426 | _cacheEntry2 = createCacheEntry(cacheKey, operation, networkPromise, networkSubscription, this._clearCacheEntry);
|
427 |
|
428 | this._cache.set(cacheKey, _cacheEntry2);
|
429 | }
|
430 | } else {
|
431 | var observerComplete = observer === null || observer === void 0 ? void 0 : observer.complete;
|
432 | observerComplete && observerComplete();
|
433 | }
|
434 |
|
435 | var cacheEntry = this._cache.get(cacheKey);
|
436 |
|
437 | !(cacheEntry != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected to have cached a result when attempting to fetch query.' + "If you're seeing this, this is likely a bug in Relay.") : invariant(false) : void 0;
|
438 |
|
439 | environment.__log({
|
440 | name: 'queryresource.fetch',
|
441 | resourceID: cacheEntry.id,
|
442 | operation: operation,
|
443 | profilerContext: profilerContext,
|
444 | fetchPolicy: fetchPolicy,
|
445 | renderPolicy: renderPolicy,
|
446 | queryAvailability: queryAvailability,
|
447 | shouldFetch: shouldFetch
|
448 | });
|
449 |
|
450 | return cacheEntry;
|
451 | };
|
452 |
|
453 | return QueryResourceImpl;
|
454 | }();
|
455 |
|
456 | function createQueryResource(environment) {
|
457 | return new QueryResourceImpl(environment);
|
458 | }
|
459 |
|
460 | var dataResources = WEAKMAP_SUPPORTED ? new WeakMap() : new Map();
|
461 |
|
462 | function getQueryResourceForEnvironment(environment) {
|
463 | var cached = dataResources.get(environment);
|
464 |
|
465 | if (cached) {
|
466 | return cached;
|
467 | }
|
468 |
|
469 | var newDataResource = createQueryResource(environment);
|
470 | dataResources.set(environment, newDataResource);
|
471 | return newDataResource;
|
472 | }
|
473 |
|
474 | module.exports = {
|
475 | createQueryResource: createQueryResource,
|
476 | getQueryResourceForEnvironment: getQueryResourceForEnvironment
|
477 | }; |
\ | No newline at end of file |