1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | var tslib_1 = require("tslib");
|
4 | var apollo_utilities_1 = require("apollo-utilities");
|
5 | var ts_invariant_1 = require("ts-invariant");
|
6 | var objectCache_1 = require("./objectCache");
|
7 | var depTrackingCache_1 = require("./depTrackingCache");
|
8 | var 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));
|
17 | exports.WriteError = WriteError;
|
18 | function 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 | }
|
24 | exports.enhanceErrorWithDocument = enhanceErrorWithDocument;
|
25 | var 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 | }());
|
229 | exports.StoreWriter = StoreWriter;
|
230 | function isGeneratedId(id) {
|
231 | return id[0] === '$';
|
232 | }
|
233 | function 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 | }
|
259 | function 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 |
|
\ | No newline at end of file |