UNPKG

13 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var tslib_1 = require("tslib");
4var apollo_utilities_1 = require("apollo-utilities");
5var ts_invariant_1 = require("ts-invariant");
6var objectCache_1 = require("./objectCache");
7var depTrackingCache_1 = require("./depTrackingCache");
8var WriteError = (function (_super) {
9 tslib_1.__extends(WriteError, _super);
10 function WriteError() {
11 var _this = _super !== null && _super.apply(this, arguments) || this;
12 _this.type = 'WriteError';
13 return _this;
14 }
15 return WriteError;
16}(Error));
17exports.WriteError = WriteError;
18function enhanceErrorWithDocument(error, document) {
19 var enhancedError = new WriteError("Error writing result to store for query:\n " + JSON.stringify(document));
20 enhancedError.message += '\n' + error.message;
21 enhancedError.stack = error.stack;
22 return enhancedError;
23}
24exports.enhanceErrorWithDocument = enhanceErrorWithDocument;
25var StoreWriter = (function () {
26 function StoreWriter() {
27 }
28 StoreWriter.prototype.writeQueryToStore = function (_a) {
29 var query = _a.query, result = _a.result, _b = _a.store, store = _b === void 0 ? depTrackingCache_1.defaultNormalizedCacheFactory() : _b, variables = _a.variables, dataIdFromObject = _a.dataIdFromObject, fragmentMatcherFunction = _a.fragmentMatcherFunction;
30 return this.writeResultToStore({
31 dataId: 'ROOT_QUERY',
32 result: result,
33 document: query,
34 store: store,
35 variables: variables,
36 dataIdFromObject: dataIdFromObject,
37 fragmentMatcherFunction: fragmentMatcherFunction,
38 });
39 };
40 StoreWriter.prototype.writeResultToStore = function (_a) {
41 var dataId = _a.dataId, result = _a.result, document = _a.document, _b = _a.store, store = _b === void 0 ? depTrackingCache_1.defaultNormalizedCacheFactory() : _b, variables = _a.variables, dataIdFromObject = _a.dataIdFromObject, fragmentMatcherFunction = _a.fragmentMatcherFunction;
42 var operationDefinition = apollo_utilities_1.getOperationDefinition(document);
43 try {
44 return this.writeSelectionSetToStore({
45 result: result,
46 dataId: dataId,
47 selectionSet: operationDefinition.selectionSet,
48 context: {
49 store: store,
50 processedData: {},
51 variables: apollo_utilities_1.assign({}, apollo_utilities_1.getDefaultValues(operationDefinition), variables),
52 dataIdFromObject: dataIdFromObject,
53 fragmentMap: apollo_utilities_1.createFragmentMap(apollo_utilities_1.getFragmentDefinitions(document)),
54 fragmentMatcherFunction: fragmentMatcherFunction,
55 },
56 });
57 }
58 catch (e) {
59 throw enhanceErrorWithDocument(e, document);
60 }
61 };
62 StoreWriter.prototype.writeSelectionSetToStore = function (_a) {
63 var _this = this;
64 var result = _a.result, dataId = _a.dataId, selectionSet = _a.selectionSet, context = _a.context;
65 var variables = context.variables, store = context.store, fragmentMap = context.fragmentMap;
66 selectionSet.selections.forEach(function (selection) {
67 var _a;
68 if (!apollo_utilities_1.shouldInclude(selection, variables)) {
69 return;
70 }
71 if (apollo_utilities_1.isField(selection)) {
72 var resultFieldKey = apollo_utilities_1.resultKeyNameFromField(selection);
73 var value = result[resultFieldKey];
74 if (typeof value !== 'undefined') {
75 _this.writeFieldToStore({
76 dataId: dataId,
77 value: value,
78 field: selection,
79 context: context,
80 });
81 }
82 else {
83 var isDefered = false;
84 var isClient = false;
85 if (selection.directives && selection.directives.length) {
86 isDefered = selection.directives.some(function (directive) { return directive.name && directive.name.value === 'defer'; });
87 isClient = selection.directives.some(function (directive) { return directive.name && directive.name.value === 'client'; });
88 }
89 if (!isDefered && !isClient && context.fragmentMatcherFunction) {
90 ts_invariant_1.invariant.warn("Missing field " + resultFieldKey + " in " + JSON.stringify(result, null, 2).substring(0, 100));
91 }
92 }
93 }
94 else {
95 var fragment = void 0;
96 if (apollo_utilities_1.isInlineFragment(selection)) {
97 fragment = selection;
98 }
99 else {
100 fragment = (fragmentMap || {})[selection.name.value];
101 ts_invariant_1.invariant(fragment, "No fragment named " + selection.name.value + ".");
102 }
103 var matches = true;
104 if (context.fragmentMatcherFunction && fragment.typeCondition) {
105 var id = dataId || 'self';
106 var idValue = apollo_utilities_1.toIdValue({ id: id, typename: undefined });
107 var fakeContext = {
108 store: new objectCache_1.ObjectCache((_a = {}, _a[id] = result, _a)),
109 cacheRedirects: {},
110 };
111 var match = context.fragmentMatcherFunction(idValue, fragment.typeCondition.name.value, fakeContext);
112 if (!apollo_utilities_1.isProduction() && match === 'heuristic') {
113 ts_invariant_1.invariant.error('WARNING: heuristic fragment matching going on!');
114 }
115 matches = !!match;
116 }
117 if (matches) {
118 _this.writeSelectionSetToStore({
119 result: result,
120 selectionSet: fragment.selectionSet,
121 dataId: dataId,
122 context: context,
123 });
124 }
125 }
126 });
127 return store;
128 };
129 StoreWriter.prototype.writeFieldToStore = function (_a) {
130 var _b;
131 var field = _a.field, value = _a.value, dataId = _a.dataId, context = _a.context;
132 var variables = context.variables, dataIdFromObject = context.dataIdFromObject, store = context.store;
133 var storeValue;
134 var storeObject;
135 var storeFieldName = apollo_utilities_1.storeKeyNameFromField(field, variables);
136 if (!field.selectionSet || value === null) {
137 storeValue =
138 value != null && typeof value === 'object'
139 ?
140 { type: 'json', json: value }
141 :
142 value;
143 }
144 else if (Array.isArray(value)) {
145 var generatedId = dataId + "." + storeFieldName;
146 storeValue = this.processArrayValue(value, generatedId, field.selectionSet, context);
147 }
148 else {
149 var valueDataId = dataId + "." + storeFieldName;
150 var generated = true;
151 if (!isGeneratedId(valueDataId)) {
152 valueDataId = '$' + valueDataId;
153 }
154 if (dataIdFromObject) {
155 var semanticId = dataIdFromObject(value);
156 ts_invariant_1.invariant(!semanticId || !isGeneratedId(semanticId), 'IDs returned by dataIdFromObject cannot begin with the "$" character.');
157 if (semanticId ||
158 (typeof semanticId === 'number' && semanticId === 0)) {
159 valueDataId = semanticId;
160 generated = false;
161 }
162 }
163 if (!isDataProcessed(valueDataId, field, context.processedData)) {
164 this.writeSelectionSetToStore({
165 dataId: valueDataId,
166 result: value,
167 selectionSet: field.selectionSet,
168 context: context,
169 });
170 }
171 var typename = value.__typename;
172 storeValue = apollo_utilities_1.toIdValue({ id: valueDataId, typename: typename }, generated);
173 storeObject = store.get(dataId);
174 var escapedId = storeObject && storeObject[storeFieldName];
175 if (escapedId !== storeValue && apollo_utilities_1.isIdValue(escapedId)) {
176 var hadTypename = escapedId.typename !== undefined;
177 var hasTypename = typename !== undefined;
178 var typenameChanged = hadTypename && hasTypename && escapedId.typename !== typename;
179 ts_invariant_1.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));
180 ts_invariant_1.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));
181 if (escapedId.generated) {
182 if (typenameChanged) {
183 if (!generated) {
184 store.delete(escapedId.id);
185 }
186 }
187 else {
188 mergeWithGenerated(escapedId.id, storeValue.id, store);
189 }
190 }
191 }
192 }
193 storeObject = store.get(dataId);
194 if (!storeObject || !apollo_utilities_1.isEqual(storeValue, storeObject[storeFieldName])) {
195 store.set(dataId, tslib_1.__assign(tslib_1.__assign({}, storeObject), (_b = {}, _b[storeFieldName] = storeValue, _b)));
196 }
197 };
198 StoreWriter.prototype.processArrayValue = function (value, generatedId, selectionSet, context) {
199 var _this = this;
200 return value.map(function (item, index) {
201 if (item === null) {
202 return null;
203 }
204 var itemDataId = generatedId + "." + index;
205 if (Array.isArray(item)) {
206 return _this.processArrayValue(item, itemDataId, selectionSet, context);
207 }
208 var generated = true;
209 if (context.dataIdFromObject) {
210 var semanticId = context.dataIdFromObject(item);
211 if (semanticId) {
212 itemDataId = semanticId;
213 generated = false;
214 }
215 }
216 if (!isDataProcessed(itemDataId, selectionSet, context.processedData)) {
217 _this.writeSelectionSetToStore({
218 dataId: itemDataId,
219 result: item,
220 selectionSet: selectionSet,
221 context: context,
222 });
223 }
224 return apollo_utilities_1.toIdValue({ id: itemDataId, typename: item.__typename }, generated);
225 });
226 };
227 return StoreWriter;
228}());
229exports.StoreWriter = StoreWriter;
230function isGeneratedId(id) {
231 return id[0] === '$';
232}
233function mergeWithGenerated(generatedKey, realKey, cache) {
234 if (generatedKey === realKey) {
235 return false;
236 }
237 var generated = cache.get(generatedKey);
238 var real = cache.get(realKey);
239 var madeChanges = false;
240 Object.keys(generated).forEach(function (key) {
241 var value = generated[key];
242 var realValue = real[key];
243 if (apollo_utilities_1.isIdValue(value) &&
244 isGeneratedId(value.id) &&
245 apollo_utilities_1.isIdValue(realValue) &&
246 !apollo_utilities_1.isEqual(value, realValue) &&
247 mergeWithGenerated(value.id, realValue.id, cache)) {
248 madeChanges = true;
249 }
250 });
251 cache.delete(generatedKey);
252 var newRealValue = tslib_1.__assign(tslib_1.__assign({}, generated), real);
253 if (apollo_utilities_1.isEqual(newRealValue, real)) {
254 return madeChanges;
255 }
256 cache.set(realKey, newRealValue);
257 return true;
258}
259function isDataProcessed(dataId, field, processedData) {
260 if (!processedData) {
261 return false;
262 }
263 if (processedData[dataId]) {
264 if (processedData[dataId].indexOf(field) >= 0) {
265 return true;
266 }
267 else {
268 processedData[dataId].push(field);
269 }
270 }
271 else {
272 processedData[dataId] = [field];
273 }
274 return false;
275}
276//# sourceMappingURL=writeToStore.js.map
\No newline at end of file