1 | import { __assign } from "tslib";
|
2 | import { invariant, InvariantError } from "../../utilities/globals/index.js";
|
3 | import { Kind, } from 'graphql';
|
4 | import { wrap } from 'optimism';
|
5 | import { isField, resultKeyNameFromField, isReference, makeReference, shouldInclude, addTypenameToDocument, getDefaultValues, getMainDefinition, getQueryDefinition, getFragmentFromSelection, maybeDeepFreeze, mergeDeepArray, DeepMerger, isNonNullObject, canUseWeakMap, compact, } from "../../utilities/index.js";
|
6 | import { maybeDependOnExistenceOfEntity, supportsResultCaching } from "./entityStore.js";
|
7 | import { isArray, extractFragmentContext, getTypenameFromStoreObject, shouldCanonizeResults } from "./helpers.js";
|
8 | import { MissingFieldError } from "../core/types/common.js";
|
9 | import { canonicalStringify, ObjectCanon } from "./object-canon.js";
|
10 | ;
|
11 | function execSelectionSetKeyArgs(options) {
|
12 | return [
|
13 | options.selectionSet,
|
14 | options.objectOrReference,
|
15 | options.context,
|
16 | options.context.canonizeResults,
|
17 | ];
|
18 | }
|
19 | var 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 | }());
|
243 | export { StoreReader };
|
244 | function 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 | }
|
256 | function 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 |
|
\ | No newline at end of file |