UNPKG

41 kBJavaScriptView Raw
1exports.__esModule = true;
2exports.assertIdValue = assertIdValue;
3exports.defaultDataIdFromObject = defaultDataIdFromObject;
4exports.defaultNormalizedCacheFactory = defaultNormalizedCacheFactory$1;
5exports.enhanceErrorWithDocument = enhanceErrorWithDocument;
6exports.WriteError = exports.StoreWriter = exports.StoreReader = exports.ObjectCache = exports.IntrospectionFragmentMatcher = exports.InMemoryCache = exports.HeuristicFragmentMatcher = void 0;
7
8var _tslib = require("tslib");
9
10var _apolloCache = require("apollo-cache");
11
12var _apolloUtilities = require("apollo-utilities");
13
14var _optimism = require("optimism");
15
16var _tsInvariant = require("ts-invariant");
17
18var haveWarned = false;
19
20function shouldWarn() {
21 var answer = !haveWarned;
22
23 if (!(0, _apolloUtilities.isTest)()) {
24 haveWarned = true;
25 }
26
27 return answer;
28}
29
30var HeuristicFragmentMatcher = function () {
31 function HeuristicFragmentMatcher() {}
32
33 HeuristicFragmentMatcher.prototype.ensureReady = function () {
34 return Promise.resolve();
35 };
36
37 HeuristicFragmentMatcher.prototype.canBypassInit = function () {
38 return true;
39 };
40
41 HeuristicFragmentMatcher.prototype.match = function (idValue, typeCondition, context) {
42 var obj = context.store.get(idValue.id);
43 var isRootQuery = idValue.id === 'ROOT_QUERY';
44
45 if (!obj) {
46 return isRootQuery;
47 }
48
49 var _a = obj.__typename,
50 __typename = _a === void 0 ? isRootQuery && 'Query' : _a;
51
52 if (!__typename) {
53 if (shouldWarn()) {
54 process.env.NODE_ENV === "production" || _tsInvariant.invariant.warn("You're using fragments in your queries, but either don't have the addTypename:\n true option set in Apollo Client, or you are trying to write a fragment to the store without the __typename.\n Please turn on the addTypename option and include __typename when writing fragments so that Apollo Client\n can accurately match fragments.");
55 process.env.NODE_ENV === "production" || _tsInvariant.invariant.warn('Could not find __typename on Fragment ', typeCondition, obj);
56 process.env.NODE_ENV === "production" || _tsInvariant.invariant.warn("DEPRECATION WARNING: using fragments without __typename is unsupported behavior " + "and will be removed in future versions of Apollo client. You should fix this and set addTypename to true now.");
57 }
58
59 return 'heuristic';
60 }
61
62 if (__typename === typeCondition) {
63 return true;
64 }
65
66 if (shouldWarn()) {
67 process.env.NODE_ENV === "production" || _tsInvariant.invariant.error('You are using the simple (heuristic) fragment matcher, but your ' + 'queries contain union or interface types. Apollo Client will not be ' + 'able to accurately map fragments. To make this error go away, use ' + 'the `IntrospectionFragmentMatcher` as described in the docs: ' + 'https://www.apollographql.com/docs/react/advanced/fragments.html#fragment-matcher');
68 }
69
70 return 'heuristic';
71 };
72
73 return HeuristicFragmentMatcher;
74}();
75
76exports.HeuristicFragmentMatcher = HeuristicFragmentMatcher;
77
78var IntrospectionFragmentMatcher = function () {
79 function IntrospectionFragmentMatcher(options) {
80 if (options && options.introspectionQueryResultData) {
81 this.possibleTypesMap = this.parseIntrospectionResult(options.introspectionQueryResultData);
82 this.isReady = true;
83 } else {
84 this.isReady = false;
85 }
86
87 this.match = this.match.bind(this);
88 }
89
90 IntrospectionFragmentMatcher.prototype.match = function (idValue, typeCondition, context) {
91 process.env.NODE_ENV === "production" ? (0, _tsInvariant.invariant)(this.isReady, 1) : (0, _tsInvariant.invariant)(this.isReady, 'FragmentMatcher.match() was called before FragmentMatcher.init()');
92 var obj = context.store.get(idValue.id);
93 var isRootQuery = idValue.id === 'ROOT_QUERY';
94
95 if (!obj) {
96 return isRootQuery;
97 }
98
99 var _a = obj.__typename,
100 __typename = _a === void 0 ? isRootQuery && 'Query' : _a;
101
102 process.env.NODE_ENV === "production" ? (0, _tsInvariant.invariant)(__typename, 2) : (0, _tsInvariant.invariant)(__typename, "Cannot match fragment because __typename property is missing: " + JSON.stringify(obj));
103
104 if (__typename === typeCondition) {
105 return true;
106 }
107
108 var implementingTypes = this.possibleTypesMap[typeCondition];
109
110 if (__typename && implementingTypes && implementingTypes.indexOf(__typename) > -1) {
111 return true;
112 }
113
114 return false;
115 };
116
117 IntrospectionFragmentMatcher.prototype.parseIntrospectionResult = function (introspectionResultData) {
118 var typeMap = {};
119
120 introspectionResultData.__schema.types.forEach(function (type) {
121 if (type.kind === 'UNION' || type.kind === 'INTERFACE') {
122 typeMap[type.name] = type.possibleTypes.map(function (implementingType) {
123 return implementingType.name;
124 });
125 }
126 });
127
128 return typeMap;
129 };
130
131 return IntrospectionFragmentMatcher;
132}();
133
134exports.IntrospectionFragmentMatcher = IntrospectionFragmentMatcher;
135var hasOwn = Object.prototype.hasOwnProperty;
136
137var DepTrackingCache = function () {
138 function DepTrackingCache(data) {
139 var _this = this;
140
141 if (data === void 0) {
142 data = Object.create(null);
143 }
144
145 this.data = data;
146 this.depend = (0, _optimism.wrap)(function (dataId) {
147 return _this.data[dataId];
148 }, {
149 disposable: true,
150 makeCacheKey: function (dataId) {
151 return dataId;
152 }
153 });
154 }
155
156 DepTrackingCache.prototype.toObject = function () {
157 return this.data;
158 };
159
160 DepTrackingCache.prototype.get = function (dataId) {
161 this.depend(dataId);
162 return this.data[dataId];
163 };
164
165 DepTrackingCache.prototype.set = function (dataId, value) {
166 var oldValue = this.data[dataId];
167
168 if (value !== oldValue) {
169 this.data[dataId] = value;
170 this.depend.dirty(dataId);
171 }
172 };
173
174 DepTrackingCache.prototype.delete = function (dataId) {
175 if (hasOwn.call(this.data, dataId)) {
176 delete this.data[dataId];
177 this.depend.dirty(dataId);
178 }
179 };
180
181 DepTrackingCache.prototype.clear = function () {
182 this.replace(null);
183 };
184
185 DepTrackingCache.prototype.replace = function (newData) {
186 var _this = this;
187
188 if (newData) {
189 Object.keys(newData).forEach(function (dataId) {
190 _this.set(dataId, newData[dataId]);
191 });
192 Object.keys(this.data).forEach(function (dataId) {
193 if (!hasOwn.call(newData, dataId)) {
194 _this.delete(dataId);
195 }
196 });
197 } else {
198 Object.keys(this.data).forEach(function (dataId) {
199 _this.delete(dataId);
200 });
201 }
202 };
203
204 return DepTrackingCache;
205}();
206
207function defaultNormalizedCacheFactory(seed) {
208 return new DepTrackingCache(seed);
209}
210
211var StoreReader = function () {
212 function StoreReader(_a) {
213 var _this = this;
214
215 var _b = _a === void 0 ? {} : _a,
216 _c = _b.cacheKeyRoot,
217 cacheKeyRoot = _c === void 0 ? new _optimism.KeyTrie(_apolloUtilities.canUseWeakMap) : _c,
218 _d = _b.freezeResults,
219 freezeResults = _d === void 0 ? false : _d;
220
221 var _e = this,
222 executeStoreQuery = _e.executeStoreQuery,
223 executeSelectionSet = _e.executeSelectionSet,
224 executeSubSelectedArray = _e.executeSubSelectedArray;
225
226 this.freezeResults = freezeResults;
227 this.executeStoreQuery = (0, _optimism.wrap)(function (options) {
228 return executeStoreQuery.call(_this, options);
229 }, {
230 makeCacheKey: function (_a) {
231 var query = _a.query,
232 rootValue = _a.rootValue,
233 contextValue = _a.contextValue,
234 variableValues = _a.variableValues,
235 fragmentMatcher = _a.fragmentMatcher;
236
237 if (contextValue.store instanceof DepTrackingCache) {
238 return cacheKeyRoot.lookup(contextValue.store, query, fragmentMatcher, JSON.stringify(variableValues), rootValue.id);
239 }
240 }
241 });
242 this.executeSelectionSet = (0, _optimism.wrap)(function (options) {
243 return executeSelectionSet.call(_this, options);
244 }, {
245 makeCacheKey: function (_a) {
246 var selectionSet = _a.selectionSet,
247 rootValue = _a.rootValue,
248 execContext = _a.execContext;
249
250 if (execContext.contextValue.store instanceof DepTrackingCache) {
251 return cacheKeyRoot.lookup(execContext.contextValue.store, selectionSet, execContext.fragmentMatcher, JSON.stringify(execContext.variableValues), rootValue.id);
252 }
253 }
254 });
255 this.executeSubSelectedArray = (0, _optimism.wrap)(function (options) {
256 return executeSubSelectedArray.call(_this, options);
257 }, {
258 makeCacheKey: function (_a) {
259 var field = _a.field,
260 array = _a.array,
261 execContext = _a.execContext;
262
263 if (execContext.contextValue.store instanceof DepTrackingCache) {
264 return cacheKeyRoot.lookup(execContext.contextValue.store, field, array, JSON.stringify(execContext.variableValues));
265 }
266 }
267 });
268 }
269
270 StoreReader.prototype.readQueryFromStore = function (options) {
271 return this.diffQueryAgainstStore((0, _tslib.__assign)((0, _tslib.__assign)({}, options), {
272 returnPartialData: false
273 })).result;
274 };
275
276 StoreReader.prototype.diffQueryAgainstStore = function (_a) {
277 var store = _a.store,
278 query = _a.query,
279 variables = _a.variables,
280 previousResult = _a.previousResult,
281 _b = _a.returnPartialData,
282 returnPartialData = _b === void 0 ? true : _b,
283 _c = _a.rootId,
284 rootId = _c === void 0 ? 'ROOT_QUERY' : _c,
285 fragmentMatcherFunction = _a.fragmentMatcherFunction,
286 config = _a.config;
287 var queryDefinition = (0, _apolloUtilities.getQueryDefinition)(query);
288 variables = (0, _apolloUtilities.assign)({}, (0, _apolloUtilities.getDefaultValues)(queryDefinition), variables);
289 var context = {
290 store: store,
291 dataIdFromObject: config && config.dataIdFromObject,
292 cacheRedirects: config && config.cacheRedirects || {}
293 };
294 var execResult = this.executeStoreQuery({
295 query: query,
296 rootValue: {
297 type: 'id',
298 id: rootId,
299 generated: true,
300 typename: 'Query'
301 },
302 contextValue: context,
303 variableValues: variables,
304 fragmentMatcher: fragmentMatcherFunction
305 });
306 var hasMissingFields = execResult.missing && execResult.missing.length > 0;
307
308 if (hasMissingFields && !returnPartialData) {
309 execResult.missing.forEach(function (info) {
310 if (info.tolerable) return;
311 throw process.env.NODE_ENV === "production" ? new _tsInvariant.InvariantError(8) : new _tsInvariant.InvariantError("Can't find field " + info.fieldName + " on object " + JSON.stringify(info.object, null, 2) + ".");
312 });
313 }
314
315 if (previousResult) {
316 if ((0, _apolloUtilities.isEqual)(previousResult, execResult.result)) {
317 execResult.result = previousResult;
318 }
319 }
320
321 return {
322 result: execResult.result,
323 complete: !hasMissingFields
324 };
325 };
326
327 StoreReader.prototype.executeStoreQuery = function (_a) {
328 var query = _a.query,
329 rootValue = _a.rootValue,
330 contextValue = _a.contextValue,
331 variableValues = _a.variableValues,
332 _b = _a.fragmentMatcher,
333 fragmentMatcher = _b === void 0 ? defaultFragmentMatcher : _b;
334 var mainDefinition = (0, _apolloUtilities.getMainDefinition)(query);
335 var fragments = (0, _apolloUtilities.getFragmentDefinitions)(query);
336 var fragmentMap = (0, _apolloUtilities.createFragmentMap)(fragments);
337 var execContext = {
338 query: query,
339 fragmentMap: fragmentMap,
340 contextValue: contextValue,
341 variableValues: variableValues,
342 fragmentMatcher: fragmentMatcher
343 };
344 return this.executeSelectionSet({
345 selectionSet: mainDefinition.selectionSet,
346 rootValue: rootValue,
347 execContext: execContext
348 });
349 };
350
351 StoreReader.prototype.executeSelectionSet = function (_a) {
352 var _this = this;
353
354 var selectionSet = _a.selectionSet,
355 rootValue = _a.rootValue,
356 execContext = _a.execContext;
357 var fragmentMap = execContext.fragmentMap,
358 contextValue = execContext.contextValue,
359 variables = execContext.variableValues;
360 var finalResult = {
361 result: null
362 };
363 var objectsToMerge = [];
364 var object = contextValue.store.get(rootValue.id);
365 var typename = object && object.__typename || rootValue.id === 'ROOT_QUERY' && 'Query' || void 0;
366
367 function handleMissing(result) {
368 var _a;
369
370 if (result.missing) {
371 finalResult.missing = finalResult.missing || [];
372
373 (_a = finalResult.missing).push.apply(_a, result.missing);
374 }
375
376 return result.result;
377 }
378
379 selectionSet.selections.forEach(function (selection) {
380 var _a;
381
382 if (!(0, _apolloUtilities.shouldInclude)(selection, variables)) {
383 return;
384 }
385
386 if ((0, _apolloUtilities.isField)(selection)) {
387 var fieldResult = handleMissing(_this.executeField(object, typename, selection, execContext));
388
389 if (typeof fieldResult !== 'undefined') {
390 objectsToMerge.push((_a = {}, _a[(0, _apolloUtilities.resultKeyNameFromField)(selection)] = fieldResult, _a));
391 }
392 } else {
393 var fragment = void 0;
394
395 if ((0, _apolloUtilities.isInlineFragment)(selection)) {
396 fragment = selection;
397 } else {
398 fragment = fragmentMap[selection.name.value];
399
400 if (!fragment) {
401 throw process.env.NODE_ENV === "production" ? new _tsInvariant.InvariantError(9) : new _tsInvariant.InvariantError("No fragment named " + selection.name.value);
402 }
403 }
404
405 var typeCondition = fragment.typeCondition && fragment.typeCondition.name.value;
406 var match = !typeCondition || execContext.fragmentMatcher(rootValue, typeCondition, contextValue);
407
408 if (match) {
409 var fragmentExecResult = _this.executeSelectionSet({
410 selectionSet: fragment.selectionSet,
411 rootValue: rootValue,
412 execContext: execContext
413 });
414
415 if (match === 'heuristic' && fragmentExecResult.missing) {
416 fragmentExecResult = (0, _tslib.__assign)((0, _tslib.__assign)({}, fragmentExecResult), {
417 missing: fragmentExecResult.missing.map(function (info) {
418 return (0, _tslib.__assign)((0, _tslib.__assign)({}, info), {
419 tolerable: true
420 });
421 })
422 });
423 }
424
425 objectsToMerge.push(handleMissing(fragmentExecResult));
426 }
427 }
428 });
429 finalResult.result = (0, _apolloUtilities.mergeDeepArray)(objectsToMerge);
430
431 if (this.freezeResults && process.env.NODE_ENV !== 'production') {
432 Object.freeze(finalResult.result);
433 }
434
435 return finalResult;
436 };
437
438 StoreReader.prototype.executeField = function (object, typename, field, execContext) {
439 var variables = execContext.variableValues,
440 contextValue = execContext.contextValue;
441 var fieldName = field.name.value;
442 var args = (0, _apolloUtilities.argumentsObjectFromField)(field, variables);
443 var info = {
444 resultKey: (0, _apolloUtilities.resultKeyNameFromField)(field),
445 directives: (0, _apolloUtilities.getDirectiveInfoFromField)(field, variables)
446 };
447 var readStoreResult = readStoreResolver(object, typename, fieldName, args, contextValue, info);
448
449 if (Array.isArray(readStoreResult.result)) {
450 return this.combineExecResults(readStoreResult, this.executeSubSelectedArray({
451 field: field,
452 array: readStoreResult.result,
453 execContext: execContext
454 }));
455 }
456
457 if (!field.selectionSet) {
458 assertSelectionSetForIdValue(field, readStoreResult.result);
459
460 if (this.freezeResults && process.env.NODE_ENV !== 'production') {
461 (0, _apolloUtilities.maybeDeepFreeze)(readStoreResult);
462 }
463
464 return readStoreResult;
465 }
466
467 if (readStoreResult.result == null) {
468 return readStoreResult;
469 }
470
471 return this.combineExecResults(readStoreResult, this.executeSelectionSet({
472 selectionSet: field.selectionSet,
473 rootValue: readStoreResult.result,
474 execContext: execContext
475 }));
476 };
477
478 StoreReader.prototype.combineExecResults = function () {
479 var execResults = [];
480
481 for (var _i = 0; _i < arguments.length; _i++) {
482 execResults[_i] = arguments[_i];
483 }
484
485 var missing;
486 execResults.forEach(function (execResult) {
487 if (execResult.missing) {
488 missing = missing || [];
489 missing.push.apply(missing, execResult.missing);
490 }
491 });
492 return {
493 result: execResults.pop().result,
494 missing: missing
495 };
496 };
497
498 StoreReader.prototype.executeSubSelectedArray = function (_a) {
499 var _this = this;
500
501 var field = _a.field,
502 array = _a.array,
503 execContext = _a.execContext;
504 var missing;
505
506 function handleMissing(childResult) {
507 if (childResult.missing) {
508 missing = missing || [];
509 missing.push.apply(missing, childResult.missing);
510 }
511
512 return childResult.result;
513 }
514
515 array = array.map(function (item) {
516 if (item === null) {
517 return null;
518 }
519
520 if (Array.isArray(item)) {
521 return handleMissing(_this.executeSubSelectedArray({
522 field: field,
523 array: item,
524 execContext: execContext
525 }));
526 }
527
528 if (field.selectionSet) {
529 return handleMissing(_this.executeSelectionSet({
530 selectionSet: field.selectionSet,
531 rootValue: item,
532 execContext: execContext
533 }));
534 }
535
536 assertSelectionSetForIdValue(field, item);
537 return item;
538 });
539
540 if (this.freezeResults && process.env.NODE_ENV !== 'production') {
541 Object.freeze(array);
542 }
543
544 return {
545 result: array,
546 missing: missing
547 };
548 };
549
550 return StoreReader;
551}();
552
553exports.StoreReader = StoreReader;
554
555function assertSelectionSetForIdValue(field, value) {
556 if (!field.selectionSet && (0, _apolloUtilities.isIdValue)(value)) {
557 throw process.env.NODE_ENV === "production" ? new _tsInvariant.InvariantError(10) : new _tsInvariant.InvariantError("Missing selection set for object of type " + value.typename + " returned for query field " + field.name.value);
558 }
559}
560
561function defaultFragmentMatcher() {
562 return true;
563}
564
565function assertIdValue(idValue) {
566 process.env.NODE_ENV === "production" ? (0, _tsInvariant.invariant)((0, _apolloUtilities.isIdValue)(idValue), 11) : (0, _tsInvariant.invariant)((0, _apolloUtilities.isIdValue)(idValue), "Encountered a sub-selection on the query, but the store doesn't have an object reference. This should never happen during normal use unless you have custom code that is directly manipulating the store; please file an issue.");
567}
568
569function readStoreResolver(object, typename, fieldName, args, context, _a) {
570 var resultKey = _a.resultKey,
571 directives = _a.directives;
572 var storeKeyName = fieldName;
573
574 if (args || directives) {
575 storeKeyName = (0, _apolloUtilities.getStoreKeyName)(storeKeyName, args, directives);
576 }
577
578 var fieldValue = void 0;
579
580 if (object) {
581 fieldValue = object[storeKeyName];
582
583 if (typeof fieldValue === 'undefined' && context.cacheRedirects && typeof typename === 'string') {
584 var type = context.cacheRedirects[typename];
585
586 if (type) {
587 var resolver = type[fieldName];
588
589 if (resolver) {
590 fieldValue = resolver(object, args, {
591 getCacheKey: function (storeObj) {
592 var id = context.dataIdFromObject(storeObj);
593 return id && (0, _apolloUtilities.toIdValue)({
594 id: id,
595 typename: storeObj.__typename
596 });
597 }
598 });
599 }
600 }
601 }
602 }
603
604 if (typeof fieldValue === 'undefined') {
605 return {
606 result: fieldValue,
607 missing: [{
608 object: object,
609 fieldName: storeKeyName,
610 tolerable: false
611 }]
612 };
613 }
614
615 if ((0, _apolloUtilities.isJsonValue)(fieldValue)) {
616 fieldValue = fieldValue.json;
617 }
618
619 return {
620 result: fieldValue
621 };
622}
623
624var ObjectCache = function () {
625 function ObjectCache(data) {
626 if (data === void 0) {
627 data = Object.create(null);
628 }
629
630 this.data = data;
631 }
632
633 ObjectCache.prototype.toObject = function () {
634 return this.data;
635 };
636
637 ObjectCache.prototype.get = function (dataId) {
638 return this.data[dataId];
639 };
640
641 ObjectCache.prototype.set = function (dataId, value) {
642 this.data[dataId] = value;
643 };
644
645 ObjectCache.prototype.delete = function (dataId) {
646 this.data[dataId] = void 0;
647 };
648
649 ObjectCache.prototype.clear = function () {
650 this.data = Object.create(null);
651 };
652
653 ObjectCache.prototype.replace = function (newData) {
654 this.data = newData || Object.create(null);
655 };
656
657 return ObjectCache;
658}();
659
660exports.ObjectCache = ObjectCache;
661
662function defaultNormalizedCacheFactory$1(seed) {
663 return new ObjectCache(seed);
664}
665
666var WriteError = function (_super) {
667 (0, _tslib.__extends)(WriteError, _super);
668
669 function WriteError() {
670 var _this = _super !== null && _super.apply(this, arguments) || this;
671
672 _this.type = 'WriteError';
673 return _this;
674 }
675
676 return WriteError;
677}(Error);
678
679exports.WriteError = WriteError;
680
681function enhanceErrorWithDocument(error, document) {
682 var enhancedError = new WriteError("Error writing result to store for query:\n " + JSON.stringify(document));
683 enhancedError.message += '\n' + error.message;
684 enhancedError.stack = error.stack;
685 return enhancedError;
686}
687
688var StoreWriter = function () {
689 function StoreWriter() {}
690
691 StoreWriter.prototype.writeQueryToStore = function (_a) {
692 var query = _a.query,
693 result = _a.result,
694 _b = _a.store,
695 store = _b === void 0 ? defaultNormalizedCacheFactory() : _b,
696 variables = _a.variables,
697 dataIdFromObject = _a.dataIdFromObject,
698 fragmentMatcherFunction = _a.fragmentMatcherFunction;
699 return this.writeResultToStore({
700 dataId: 'ROOT_QUERY',
701 result: result,
702 document: query,
703 store: store,
704 variables: variables,
705 dataIdFromObject: dataIdFromObject,
706 fragmentMatcherFunction: fragmentMatcherFunction
707 });
708 };
709
710 StoreWriter.prototype.writeResultToStore = function (_a) {
711 var dataId = _a.dataId,
712 result = _a.result,
713 document = _a.document,
714 _b = _a.store,
715 store = _b === void 0 ? defaultNormalizedCacheFactory() : _b,
716 variables = _a.variables,
717 dataIdFromObject = _a.dataIdFromObject,
718 fragmentMatcherFunction = _a.fragmentMatcherFunction;
719 var operationDefinition = (0, _apolloUtilities.getOperationDefinition)(document);
720
721 try {
722 return this.writeSelectionSetToStore({
723 result: result,
724 dataId: dataId,
725 selectionSet: operationDefinition.selectionSet,
726 context: {
727 store: store,
728 processedData: {},
729 variables: (0, _apolloUtilities.assign)({}, (0, _apolloUtilities.getDefaultValues)(operationDefinition), variables),
730 dataIdFromObject: dataIdFromObject,
731 fragmentMap: (0, _apolloUtilities.createFragmentMap)((0, _apolloUtilities.getFragmentDefinitions)(document)),
732 fragmentMatcherFunction: fragmentMatcherFunction
733 }
734 });
735 } catch (e) {
736 throw enhanceErrorWithDocument(e, document);
737 }
738 };
739
740 StoreWriter.prototype.writeSelectionSetToStore = function (_a) {
741 var _this = this;
742
743 var result = _a.result,
744 dataId = _a.dataId,
745 selectionSet = _a.selectionSet,
746 context = _a.context;
747 var variables = context.variables,
748 store = context.store,
749 fragmentMap = context.fragmentMap;
750 selectionSet.selections.forEach(function (selection) {
751 var _a;
752
753 if (!(0, _apolloUtilities.shouldInclude)(selection, variables)) {
754 return;
755 }
756
757 if ((0, _apolloUtilities.isField)(selection)) {
758 var resultFieldKey = (0, _apolloUtilities.resultKeyNameFromField)(selection);
759 var value = result[resultFieldKey];
760
761 if (typeof value !== 'undefined') {
762 _this.writeFieldToStore({
763 dataId: dataId,
764 value: value,
765 field: selection,
766 context: context
767 });
768 } else {
769 var isDefered = false;
770 var isClient = false;
771
772 if (selection.directives && selection.directives.length) {
773 isDefered = selection.directives.some(function (directive) {
774 return directive.name && directive.name.value === 'defer';
775 });
776 isClient = selection.directives.some(function (directive) {
777 return directive.name && directive.name.value === 'client';
778 });
779 }
780
781 if (!isDefered && !isClient && context.fragmentMatcherFunction) {
782 process.env.NODE_ENV === "production" || _tsInvariant.invariant.warn("Missing field " + resultFieldKey + " in " + JSON.stringify(result, null, 2).substring(0, 100));
783 }
784 }
785 } else {
786 var fragment = void 0;
787
788 if ((0, _apolloUtilities.isInlineFragment)(selection)) {
789 fragment = selection;
790 } else {
791 fragment = (fragmentMap || {})[selection.name.value];
792 process.env.NODE_ENV === "production" ? (0, _tsInvariant.invariant)(fragment, 3) : (0, _tsInvariant.invariant)(fragment, "No fragment named " + selection.name.value + ".");
793 }
794
795 var matches = true;
796
797 if (context.fragmentMatcherFunction && fragment.typeCondition) {
798 var id = dataId || 'self';
799 var idValue = (0, _apolloUtilities.toIdValue)({
800 id: id,
801 typename: undefined
802 });
803 var fakeContext = {
804 store: new ObjectCache((_a = {}, _a[id] = result, _a)),
805 cacheRedirects: {}
806 };
807 var match = context.fragmentMatcherFunction(idValue, fragment.typeCondition.name.value, fakeContext);
808
809 if (!(0, _apolloUtilities.isProduction)() && match === 'heuristic') {
810 process.env.NODE_ENV === "production" || _tsInvariant.invariant.error('WARNING: heuristic fragment matching going on!');
811 }
812
813 matches = !!match;
814 }
815
816 if (matches) {
817 _this.writeSelectionSetToStore({
818 result: result,
819 selectionSet: fragment.selectionSet,
820 dataId: dataId,
821 context: context
822 });
823 }
824 }
825 });
826 return store;
827 };
828
829 StoreWriter.prototype.writeFieldToStore = function (_a) {
830 var _b;
831
832 var field = _a.field,
833 value = _a.value,
834 dataId = _a.dataId,
835 context = _a.context;
836 var variables = context.variables,
837 dataIdFromObject = context.dataIdFromObject,
838 store = context.store;
839 var storeValue;
840 var storeObject;
841 var storeFieldName = (0, _apolloUtilities.storeKeyNameFromField)(field, variables);
842
843 if (!field.selectionSet || value === null) {
844 storeValue = value != null && typeof value === 'object' ? {
845 type: 'json',
846 json: value
847 } : value;
848 } else if (Array.isArray(value)) {
849 var generatedId = dataId + "." + storeFieldName;
850 storeValue = this.processArrayValue(value, generatedId, field.selectionSet, context);
851 } else {
852 var valueDataId = dataId + "." + storeFieldName;
853 var generated = true;
854
855 if (!isGeneratedId(valueDataId)) {
856 valueDataId = '$' + valueDataId;
857 }
858
859 if (dataIdFromObject) {
860 var semanticId = dataIdFromObject(value);
861 process.env.NODE_ENV === "production" ? (0, _tsInvariant.invariant)(!semanticId || !isGeneratedId(semanticId), 4) : (0, _tsInvariant.invariant)(!semanticId || !isGeneratedId(semanticId), 'IDs returned by dataIdFromObject cannot begin with the "$" character.');
862
863 if (semanticId || typeof semanticId === 'number' && semanticId === 0) {
864 valueDataId = semanticId;
865 generated = false;
866 }
867 }
868
869 if (!isDataProcessed(valueDataId, field, context.processedData)) {
870 this.writeSelectionSetToStore({
871 dataId: valueDataId,
872 result: value,
873 selectionSet: field.selectionSet,
874 context: context
875 });
876 }
877
878 var typename = value.__typename;
879 storeValue = (0, _apolloUtilities.toIdValue)({
880 id: valueDataId,
881 typename: typename
882 }, generated);
883 storeObject = store.get(dataId);
884 var escapedId = storeObject && storeObject[storeFieldName];
885
886 if (escapedId !== storeValue && (0, _apolloUtilities.isIdValue)(escapedId)) {
887 var hadTypename = escapedId.typename !== undefined;
888 var hasTypename = typename !== undefined;
889 var typenameChanged = hadTypename && hasTypename && escapedId.typename !== typename;
890 process.env.NODE_ENV === "production" ? (0, _tsInvariant.invariant)(!generated || escapedId.generated || typenameChanged, 5) : (0, _tsInvariant.invariant)(!generated || escapedId.generated || typenameChanged, "Store error: the application attempted to write an object with no provided id but the store already contains an id of " + escapedId.id + " for this object. The selectionSet that was trying to be written is:\n" + JSON.stringify(field));
891 process.env.NODE_ENV === "production" ? (0, _tsInvariant.invariant)(!hadTypename || hasTypename, 6) : (0, _tsInvariant.invariant)(!hadTypename || hasTypename, "Store error: the application attempted to write an object with no provided typename but the store already contains an object with typename of " + escapedId.typename + " for the object of id " + escapedId.id + ". The selectionSet that was trying to be written is:\n" + JSON.stringify(field));
892
893 if (escapedId.generated) {
894 if (typenameChanged) {
895 if (!generated) {
896 store.delete(escapedId.id);
897 }
898 } else {
899 mergeWithGenerated(escapedId.id, storeValue.id, store);
900 }
901 }
902 }
903 }
904
905 storeObject = store.get(dataId);
906
907 if (!storeObject || !(0, _apolloUtilities.isEqual)(storeValue, storeObject[storeFieldName])) {
908 store.set(dataId, (0, _tslib.__assign)((0, _tslib.__assign)({}, storeObject), (_b = {}, _b[storeFieldName] = storeValue, _b)));
909 }
910 };
911
912 StoreWriter.prototype.processArrayValue = function (value, generatedId, selectionSet, context) {
913 var _this = this;
914
915 return value.map(function (item, index) {
916 if (item === null) {
917 return null;
918 }
919
920 var itemDataId = generatedId + "." + index;
921
922 if (Array.isArray(item)) {
923 return _this.processArrayValue(item, itemDataId, selectionSet, context);
924 }
925
926 var generated = true;
927
928 if (context.dataIdFromObject) {
929 var semanticId = context.dataIdFromObject(item);
930
931 if (semanticId) {
932 itemDataId = semanticId;
933 generated = false;
934 }
935 }
936
937 if (!isDataProcessed(itemDataId, selectionSet, context.processedData)) {
938 _this.writeSelectionSetToStore({
939 dataId: itemDataId,
940 result: item,
941 selectionSet: selectionSet,
942 context: context
943 });
944 }
945
946 return (0, _apolloUtilities.toIdValue)({
947 id: itemDataId,
948 typename: item.__typename
949 }, generated);
950 });
951 };
952
953 return StoreWriter;
954}();
955
956exports.StoreWriter = StoreWriter;
957
958function isGeneratedId(id) {
959 return id[0] === '$';
960}
961
962function mergeWithGenerated(generatedKey, realKey, cache) {
963 if (generatedKey === realKey) {
964 return false;
965 }
966
967 var generated = cache.get(generatedKey);
968 var real = cache.get(realKey);
969 var madeChanges = false;
970 Object.keys(generated).forEach(function (key) {
971 var value = generated[key];
972 var realValue = real[key];
973
974 if ((0, _apolloUtilities.isIdValue)(value) && isGeneratedId(value.id) && (0, _apolloUtilities.isIdValue)(realValue) && !(0, _apolloUtilities.isEqual)(value, realValue) && mergeWithGenerated(value.id, realValue.id, cache)) {
975 madeChanges = true;
976 }
977 });
978 cache.delete(generatedKey);
979 var newRealValue = (0, _tslib.__assign)((0, _tslib.__assign)({}, generated), real);
980
981 if ((0, _apolloUtilities.isEqual)(newRealValue, real)) {
982 return madeChanges;
983 }
984
985 cache.set(realKey, newRealValue);
986 return true;
987}
988
989function isDataProcessed(dataId, field, processedData) {
990 if (!processedData) {
991 return false;
992 }
993
994 if (processedData[dataId]) {
995 if (processedData[dataId].indexOf(field) >= 0) {
996 return true;
997 } else {
998 processedData[dataId].push(field);
999 }
1000 } else {
1001 processedData[dataId] = [field];
1002 }
1003
1004 return false;
1005}
1006
1007var defaultConfig = {
1008 fragmentMatcher: new HeuristicFragmentMatcher(),
1009 dataIdFromObject: defaultDataIdFromObject,
1010 addTypename: true,
1011 resultCaching: true,
1012 freezeResults: false
1013};
1014
1015function defaultDataIdFromObject(result) {
1016 if (result.__typename) {
1017 if (result.id !== undefined) {
1018 return result.__typename + ":" + result.id;
1019 }
1020
1021 if (result._id !== undefined) {
1022 return result.__typename + ":" + result._id;
1023 }
1024 }
1025
1026 return null;
1027}
1028
1029var hasOwn$1 = Object.prototype.hasOwnProperty;
1030
1031var OptimisticCacheLayer = function (_super) {
1032 (0, _tslib.__extends)(OptimisticCacheLayer, _super);
1033
1034 function OptimisticCacheLayer(optimisticId, parent, transaction) {
1035 var _this = _super.call(this, Object.create(null)) || this;
1036
1037 _this.optimisticId = optimisticId;
1038 _this.parent = parent;
1039 _this.transaction = transaction;
1040 return _this;
1041 }
1042
1043 OptimisticCacheLayer.prototype.toObject = function () {
1044 return (0, _tslib.__assign)((0, _tslib.__assign)({}, this.parent.toObject()), this.data);
1045 };
1046
1047 OptimisticCacheLayer.prototype.get = function (dataId) {
1048 return hasOwn$1.call(this.data, dataId) ? this.data[dataId] : this.parent.get(dataId);
1049 };
1050
1051 return OptimisticCacheLayer;
1052}(ObjectCache);
1053
1054var InMemoryCache = function (_super) {
1055 (0, _tslib.__extends)(InMemoryCache, _super);
1056
1057 function InMemoryCache(config) {
1058 if (config === void 0) {
1059 config = {};
1060 }
1061
1062 var _this = _super.call(this) || this;
1063
1064 _this.watches = new Set();
1065 _this.typenameDocumentCache = new Map();
1066 _this.cacheKeyRoot = new _optimism.KeyTrie(_apolloUtilities.canUseWeakMap);
1067 _this.silenceBroadcast = false;
1068 _this.config = (0, _tslib.__assign)((0, _tslib.__assign)({}, defaultConfig), config);
1069
1070 if (_this.config.customResolvers) {
1071 process.env.NODE_ENV === "production" || _tsInvariant.invariant.warn('customResolvers have been renamed to cacheRedirects. Please update your config as we will be deprecating customResolvers in the next major version.');
1072 _this.config.cacheRedirects = _this.config.customResolvers;
1073 }
1074
1075 if (_this.config.cacheResolvers) {
1076 process.env.NODE_ENV === "production" || _tsInvariant.invariant.warn('cacheResolvers have been renamed to cacheRedirects. Please update your config as we will be deprecating cacheResolvers in the next major version.');
1077 _this.config.cacheRedirects = _this.config.cacheResolvers;
1078 }
1079
1080 _this.addTypename = !!_this.config.addTypename;
1081 _this.data = _this.config.resultCaching ? new DepTrackingCache() : new ObjectCache();
1082 _this.optimisticData = _this.data;
1083 _this.storeWriter = new StoreWriter();
1084 _this.storeReader = new StoreReader({
1085 cacheKeyRoot: _this.cacheKeyRoot,
1086 freezeResults: config.freezeResults
1087 });
1088 var cache = _this;
1089 var maybeBroadcastWatch = cache.maybeBroadcastWatch;
1090 _this.maybeBroadcastWatch = (0, _optimism.wrap)(function (c) {
1091 return maybeBroadcastWatch.call(_this, c);
1092 }, {
1093 makeCacheKey: function (c) {
1094 if (c.optimistic) {
1095 return;
1096 }
1097
1098 if (c.previousResult) {
1099 return;
1100 }
1101
1102 if (cache.data instanceof DepTrackingCache) {
1103 return cache.cacheKeyRoot.lookup(c.query, JSON.stringify(c.variables));
1104 }
1105 }
1106 });
1107 return _this;
1108 }
1109
1110 InMemoryCache.prototype.restore = function (data) {
1111 if (data) this.data.replace(data);
1112 return this;
1113 };
1114
1115 InMemoryCache.prototype.extract = function (optimistic) {
1116 if (optimistic === void 0) {
1117 optimistic = false;
1118 }
1119
1120 return (optimistic ? this.optimisticData : this.data).toObject();
1121 };
1122
1123 InMemoryCache.prototype.read = function (options) {
1124 if (typeof options.rootId === 'string' && typeof this.data.get(options.rootId) === 'undefined') {
1125 return null;
1126 }
1127
1128 var fragmentMatcher = this.config.fragmentMatcher;
1129 var fragmentMatcherFunction = fragmentMatcher && fragmentMatcher.match;
1130 return this.storeReader.readQueryFromStore({
1131 store: options.optimistic ? this.optimisticData : this.data,
1132 query: this.transformDocument(options.query),
1133 variables: options.variables,
1134 rootId: options.rootId,
1135 fragmentMatcherFunction: fragmentMatcherFunction,
1136 previousResult: options.previousResult,
1137 config: this.config
1138 }) || null;
1139 };
1140
1141 InMemoryCache.prototype.write = function (write) {
1142 var fragmentMatcher = this.config.fragmentMatcher;
1143 var fragmentMatcherFunction = fragmentMatcher && fragmentMatcher.match;
1144 this.storeWriter.writeResultToStore({
1145 dataId: write.dataId,
1146 result: write.result,
1147 variables: write.variables,
1148 document: this.transformDocument(write.query),
1149 store: this.data,
1150 dataIdFromObject: this.config.dataIdFromObject,
1151 fragmentMatcherFunction: fragmentMatcherFunction
1152 });
1153 this.broadcastWatches();
1154 };
1155
1156 InMemoryCache.prototype.diff = function (query) {
1157 var fragmentMatcher = this.config.fragmentMatcher;
1158 var fragmentMatcherFunction = fragmentMatcher && fragmentMatcher.match;
1159 return this.storeReader.diffQueryAgainstStore({
1160 store: query.optimistic ? this.optimisticData : this.data,
1161 query: this.transformDocument(query.query),
1162 variables: query.variables,
1163 returnPartialData: query.returnPartialData,
1164 previousResult: query.previousResult,
1165 fragmentMatcherFunction: fragmentMatcherFunction,
1166 config: this.config
1167 });
1168 };
1169
1170 InMemoryCache.prototype.watch = function (watch) {
1171 var _this = this;
1172
1173 this.watches.add(watch);
1174 return function () {
1175 _this.watches.delete(watch);
1176 };
1177 };
1178
1179 InMemoryCache.prototype.evict = function (query) {
1180 throw process.env.NODE_ENV === "production" ? new _tsInvariant.InvariantError(7) : new _tsInvariant.InvariantError("eviction is not implemented on InMemory Cache");
1181 };
1182
1183 InMemoryCache.prototype.reset = function () {
1184 this.data.clear();
1185 this.broadcastWatches();
1186 return Promise.resolve();
1187 };
1188
1189 InMemoryCache.prototype.removeOptimistic = function (idToRemove) {
1190 var toReapply = [];
1191 var removedCount = 0;
1192 var layer = this.optimisticData;
1193
1194 while (layer instanceof OptimisticCacheLayer) {
1195 if (layer.optimisticId === idToRemove) {
1196 ++removedCount;
1197 } else {
1198 toReapply.push(layer);
1199 }
1200
1201 layer = layer.parent;
1202 }
1203
1204 if (removedCount > 0) {
1205 this.optimisticData = layer;
1206
1207 while (toReapply.length > 0) {
1208 var layer_1 = toReapply.pop();
1209 this.performTransaction(layer_1.transaction, layer_1.optimisticId);
1210 }
1211
1212 this.broadcastWatches();
1213 }
1214 };
1215
1216 InMemoryCache.prototype.performTransaction = function (transaction, optimisticId) {
1217 var _a = this,
1218 data = _a.data,
1219 silenceBroadcast = _a.silenceBroadcast;
1220
1221 this.silenceBroadcast = true;
1222
1223 if (typeof optimisticId === 'string') {
1224 this.data = this.optimisticData = new OptimisticCacheLayer(optimisticId, this.optimisticData, transaction);
1225 }
1226
1227 try {
1228 transaction(this);
1229 } finally {
1230 this.silenceBroadcast = silenceBroadcast;
1231 this.data = data;
1232 }
1233
1234 this.broadcastWatches();
1235 };
1236
1237 InMemoryCache.prototype.recordOptimisticTransaction = function (transaction, id) {
1238 return this.performTransaction(transaction, id);
1239 };
1240
1241 InMemoryCache.prototype.transformDocument = function (document) {
1242 if (this.addTypename) {
1243 var result = this.typenameDocumentCache.get(document);
1244
1245 if (!result) {
1246 result = (0, _apolloUtilities.addTypenameToDocument)(document);
1247 this.typenameDocumentCache.set(document, result);
1248 this.typenameDocumentCache.set(result, result);
1249 }
1250
1251 return result;
1252 }
1253
1254 return document;
1255 };
1256
1257 InMemoryCache.prototype.broadcastWatches = function () {
1258 var _this = this;
1259
1260 if (!this.silenceBroadcast) {
1261 this.watches.forEach(function (c) {
1262 return _this.maybeBroadcastWatch(c);
1263 });
1264 }
1265 };
1266
1267 InMemoryCache.prototype.maybeBroadcastWatch = function (c) {
1268 c.callback(this.diff({
1269 query: c.query,
1270 variables: c.variables,
1271 previousResult: c.previousResult && c.previousResult(),
1272 optimistic: c.optimistic
1273 }));
1274 };
1275
1276 return InMemoryCache;
1277}(_apolloCache.ApolloCache);
1278
1279
1280exports.InMemoryCache = InMemoryCache;