UNPKG

12.3 kBJavaScriptView Raw
1import { __assign } from "tslib";
2import { invariant, InvariantError } from "../../utilities/globals/index.js";
3import { Kind, } from 'graphql';
4import { wrap } from 'optimism';
5import { isField, resultKeyNameFromField, isReference, makeReference, shouldInclude, addTypenameToDocument, getDefaultValues, getMainDefinition, getQueryDefinition, getFragmentFromSelection, maybeDeepFreeze, mergeDeepArray, DeepMerger, isNonNullObject, canUseWeakMap, compact, } from "../../utilities/index.js";
6import { maybeDependOnExistenceOfEntity, supportsResultCaching } from "./entityStore.js";
7import { isArray, extractFragmentContext, getTypenameFromStoreObject, shouldCanonizeResults } from "./helpers.js";
8import { MissingFieldError } from "../core/types/common.js";
9import { canonicalStringify, ObjectCanon } from "./object-canon.js";
10;
11function execSelectionSetKeyArgs(options) {
12 return [
13 options.selectionSet,
14 options.objectOrReference,
15 options.context,
16 options.context.canonizeResults,
17 ];
18}
19var StoreReader = (function () {
20 function StoreReader(config) {
21 var _this = this;
22 this.knownResults = new (canUseWeakMap ? WeakMap : Map)();
23 this.config = compact(config, {
24 addTypename: config.addTypename !== false,
25 canonizeResults: shouldCanonizeResults(config),
26 });
27 this.canon = config.canon || new ObjectCanon;
28 this.executeSelectionSet = wrap(function (options) {
29 var _a;
30 var canonizeResults = options.context.canonizeResults;
31 var peekArgs = execSelectionSetKeyArgs(options);
32 peekArgs[3] = !canonizeResults;
33 var other = (_a = _this.executeSelectionSet).peek.apply(_a, peekArgs);
34 if (other) {
35 if (canonizeResults) {
36 return __assign(__assign({}, other), { result: _this.canon.admit(other.result) });
37 }
38 return other;
39 }
40 maybeDependOnExistenceOfEntity(options.context.store, options.enclosingRef.__ref);
41 return _this.execSelectionSetImpl(options);
42 }, {
43 max: this.config.resultCacheMaxSize,
44 keyArgs: execSelectionSetKeyArgs,
45 makeCacheKey: function (selectionSet, parent, context, canonizeResults) {
46 if (supportsResultCaching(context.store)) {
47 return context.store.makeCacheKey(selectionSet, isReference(parent) ? parent.__ref : parent, context.varString, canonizeResults);
48 }
49 }
50 });
51 this.executeSubSelectedArray = wrap(function (options) {
52 maybeDependOnExistenceOfEntity(options.context.store, options.enclosingRef.__ref);
53 return _this.execSubSelectedArrayImpl(options);
54 }, {
55 max: this.config.resultCacheMaxSize,
56 makeCacheKey: function (_a) {
57 var field = _a.field, array = _a.array, context = _a.context;
58 if (supportsResultCaching(context.store)) {
59 return context.store.makeCacheKey(field, array, context.varString);
60 }
61 }
62 });
63 }
64 StoreReader.prototype.resetCanon = function () {
65 this.canon = new ObjectCanon;
66 };
67 StoreReader.prototype.diffQueryAgainstStore = function (_a) {
68 var store = _a.store, query = _a.query, _b = _a.rootId, rootId = _b === void 0 ? 'ROOT_QUERY' : _b, variables = _a.variables, _c = _a.returnPartialData, returnPartialData = _c === void 0 ? true : _c, _d = _a.canonizeResults, canonizeResults = _d === void 0 ? this.config.canonizeResults : _d;
69 var policies = this.config.cache.policies;
70 variables = __assign(__assign({}, getDefaultValues(getQueryDefinition(query))), variables);
71 var rootRef = makeReference(rootId);
72 var execResult = this.executeSelectionSet({
73 selectionSet: getMainDefinition(query).selectionSet,
74 objectOrReference: rootRef,
75 enclosingRef: rootRef,
76 context: __assign({ store: store, query: query, policies: policies, variables: variables, varString: canonicalStringify(variables), canonizeResults: canonizeResults }, extractFragmentContext(query, this.config.fragments)),
77 });
78 var missing;
79 if (execResult.missing) {
80 missing = [new MissingFieldError(firstMissing(execResult.missing), execResult.missing, query, variables)];
81 if (!returnPartialData) {
82 throw missing[0];
83 }
84 }
85 return {
86 result: execResult.result,
87 complete: !missing,
88 missing: missing,
89 };
90 };
91 StoreReader.prototype.isFresh = function (result, parent, selectionSet, context) {
92 if (supportsResultCaching(context.store) &&
93 this.knownResults.get(result) === selectionSet) {
94 var latest = this.executeSelectionSet.peek(selectionSet, parent, context, this.canon.isKnown(result));
95 if (latest && result === latest.result) {
96 return true;
97 }
98 }
99 return false;
100 };
101 StoreReader.prototype.execSelectionSetImpl = function (_a) {
102 var _this = this;
103 var selectionSet = _a.selectionSet, objectOrReference = _a.objectOrReference, enclosingRef = _a.enclosingRef, context = _a.context;
104 if (isReference(objectOrReference) &&
105 !context.policies.rootTypenamesById[objectOrReference.__ref] &&
106 !context.store.has(objectOrReference.__ref)) {
107 return {
108 result: this.canon.empty,
109 missing: "Dangling reference to missing ".concat(objectOrReference.__ref, " object"),
110 };
111 }
112 var variables = context.variables, policies = context.policies, store = context.store;
113 var typename = store.getFieldValue(objectOrReference, "__typename");
114 var objectsToMerge = [];
115 var missing;
116 var missingMerger = new DeepMerger();
117 if (this.config.addTypename &&
118 typeof typename === "string" &&
119 !policies.rootIdsByTypename[typename]) {
120 objectsToMerge.push({ __typename: typename });
121 }
122 function handleMissing(result, resultName) {
123 var _a;
124 if (result.missing) {
125 missing = missingMerger.merge(missing, (_a = {}, _a[resultName] = result.missing, _a));
126 }
127 return result.result;
128 }
129 var workSet = new Set(selectionSet.selections);
130 workSet.forEach(function (selection) {
131 var _a, _b;
132 if (!shouldInclude(selection, variables))
133 return;
134 if (isField(selection)) {
135 var fieldValue = policies.readField({
136 fieldName: selection.name.value,
137 field: selection,
138 variables: context.variables,
139 from: objectOrReference,
140 }, context);
141 var resultName = resultKeyNameFromField(selection);
142 if (fieldValue === void 0) {
143 if (!addTypenameToDocument.added(selection)) {
144 missing = missingMerger.merge(missing, (_a = {},
145 _a[resultName] = "Can't find field '".concat(selection.name.value, "' on ").concat(isReference(objectOrReference)
146 ? objectOrReference.__ref + " object"
147 : "object " + JSON.stringify(objectOrReference, null, 2)),
148 _a));
149 }
150 }
151 else if (isArray(fieldValue)) {
152 fieldValue = handleMissing(_this.executeSubSelectedArray({
153 field: selection,
154 array: fieldValue,
155 enclosingRef: enclosingRef,
156 context: context,
157 }), resultName);
158 }
159 else if (!selection.selectionSet) {
160 if (context.canonizeResults) {
161 fieldValue = _this.canon.pass(fieldValue);
162 }
163 }
164 else if (fieldValue != null) {
165 fieldValue = handleMissing(_this.executeSelectionSet({
166 selectionSet: selection.selectionSet,
167 objectOrReference: fieldValue,
168 enclosingRef: isReference(fieldValue) ? fieldValue : enclosingRef,
169 context: context,
170 }), resultName);
171 }
172 if (fieldValue !== void 0) {
173 objectsToMerge.push((_b = {}, _b[resultName] = fieldValue, _b));
174 }
175 }
176 else {
177 var fragment = getFragmentFromSelection(selection, context.lookupFragment);
178 if (!fragment && selection.kind === Kind.FRAGMENT_SPREAD) {
179 throw __DEV__ ? new InvariantError("No fragment named ".concat(selection.name.value)) : new InvariantError(5);
180 }
181 if (fragment && policies.fragmentMatches(fragment, typename)) {
182 fragment.selectionSet.selections.forEach(workSet.add, workSet);
183 }
184 }
185 });
186 var result = mergeDeepArray(objectsToMerge);
187 var finalResult = { result: result, missing: missing };
188 var frozen = context.canonizeResults
189 ? this.canon.admit(finalResult)
190 : maybeDeepFreeze(finalResult);
191 if (frozen.result) {
192 this.knownResults.set(frozen.result, selectionSet);
193 }
194 return frozen;
195 };
196 StoreReader.prototype.execSubSelectedArrayImpl = function (_a) {
197 var _this = this;
198 var field = _a.field, array = _a.array, enclosingRef = _a.enclosingRef, context = _a.context;
199 var missing;
200 var missingMerger = new DeepMerger();
201 function handleMissing(childResult, i) {
202 var _a;
203 if (childResult.missing) {
204 missing = missingMerger.merge(missing, (_a = {}, _a[i] = childResult.missing, _a));
205 }
206 return childResult.result;
207 }
208 if (field.selectionSet) {
209 array = array.filter(context.store.canRead);
210 }
211 array = array.map(function (item, i) {
212 if (item === null) {
213 return null;
214 }
215 if (isArray(item)) {
216 return handleMissing(_this.executeSubSelectedArray({
217 field: field,
218 array: item,
219 enclosingRef: enclosingRef,
220 context: context,
221 }), i);
222 }
223 if (field.selectionSet) {
224 return handleMissing(_this.executeSelectionSet({
225 selectionSet: field.selectionSet,
226 objectOrReference: item,
227 enclosingRef: isReference(item) ? item : enclosingRef,
228 context: context,
229 }), i);
230 }
231 if (__DEV__) {
232 assertSelectionSetForIdValue(context.store, field, item);
233 }
234 return item;
235 });
236 return {
237 result: context.canonizeResults ? this.canon.admit(array) : array,
238 missing: missing,
239 };
240 };
241 return StoreReader;
242}());
243export { StoreReader };
244function firstMissing(tree) {
245 try {
246 JSON.stringify(tree, function (_, value) {
247 if (typeof value === "string")
248 throw value;
249 return value;
250 });
251 }
252 catch (result) {
253 return result;
254 }
255}
256function assertSelectionSetForIdValue(store, field, fieldValue) {
257 if (!field.selectionSet) {
258 var workSet_1 = new Set([fieldValue]);
259 workSet_1.forEach(function (value) {
260 if (isNonNullObject(value)) {
261 __DEV__ ? invariant(!isReference(value), "Missing selection set for object of type ".concat(getTypenameFromStoreObject(store, value), " returned for query field ").concat(field.name.value)) : invariant(!isReference(value), 6);
262 Object.values(value).forEach(workSet_1.add, workSet_1);
263 }
264 });
265 }
266}
267//# sourceMappingURL=readFromStore.js.map
\No newline at end of file