1 | import { __assign, __awaiter, __generator } from "tslib";
|
2 | import { invariant } from "../utilities/globals/index.js";
|
3 | import { visit, BREAK, isSelectionNode, } from 'graphql';
|
4 | import { argumentsObjectFromField, buildQueryFromSelectionSet, createFragmentMap, getFragmentDefinitions, getMainDefinition, hasDirectives, isField, isInlineFragment, mergeDeep, mergeDeepArray, removeClientSetsFromDocument, resultKeyNameFromField, shouldInclude, } from "../utilities/index.js";
|
5 | import { cacheSlot } from "../cache/index.js";
|
6 | var 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 | }());
|
316 | export { LocalState };
|
317 |
|
\ | No newline at end of file |