UNPKG

16.7 kBJavaScriptView Raw
1import { __assign, __awaiter, __generator } from "tslib";
2import { invariant } from "../utilities/globals/index.js";
3import { visit, BREAK, isSelectionNode, } from 'graphql';
4import { argumentsObjectFromField, buildQueryFromSelectionSet, createFragmentMap, getFragmentDefinitions, getMainDefinition, hasDirectives, isField, isInlineFragment, mergeDeep, mergeDeepArray, removeClientSetsFromDocument, resultKeyNameFromField, shouldInclude, } from "../utilities/index.js";
5import { cacheSlot } from "../cache/index.js";
6var LocalState = (function () {
7 function LocalState(_a) {
8 var cache = _a.cache, client = _a.client, resolvers = _a.resolvers, fragmentMatcher = _a.fragmentMatcher;
9 this.selectionsToResolveCache = new WeakMap();
10 this.cache = cache;
11 if (client) {
12 this.client = client;
13 }
14 if (resolvers) {
15 this.addResolvers(resolvers);
16 }
17 if (fragmentMatcher) {
18 this.setFragmentMatcher(fragmentMatcher);
19 }
20 }
21 LocalState.prototype.addResolvers = function (resolvers) {
22 var _this = this;
23 this.resolvers = this.resolvers || {};
24 if (Array.isArray(resolvers)) {
25 resolvers.forEach(function (resolverGroup) {
26 _this.resolvers = mergeDeep(_this.resolvers, resolverGroup);
27 });
28 }
29 else {
30 this.resolvers = mergeDeep(this.resolvers, resolvers);
31 }
32 };
33 LocalState.prototype.setResolvers = function (resolvers) {
34 this.resolvers = {};
35 this.addResolvers(resolvers);
36 };
37 LocalState.prototype.getResolvers = function () {
38 return this.resolvers || {};
39 };
40 LocalState.prototype.runResolvers = function (_a) {
41 var document = _a.document, remoteResult = _a.remoteResult, context = _a.context, variables = _a.variables, _b = _a.onlyRunForcedResolvers, onlyRunForcedResolvers = _b === void 0 ? false : _b;
42 return __awaiter(this, void 0, void 0, function () {
43 return __generator(this, function (_c) {
44 if (document) {
45 return [2, this.resolveDocument(document, remoteResult.data, context, variables, this.fragmentMatcher, onlyRunForcedResolvers).then(function (localResult) { return (__assign(__assign({}, remoteResult), { data: localResult.result })); })];
46 }
47 return [2, remoteResult];
48 });
49 });
50 };
51 LocalState.prototype.setFragmentMatcher = function (fragmentMatcher) {
52 this.fragmentMatcher = fragmentMatcher;
53 };
54 LocalState.prototype.getFragmentMatcher = function () {
55 return this.fragmentMatcher;
56 };
57 LocalState.prototype.clientQuery = function (document) {
58 if (hasDirectives(['client'], document)) {
59 if (this.resolvers) {
60 return document;
61 }
62 }
63 return null;
64 };
65 LocalState.prototype.serverQuery = function (document) {
66 return removeClientSetsFromDocument(document);
67 };
68 LocalState.prototype.prepareContext = function (context) {
69 var cache = this.cache;
70 return __assign(__assign({}, context), { cache: cache, getCacheKey: function (obj) {
71 return cache.identify(obj);
72 } });
73 };
74 LocalState.prototype.addExportedVariables = function (document, variables, context) {
75 if (variables === void 0) { variables = {}; }
76 if (context === void 0) { context = {}; }
77 return __awaiter(this, void 0, void 0, function () {
78 return __generator(this, function (_a) {
79 if (document) {
80 return [2, this.resolveDocument(document, this.buildRootValueFromCache(document, variables) || {}, this.prepareContext(context), variables).then(function (data) { return (__assign(__assign({}, variables), data.exportedVariables)); })];
81 }
82 return [2, __assign({}, variables)];
83 });
84 });
85 };
86 LocalState.prototype.shouldForceResolvers = function (document) {
87 var forceResolvers = false;
88 visit(document, {
89 Directive: {
90 enter: function (node) {
91 if (node.name.value === 'client' && node.arguments) {
92 forceResolvers = node.arguments.some(function (arg) {
93 return arg.name.value === 'always' &&
94 arg.value.kind === 'BooleanValue' &&
95 arg.value.value === true;
96 });
97 if (forceResolvers) {
98 return BREAK;
99 }
100 }
101 },
102 },
103 });
104 return forceResolvers;
105 };
106 LocalState.prototype.buildRootValueFromCache = function (document, variables) {
107 return this.cache.diff({
108 query: buildQueryFromSelectionSet(document),
109 variables: variables,
110 returnPartialData: true,
111 optimistic: false,
112 }).result;
113 };
114 LocalState.prototype.resolveDocument = function (document, rootValue, context, variables, fragmentMatcher, onlyRunForcedResolvers) {
115 if (context === void 0) { context = {}; }
116 if (variables === void 0) { variables = {}; }
117 if (fragmentMatcher === void 0) { fragmentMatcher = function () { return true; }; }
118 if (onlyRunForcedResolvers === void 0) { onlyRunForcedResolvers = false; }
119 return __awaiter(this, void 0, void 0, function () {
120 var mainDefinition, fragments, fragmentMap, selectionsToResolve, definitionOperation, defaultOperationType, _a, cache, client, execContext, isClientFieldDescendant;
121 return __generator(this, function (_b) {
122 mainDefinition = getMainDefinition(document);
123 fragments = getFragmentDefinitions(document);
124 fragmentMap = createFragmentMap(fragments);
125 selectionsToResolve = this.collectSelectionsToResolve(mainDefinition, fragmentMap);
126 definitionOperation = mainDefinition.operation;
127 defaultOperationType = definitionOperation
128 ? definitionOperation.charAt(0).toUpperCase() +
129 definitionOperation.slice(1)
130 : 'Query';
131 _a = this, cache = _a.cache, client = _a.client;
132 execContext = {
133 fragmentMap: fragmentMap,
134 context: __assign(__assign({}, context), { cache: cache, client: client }),
135 variables: variables,
136 fragmentMatcher: fragmentMatcher,
137 defaultOperationType: defaultOperationType,
138 exportedVariables: {},
139 selectionsToResolve: selectionsToResolve,
140 onlyRunForcedResolvers: onlyRunForcedResolvers,
141 };
142 isClientFieldDescendant = false;
143 return [2, this.resolveSelectionSet(mainDefinition.selectionSet, isClientFieldDescendant, rootValue, execContext).then(function (result) { return ({
144 result: result,
145 exportedVariables: execContext.exportedVariables,
146 }); })];
147 });
148 });
149 };
150 LocalState.prototype.resolveSelectionSet = function (selectionSet, isClientFieldDescendant, rootValue, execContext) {
151 return __awaiter(this, void 0, void 0, function () {
152 var fragmentMap, context, variables, resultsToMerge, execute;
153 var _this = this;
154 return __generator(this, function (_a) {
155 fragmentMap = execContext.fragmentMap, context = execContext.context, variables = execContext.variables;
156 resultsToMerge = [rootValue];
157 execute = function (selection) { return __awaiter(_this, void 0, void 0, function () {
158 var fragment, typeCondition;
159 return __generator(this, function (_a) {
160 if (!isClientFieldDescendant && !execContext.selectionsToResolve.has(selection)) {
161 return [2];
162 }
163 if (!shouldInclude(selection, variables)) {
164 return [2];
165 }
166 if (isField(selection)) {
167 return [2, this.resolveField(selection, isClientFieldDescendant, rootValue, execContext).then(function (fieldResult) {
168 var _a;
169 if (typeof fieldResult !== 'undefined') {
170 resultsToMerge.push((_a = {},
171 _a[resultKeyNameFromField(selection)] = fieldResult,
172 _a));
173 }
174 })];
175 }
176 if (isInlineFragment(selection)) {
177 fragment = selection;
178 }
179 else {
180 fragment = fragmentMap[selection.name.value];
181 __DEV__ ? invariant(fragment, "No fragment named ".concat(selection.name.value)) : invariant(fragment, 11);
182 }
183 if (fragment && fragment.typeCondition) {
184 typeCondition = fragment.typeCondition.name.value;
185 if (execContext.fragmentMatcher(rootValue, typeCondition, context)) {
186 return [2, this.resolveSelectionSet(fragment.selectionSet, isClientFieldDescendant, rootValue, execContext).then(function (fragmentResult) {
187 resultsToMerge.push(fragmentResult);
188 })];
189 }
190 }
191 return [2];
192 });
193 }); };
194 return [2, Promise.all(selectionSet.selections.map(execute)).then(function () {
195 return mergeDeepArray(resultsToMerge);
196 })];
197 });
198 });
199 };
200 LocalState.prototype.resolveField = function (field, isClientFieldDescendant, rootValue, execContext) {
201 return __awaiter(this, void 0, void 0, function () {
202 var variables, fieldName, aliasedFieldName, aliasUsed, defaultResult, resultPromise, resolverType, resolverMap, resolve;
203 var _this = this;
204 return __generator(this, function (_a) {
205 if (!rootValue) {
206 return [2, null];
207 }
208 variables = execContext.variables;
209 fieldName = field.name.value;
210 aliasedFieldName = resultKeyNameFromField(field);
211 aliasUsed = fieldName !== aliasedFieldName;
212 defaultResult = rootValue[aliasedFieldName] || rootValue[fieldName];
213 resultPromise = Promise.resolve(defaultResult);
214 if (!execContext.onlyRunForcedResolvers ||
215 this.shouldForceResolvers(field)) {
216 resolverType = rootValue.__typename || execContext.defaultOperationType;
217 resolverMap = this.resolvers && this.resolvers[resolverType];
218 if (resolverMap) {
219 resolve = resolverMap[aliasUsed ? fieldName : aliasedFieldName];
220 if (resolve) {
221 resultPromise = Promise.resolve(cacheSlot.withValue(this.cache, resolve, [
222 rootValue,
223 argumentsObjectFromField(field, variables),
224 execContext.context,
225 { field: field, fragmentMap: execContext.fragmentMap },
226 ]));
227 }
228 }
229 }
230 return [2, resultPromise.then(function (result) {
231 var _a, _b;
232 if (result === void 0) { result = defaultResult; }
233 if (field.directives) {
234 field.directives.forEach(function (directive) {
235 if (directive.name.value === 'export' && directive.arguments) {
236 directive.arguments.forEach(function (arg) {
237 if (arg.name.value === 'as' && arg.value.kind === 'StringValue') {
238 execContext.exportedVariables[arg.value.value] = result;
239 }
240 });
241 }
242 });
243 }
244 if (!field.selectionSet) {
245 return result;
246 }
247 if (result == null) {
248 return result;
249 }
250 var isClientField = (_b = (_a = field.directives) === null || _a === void 0 ? void 0 : _a.some(function (d) { return d.name.value === 'client'; })) !== null && _b !== void 0 ? _b : false;
251 if (Array.isArray(result)) {
252 return _this.resolveSubSelectedArray(field, isClientFieldDescendant || isClientField, result, execContext);
253 }
254 if (field.selectionSet) {
255 return _this.resolveSelectionSet(field.selectionSet, isClientFieldDescendant || isClientField, result, execContext);
256 }
257 })];
258 });
259 });
260 };
261 LocalState.prototype.resolveSubSelectedArray = function (field, isClientFieldDescendant, result, execContext) {
262 var _this = this;
263 return Promise.all(result.map(function (item) {
264 if (item === null) {
265 return null;
266 }
267 if (Array.isArray(item)) {
268 return _this.resolveSubSelectedArray(field, isClientFieldDescendant, item, execContext);
269 }
270 if (field.selectionSet) {
271 return _this.resolveSelectionSet(field.selectionSet, isClientFieldDescendant, item, execContext);
272 }
273 }));
274 };
275 LocalState.prototype.collectSelectionsToResolve = function (mainDefinition, fragmentMap) {
276 var isSingleASTNode = function (node) { return !Array.isArray(node); };
277 var selectionsToResolveCache = this.selectionsToResolveCache;
278 function collectByDefinition(definitionNode) {
279 if (!selectionsToResolveCache.has(definitionNode)) {
280 var matches_1 = new Set();
281 selectionsToResolveCache.set(definitionNode, matches_1);
282 visit(definitionNode, {
283 Directive: function (node, _, __, ___, ancestors) {
284 if (node.name.value === 'client') {
285 ancestors.forEach(function (node) {
286 if (isSingleASTNode(node) && isSelectionNode(node)) {
287 matches_1.add(node);
288 }
289 });
290 }
291 },
292 FragmentSpread: function (spread, _, __, ___, ancestors) {
293 var fragment = fragmentMap[spread.name.value];
294 __DEV__ ? invariant(fragment, "No fragment named ".concat(spread.name.value)) : invariant(fragment, 12);
295 var fragmentSelections = collectByDefinition(fragment);
296 if (fragmentSelections.size > 0) {
297 ancestors.forEach(function (node) {
298 if (isSingleASTNode(node) && isSelectionNode(node)) {
299 matches_1.add(node);
300 }
301 });
302 matches_1.add(spread);
303 fragmentSelections.forEach(function (selection) {
304 matches_1.add(selection);
305 });
306 }
307 }
308 });
309 }
310 return selectionsToResolveCache.get(definitionNode);
311 }
312 return collectByDefinition(mainDefinition);
313 };
314 return LocalState;
315}());
316export { LocalState };
317//# sourceMappingURL=LocalState.js.map
\No newline at end of file