@graphql-tools/executor 0.0.3-alpha-20221031195032-ea7637a2 → 0.0.3-alpha-20221031225249-642ec6e9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/execution/execute.js +109 -654
- package/cjs/execution/subscribe.js +158 -0
- package/esm/execution/execute.js +108 -651
- package/esm/execution/subscribe.js +153 -0
- package/package.json +2 -2
- package/typings/execution/execute.d.cts +23 -168
- package/typings/execution/execute.d.ts +23 -168
- package/typings/execution/subscribe.d.cts +59 -0
- package/typings/execution/subscribe.d.ts +59 -0
- package/cjs/execution/flattenAsyncIterable.js +0 -91
- package/cjs/execution/invariant.js +0 -9
- package/cjs/execution/promiseForObject.js +0 -21
- package/esm/execution/flattenAsyncIterable.js +0 -87
- package/esm/execution/invariant.js +0 -5
- package/esm/execution/promiseForObject.js +0 -17
- package/typings/execution/flattenAsyncIterable.d.cts +0 -7
- package/typings/execution/flattenAsyncIterable.d.ts +0 -7
- package/typings/execution/invariant.d.cts +0 -1
- package/typings/execution/invariant.d.ts +0 -1
- package/typings/execution/promiseForObject.d.cts +0 -12
- package/typings/execution/promiseForObject.d.ts +0 -12
package/cjs/execution/execute.js
CHANGED
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getFieldDef = exports.createSourceEventStream = exports.
|
|
3
|
+
exports.getFieldDef = exports.createSourceEventStream = exports.subscribe = exports.defaultFieldResolver = exports.defaultTypeResolver = exports.buildResolveInfo = exports.buildExecutionContext = exports.assertValidExecutionArguments = exports.executeSync = exports.execute = void 0;
|
|
4
4
|
const graphql_1 = require("graphql");
|
|
5
5
|
const utils_1 = require("@graphql-tools/utils");
|
|
6
6
|
const values_js_1 = require("./values.js");
|
|
7
|
-
const promiseForObject_js_1 = require("./promiseForObject.js");
|
|
8
|
-
const flattenAsyncIterable_js_1 = require("./flattenAsyncIterable.js");
|
|
9
|
-
const invariant_js_1 = require("./invariant.js");
|
|
10
|
-
/**
|
|
11
|
-
* A memoized collection of relevant subfields with regard to the return
|
|
12
|
-
* type. Memoizing ensures the subfields are not repeatedly calculated, which
|
|
13
|
-
* saves overhead when resolving lists of values.
|
|
14
|
-
*/
|
|
15
|
-
const collectSubfields = (0, utils_1.memoize3)((exeContext, returnType, fieldNodes) => (0, utils_1.collectSubFields)(exeContext.schema, exeContext.fragments, exeContext.variableValues, returnType, fieldNodes));
|
|
16
|
-
const UNEXPECTED_MULTIPLE_PAYLOADS = 'Executing this GraphQL operation would unexpectedly produce multiple payloads (due to @defer or @stream directive)';
|
|
17
7
|
/**
|
|
18
8
|
* Implements the "Executing requests" section of the GraphQL specification.
|
|
19
9
|
*
|
|
@@ -23,44 +13,8 @@ const UNEXPECTED_MULTIPLE_PAYLOADS = 'Executing this GraphQL operation would une
|
|
|
23
13
|
*
|
|
24
14
|
* If the arguments to this function do not result in a legal execution context,
|
|
25
15
|
* a GraphQLError will be thrown immediately explaining the invalid input.
|
|
26
|
-
*
|
|
27
|
-
* This function does not support incremental delivery (`@defer` and `@stream`).
|
|
28
|
-
* If an operation which would defer or stream data is executed with this
|
|
29
|
-
* function, it will throw or resolve to an object containing an error instead.
|
|
30
|
-
* Use `experimentalExecuteIncrementally` if you want to support incremental
|
|
31
|
-
* delivery.
|
|
32
16
|
*/
|
|
33
17
|
function execute(args) {
|
|
34
|
-
const result = experimentalExecuteIncrementally(args);
|
|
35
|
-
if (!(0, utils_1.isPromise)(result)) {
|
|
36
|
-
if ('initialResult' in result) {
|
|
37
|
-
throw new Error(UNEXPECTED_MULTIPLE_PAYLOADS);
|
|
38
|
-
}
|
|
39
|
-
return result;
|
|
40
|
-
}
|
|
41
|
-
return result.then(incrementalResult => {
|
|
42
|
-
if ('initialResult' in incrementalResult) {
|
|
43
|
-
return {
|
|
44
|
-
errors: [(0, utils_1.createGraphQLError)(UNEXPECTED_MULTIPLE_PAYLOADS)],
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
return incrementalResult;
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
exports.execute = execute;
|
|
51
|
-
/**
|
|
52
|
-
* Implements the "Executing requests" section of the GraphQL specification,
|
|
53
|
-
* including `@defer` and `@stream` as proposed in
|
|
54
|
-
* https://github.com/graphql/graphql-spec/pull/742
|
|
55
|
-
*
|
|
56
|
-
* This function returns a Promise of an ExperimentalIncrementalExecutionResults
|
|
57
|
-
* object. This object either consists of a single ExecutionResult, or an
|
|
58
|
-
* object containing an `initialResult` and a stream of `subsequentResults`.
|
|
59
|
-
*
|
|
60
|
-
* If the arguments to this function do not result in a legal execution context,
|
|
61
|
-
* a GraphQLError will be thrown immediately explaining the invalid input.
|
|
62
|
-
*/
|
|
63
|
-
function experimentalExecuteIncrementally(args) {
|
|
64
18
|
// If a valid execution context cannot be created due to incorrect arguments,
|
|
65
19
|
// a "Response" with only errors is returned.
|
|
66
20
|
const exeContext = buildExecutionContext(args);
|
|
@@ -70,7 +24,7 @@ function experimentalExecuteIncrementally(args) {
|
|
|
70
24
|
}
|
|
71
25
|
return executeImpl(exeContext);
|
|
72
26
|
}
|
|
73
|
-
exports.
|
|
27
|
+
exports.execute = execute;
|
|
74
28
|
function executeImpl(exeContext) {
|
|
75
29
|
// Return a Promise that will eventually resolve to the data described by
|
|
76
30
|
// The "Response" section of the GraphQL specification.
|
|
@@ -86,34 +40,12 @@ function executeImpl(exeContext) {
|
|
|
86
40
|
try {
|
|
87
41
|
const result = executeOperation(exeContext);
|
|
88
42
|
if ((0, utils_1.isPromise)(result)) {
|
|
89
|
-
return result.then(data => {
|
|
90
|
-
const initialResult = buildResponse(data, exeContext.errors);
|
|
91
|
-
if (exeContext.subsequentPayloads.size > 0) {
|
|
92
|
-
return {
|
|
93
|
-
initialResult: {
|
|
94
|
-
...initialResult,
|
|
95
|
-
hasNext: true,
|
|
96
|
-
},
|
|
97
|
-
subsequentResults: yieldSubsequentPayloads(exeContext),
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
return initialResult;
|
|
101
|
-
}, error => {
|
|
43
|
+
return result.then(data => buildResponse(data, exeContext.errors), error => {
|
|
102
44
|
exeContext.errors.push(error);
|
|
103
45
|
return buildResponse(null, exeContext.errors);
|
|
104
46
|
});
|
|
105
47
|
}
|
|
106
|
-
|
|
107
|
-
if (exeContext.subsequentPayloads.size > 0) {
|
|
108
|
-
return {
|
|
109
|
-
initialResult: {
|
|
110
|
-
...initialResult,
|
|
111
|
-
hasNext: true,
|
|
112
|
-
},
|
|
113
|
-
subsequentResults: yieldSubsequentPayloads(exeContext),
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
return initialResult;
|
|
48
|
+
return buildResponse(result, exeContext.errors);
|
|
117
49
|
}
|
|
118
50
|
catch (error) {
|
|
119
51
|
exeContext.errors.push(error);
|
|
@@ -126,9 +58,9 @@ function executeImpl(exeContext) {
|
|
|
126
58
|
* that all field resolvers are also synchronous.
|
|
127
59
|
*/
|
|
128
60
|
function executeSync(args) {
|
|
129
|
-
const result =
|
|
61
|
+
const result = execute(args);
|
|
130
62
|
// Assert that the execution was synchronous.
|
|
131
|
-
if ((0, utils_1.isPromise)(result)
|
|
63
|
+
if ((0, utils_1.isPromise)(result)) {
|
|
132
64
|
throw new Error('GraphQL execution failed to complete synchronously.');
|
|
133
65
|
}
|
|
134
66
|
return result;
|
|
@@ -216,7 +148,6 @@ function buildExecutionContext(args) {
|
|
|
216
148
|
fieldResolver: fieldResolver !== null && fieldResolver !== void 0 ? fieldResolver : exports.defaultFieldResolver,
|
|
217
149
|
typeResolver: typeResolver !== null && typeResolver !== void 0 ? typeResolver : exports.defaultTypeResolver,
|
|
218
150
|
subscribeFieldResolver: subscribeFieldResolver !== null && subscribeFieldResolver !== void 0 ? subscribeFieldResolver : exports.defaultFieldResolver,
|
|
219
|
-
subsequentPayloads: new Set(),
|
|
220
151
|
errors: [],
|
|
221
152
|
};
|
|
222
153
|
}
|
|
@@ -225,7 +156,6 @@ function buildPerEventExecutionContext(exeContext, payload) {
|
|
|
225
156
|
return {
|
|
226
157
|
...exeContext,
|
|
227
158
|
rootValue: payload,
|
|
228
|
-
subsequentPayloads: new Set(),
|
|
229
159
|
errors: [],
|
|
230
160
|
};
|
|
231
161
|
}
|
|
@@ -235,32 +165,26 @@ function buildPerEventExecutionContext(exeContext, payload) {
|
|
|
235
165
|
function executeOperation(exeContext) {
|
|
236
166
|
const { operation, schema, fragments, variableValues, rootValue } = exeContext;
|
|
237
167
|
const rootType = (0, utils_1.getDefinedRootType)(schema, operation.operation, [operation]);
|
|
238
|
-
|
|
239
|
-
(0, utils_1.createGraphQLError)(`Schema is not configured to execute ${operation.operation} operation.`, {
|
|
240
|
-
nodes: operation,
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
const { fields: rootFields, patches } = (0, utils_1.collectFields)(schema, fragments, variableValues, rootType, operation.selectionSet);
|
|
168
|
+
const rootFields = (0, utils_1.collectFields)(schema, fragments, variableValues, rootType, operation.selectionSet);
|
|
244
169
|
const path = undefined;
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
}
|
|
256
|
-
return result;
|
|
170
|
+
switch (operation.operation) {
|
|
171
|
+
case 'query':
|
|
172
|
+
return executeFields(exeContext, rootType, rootValue, path, rootFields);
|
|
173
|
+
case 'mutation':
|
|
174
|
+
return executeFieldsSerially(exeContext, rootType, rootValue, path, rootFields);
|
|
175
|
+
case 'subscription':
|
|
176
|
+
// TODO: deprecate `subscribe` and move all logic here
|
|
177
|
+
// Temporary solution until we finish merging execute and subscribe together
|
|
178
|
+
return executeFields(exeContext, rootType, rootValue, path, rootFields);
|
|
179
|
+
}
|
|
180
|
+
throw new Error(`Can only execute queries, mutations and subscriptions, got "${operation.operation}".`);
|
|
257
181
|
}
|
|
258
182
|
/**
|
|
259
183
|
* Implements the "Executing selection sets" section of the spec
|
|
260
184
|
* for fields that must be executed serially.
|
|
261
185
|
*/
|
|
262
186
|
function executeFieldsSerially(exeContext, parentType, sourceValue, path, fields) {
|
|
263
|
-
return (0, utils_1.promiseReduce)(fields, (results, [responseName, fieldNodes]) => {
|
|
187
|
+
return (0, utils_1.promiseReduce)(fields.entries(), (results, [responseName, fieldNodes]) => {
|
|
264
188
|
const fieldPath = (0, utils_1.addPath)(path, responseName, parentType.name);
|
|
265
189
|
const result = executeField(exeContext, parentType, sourceValue, fieldNodes, fieldPath);
|
|
266
190
|
if (result === undefined) {
|
|
@@ -280,30 +204,19 @@ function executeFieldsSerially(exeContext, parentType, sourceValue, path, fields
|
|
|
280
204
|
* Implements the "Executing selection sets" section of the spec
|
|
281
205
|
* for fields that may be executed in parallel.
|
|
282
206
|
*/
|
|
283
|
-
function executeFields(exeContext, parentType, sourceValue, path, fields
|
|
207
|
+
function executeFields(exeContext, parentType, sourceValue, path, fields) {
|
|
284
208
|
const results = Object.create(null);
|
|
285
209
|
let containsPromise = false;
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
containsPromise = true;
|
|
294
|
-
}
|
|
210
|
+
for (const [responseName, fieldNodes] of fields.entries()) {
|
|
211
|
+
const fieldPath = (0, utils_1.addPath)(path, responseName, parentType.name);
|
|
212
|
+
const result = executeField(exeContext, parentType, sourceValue, fieldNodes, fieldPath);
|
|
213
|
+
if (result !== undefined) {
|
|
214
|
+
results[responseName] = result;
|
|
215
|
+
if ((0, utils_1.isPromise)(result)) {
|
|
216
|
+
containsPromise = true;
|
|
295
217
|
}
|
|
296
218
|
}
|
|
297
219
|
}
|
|
298
|
-
catch (error) {
|
|
299
|
-
if (containsPromise) {
|
|
300
|
-
// Ensure that any promises returned by other fields are handled, as they may also reject.
|
|
301
|
-
return (0, promiseForObject_js_1.promiseForObject)(results).finally(() => {
|
|
302
|
-
throw error;
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
throw error;
|
|
306
|
-
}
|
|
307
220
|
// If there are no promises, we can just return the object
|
|
308
221
|
if (!containsPromise) {
|
|
309
222
|
return results;
|
|
@@ -311,7 +224,13 @@ function executeFields(exeContext, parentType, sourceValue, path, fields, asyncP
|
|
|
311
224
|
// Otherwise, results is a map from field name to the result of resolving that
|
|
312
225
|
// field, which is possibly a promise. Return a promise that will return this
|
|
313
226
|
// same map, but with any promises replaced with the values they resolved to.
|
|
314
|
-
return (
|
|
227
|
+
return Promise.all(Object.values(results)).then(resolvedValues => {
|
|
228
|
+
const resolvedObject = Object.create(null);
|
|
229
|
+
for (const [i, key] of Object.keys(results).entries()) {
|
|
230
|
+
resolvedObject[key] = resolvedValues[i];
|
|
231
|
+
}
|
|
232
|
+
return resolvedObject;
|
|
233
|
+
});
|
|
315
234
|
}
|
|
316
235
|
/**
|
|
317
236
|
* Implements the "Executing fields" section of the spec
|
|
@@ -319,15 +238,14 @@ function executeFields(exeContext, parentType, sourceValue, path, fields, asyncP
|
|
|
319
238
|
* calling its resolve function, then calls completeValue to complete promises,
|
|
320
239
|
* serialize scalars, or execute the sub-selection-set for objects.
|
|
321
240
|
*/
|
|
322
|
-
function executeField(exeContext, parentType, source, fieldNodes, path
|
|
323
|
-
var _a
|
|
324
|
-
const errors = (_a = asyncPayloadRecord === null || asyncPayloadRecord === void 0 ? void 0 : asyncPayloadRecord.errors) !== null && _a !== void 0 ? _a : exeContext.errors;
|
|
241
|
+
function executeField(exeContext, parentType, source, fieldNodes, path) {
|
|
242
|
+
var _a;
|
|
325
243
|
const fieldDef = getFieldDef(exeContext.schema, parentType, fieldNodes[0]);
|
|
326
244
|
if (!fieldDef) {
|
|
327
245
|
return;
|
|
328
246
|
}
|
|
329
247
|
const returnType = fieldDef.type;
|
|
330
|
-
const resolveFn = (
|
|
248
|
+
const resolveFn = (_a = fieldDef.resolve) !== null && _a !== void 0 ? _a : exeContext.fieldResolver;
|
|
331
249
|
const info = buildResolveInfo(exeContext, fieldDef, fieldNodes, parentType, path);
|
|
332
250
|
// Get the resolve function, regardless of if its result is normal or abrupt (error).
|
|
333
251
|
try {
|
|
@@ -342,28 +260,24 @@ function executeField(exeContext, parentType, source, fieldNodes, path, asyncPay
|
|
|
342
260
|
const result = resolveFn(source, args, contextValue, info);
|
|
343
261
|
let completed;
|
|
344
262
|
if ((0, utils_1.isPromise)(result)) {
|
|
345
|
-
completed = result.then(resolved => completeValue(exeContext, returnType, fieldNodes, info, path, resolved
|
|
263
|
+
completed = result.then(resolved => completeValue(exeContext, returnType, fieldNodes, info, path, resolved));
|
|
346
264
|
}
|
|
347
265
|
else {
|
|
348
|
-
completed = completeValue(exeContext, returnType, fieldNodes, info, path, result
|
|
266
|
+
completed = completeValue(exeContext, returnType, fieldNodes, info, path, result);
|
|
349
267
|
}
|
|
350
268
|
if ((0, utils_1.isPromise)(completed)) {
|
|
351
269
|
// Note: we don't rely on a `catch` method, but we do expect "thenable"
|
|
352
270
|
// to take a second callback for the error case.
|
|
353
271
|
return completed.then(undefined, rawError => {
|
|
354
272
|
const error = (0, graphql_1.locatedError)(rawError, fieldNodes, (0, utils_1.pathToArray)(path));
|
|
355
|
-
|
|
356
|
-
filterSubsequentPayloads(exeContext, path, asyncPayloadRecord);
|
|
357
|
-
return handledError;
|
|
273
|
+
return handleFieldError(error, returnType, exeContext);
|
|
358
274
|
});
|
|
359
275
|
}
|
|
360
276
|
return completed;
|
|
361
277
|
}
|
|
362
278
|
catch (rawError) {
|
|
363
279
|
const error = (0, graphql_1.locatedError)(rawError, fieldNodes, (0, utils_1.pathToArray)(path));
|
|
364
|
-
|
|
365
|
-
filterSubsequentPayloads(exeContext, path, asyncPayloadRecord);
|
|
366
|
-
return handledError;
|
|
280
|
+
return handleFieldError(error, returnType, exeContext);
|
|
367
281
|
}
|
|
368
282
|
}
|
|
369
283
|
/**
|
|
@@ -387,7 +301,7 @@ function buildResolveInfo(exeContext, fieldDef, fieldNodes, parentType, path) {
|
|
|
387
301
|
};
|
|
388
302
|
}
|
|
389
303
|
exports.buildResolveInfo = buildResolveInfo;
|
|
390
|
-
function handleFieldError(error, returnType,
|
|
304
|
+
function handleFieldError(error, returnType, exeContext) {
|
|
391
305
|
// If the field type is non-nullable, then it is resolved without any
|
|
392
306
|
// protection from errors, however it still properly locates the error.
|
|
393
307
|
if ((0, graphql_1.isNonNullType)(returnType)) {
|
|
@@ -395,7 +309,7 @@ function handleFieldError(error, returnType, errors) {
|
|
|
395
309
|
}
|
|
396
310
|
// Otherwise, error protection is applied, logging the error and resolving
|
|
397
311
|
// a null value for this field if one is encountered.
|
|
398
|
-
errors.push(error);
|
|
312
|
+
exeContext.errors.push(error);
|
|
399
313
|
return null;
|
|
400
314
|
}
|
|
401
315
|
/**
|
|
@@ -419,7 +333,7 @@ function handleFieldError(error, returnType, errors) {
|
|
|
419
333
|
* Otherwise, the field type expects a sub-selection set, and will complete the
|
|
420
334
|
* value by executing all sub-selections.
|
|
421
335
|
*/
|
|
422
|
-
function completeValue(exeContext, returnType, fieldNodes, info, path, result
|
|
336
|
+
function completeValue(exeContext, returnType, fieldNodes, info, path, result) {
|
|
423
337
|
// If result is an Error, throw a located error.
|
|
424
338
|
if (result instanceof Error) {
|
|
425
339
|
throw result;
|
|
@@ -427,7 +341,7 @@ function completeValue(exeContext, returnType, fieldNodes, info, path, result, a
|
|
|
427
341
|
// If field type is NonNull, complete for inner type, and throw field error
|
|
428
342
|
// if result is null.
|
|
429
343
|
if ((0, graphql_1.isNonNullType)(returnType)) {
|
|
430
|
-
const completed = completeValue(exeContext, returnType.ofType, fieldNodes, info, path, result
|
|
344
|
+
const completed = completeValue(exeContext, returnType.ofType, fieldNodes, info, path, result);
|
|
431
345
|
if (completed === null) {
|
|
432
346
|
throw new Error(`Cannot return null for non-nullable field ${info.parentType.name}.${info.fieldName}.`);
|
|
433
347
|
}
|
|
@@ -439,7 +353,7 @@ function completeValue(exeContext, returnType, fieldNodes, info, path, result, a
|
|
|
439
353
|
}
|
|
440
354
|
// If field type is List, complete each item in the list with the inner type
|
|
441
355
|
if ((0, graphql_1.isListType)(returnType)) {
|
|
442
|
-
return completeListValue(exeContext, returnType, fieldNodes, info, path, result
|
|
356
|
+
return completeListValue(exeContext, returnType, fieldNodes, info, path, result);
|
|
443
357
|
}
|
|
444
358
|
// If field type is a leaf type, Scalar or Enum, serialize to a valid value,
|
|
445
359
|
// returning null if serialization is not possible.
|
|
@@ -449,74 +363,51 @@ function completeValue(exeContext, returnType, fieldNodes, info, path, result, a
|
|
|
449
363
|
// If field type is an abstract type, Interface or Union, determine the
|
|
450
364
|
// runtime Object type and complete for that type.
|
|
451
365
|
if ((0, graphql_1.isAbstractType)(returnType)) {
|
|
452
|
-
return completeAbstractValue(exeContext, returnType, fieldNodes, info, path, result
|
|
366
|
+
return completeAbstractValue(exeContext, returnType, fieldNodes, info, path, result);
|
|
453
367
|
}
|
|
454
368
|
// If field type is Object, execute and complete all sub-selections.
|
|
455
369
|
if ((0, graphql_1.isObjectType)(returnType)) {
|
|
456
|
-
return completeObjectValue(exeContext, returnType, fieldNodes, info, path, result
|
|
370
|
+
return completeObjectValue(exeContext, returnType, fieldNodes, info, path, result);
|
|
457
371
|
}
|
|
458
372
|
/* c8 ignore next 6 */
|
|
459
373
|
// Not reachable, all possible output types have been considered.
|
|
460
374
|
console.assert(false, 'Cannot complete value of unexpected output type: ' + (0, utils_1.inspect)(returnType));
|
|
461
375
|
}
|
|
462
|
-
/**
|
|
463
|
-
* Returns an object containing the `@stream` arguments if a field should be
|
|
464
|
-
* streamed based on the experimental flag, stream directive present and
|
|
465
|
-
* not disabled by the "if" argument.
|
|
466
|
-
*/
|
|
467
|
-
function getStreamValues(exeContext, fieldNodes, path) {
|
|
468
|
-
// do not stream inner lists of multi-dimensional lists
|
|
469
|
-
if (typeof path.key === 'number') {
|
|
470
|
-
return;
|
|
471
|
-
}
|
|
472
|
-
// validation only allows equivalent streams on multiple fields, so it is
|
|
473
|
-
// safe to only check the first fieldNode for the stream directive
|
|
474
|
-
const stream = (0, graphql_1.getDirectiveValues)(utils_1.GraphQLStreamDirective, fieldNodes[0], exeContext.variableValues);
|
|
475
|
-
if (!stream) {
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
if (stream['if'] === false) {
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
(0, invariant_js_1.invariant)(typeof stream['initialCount'] === 'number', 'initialCount must be a number');
|
|
482
|
-
(0, invariant_js_1.invariant)(stream['initialCount'] >= 0, 'initialCount must be a positive integer');
|
|
483
|
-
return {
|
|
484
|
-
initialCount: stream['initialCount'],
|
|
485
|
-
label: typeof stream['label'] === 'string' ? stream['label'] : undefined,
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
376
|
/**
|
|
489
377
|
* Complete a async iterator value by completing the result and calling
|
|
490
378
|
* recursively until all the results are completed.
|
|
491
379
|
*/
|
|
492
|
-
async function completeAsyncIteratorValue(exeContext, itemType, fieldNodes, info, path, iterator
|
|
493
|
-
var _a;
|
|
494
|
-
const errors = (_a = asyncPayloadRecord === null || asyncPayloadRecord === void 0 ? void 0 : asyncPayloadRecord.errors) !== null && _a !== void 0 ? _a : exeContext.errors;
|
|
495
|
-
const stream = getStreamValues(exeContext, fieldNodes, path);
|
|
380
|
+
async function completeAsyncIteratorValue(exeContext, itemType, fieldNodes, info, path, iterator) {
|
|
496
381
|
let containsPromise = false;
|
|
497
382
|
const completedResults = [];
|
|
498
383
|
let index = 0;
|
|
499
384
|
while (true) {
|
|
500
|
-
|
|
501
|
-
executeStreamIterator(index, iterator, exeContext, fieldNodes, info, itemType, path, stream.label, asyncPayloadRecord);
|
|
502
|
-
break;
|
|
503
|
-
}
|
|
504
|
-
const itemPath = (0, utils_1.addPath)(path, index, undefined);
|
|
505
|
-
let iteration;
|
|
385
|
+
const fieldPath = (0, utils_1.addPath)(path, index, undefined);
|
|
506
386
|
try {
|
|
507
|
-
|
|
508
|
-
if (
|
|
387
|
+
const { value, done } = await iterator.next();
|
|
388
|
+
if (done) {
|
|
509
389
|
break;
|
|
510
390
|
}
|
|
391
|
+
try {
|
|
392
|
+
// TODO can the error checking logic be consolidated with completeListValue?
|
|
393
|
+
const completedItem = completeValue(exeContext, itemType, fieldNodes, info, fieldPath, value);
|
|
394
|
+
if ((0, utils_1.isPromise)(completedItem)) {
|
|
395
|
+
containsPromise = true;
|
|
396
|
+
}
|
|
397
|
+
completedResults.push(completedItem);
|
|
398
|
+
}
|
|
399
|
+
catch (rawError) {
|
|
400
|
+
completedResults.push(null);
|
|
401
|
+
const error = (0, graphql_1.locatedError)(rawError, fieldNodes, (0, utils_1.pathToArray)(fieldPath));
|
|
402
|
+
handleFieldError(error, itemType, exeContext);
|
|
403
|
+
}
|
|
511
404
|
}
|
|
512
405
|
catch (rawError) {
|
|
513
|
-
|
|
514
|
-
|
|
406
|
+
completedResults.push(null);
|
|
407
|
+
const error = (0, graphql_1.locatedError)(rawError, fieldNodes, (0, utils_1.pathToArray)(fieldPath));
|
|
408
|
+
handleFieldError(error, itemType, exeContext);
|
|
515
409
|
break;
|
|
516
410
|
}
|
|
517
|
-
if (completeListItemValue(iteration.value, completedResults, errors, exeContext, itemType, fieldNodes, info, itemPath, asyncPayloadRecord)) {
|
|
518
|
-
containsPromise = true;
|
|
519
|
-
}
|
|
520
411
|
index += 1;
|
|
521
412
|
}
|
|
522
413
|
return containsPromise ? Promise.all(completedResults) : completedResults;
|
|
@@ -525,75 +416,48 @@ async function completeAsyncIteratorValue(exeContext, itemType, fieldNodes, info
|
|
|
525
416
|
* Complete a list value by completing each item in the list with the
|
|
526
417
|
* inner type
|
|
527
418
|
*/
|
|
528
|
-
function completeListValue(exeContext, returnType, fieldNodes, info, path, result
|
|
529
|
-
var _a;
|
|
419
|
+
function completeListValue(exeContext, returnType, fieldNodes, info, path, result) {
|
|
530
420
|
const itemType = returnType.ofType;
|
|
531
|
-
const errors = (_a = asyncPayloadRecord === null || asyncPayloadRecord === void 0 ? void 0 : asyncPayloadRecord.errors) !== null && _a !== void 0 ? _a : exeContext.errors;
|
|
532
421
|
if ((0, utils_1.isAsyncIterable)(result)) {
|
|
533
422
|
const iterator = result[Symbol.asyncIterator]();
|
|
534
|
-
return completeAsyncIteratorValue(exeContext, itemType, fieldNodes, info, path, iterator
|
|
423
|
+
return completeAsyncIteratorValue(exeContext, itemType, fieldNodes, info, path, iterator);
|
|
535
424
|
}
|
|
536
425
|
if (!(0, utils_1.isIterableObject)(result)) {
|
|
537
426
|
throw (0, utils_1.createGraphQLError)(`Expected Iterable, but did not find one for field "${info.parentType.name}.${info.fieldName}".`);
|
|
538
427
|
}
|
|
539
|
-
const stream = getStreamValues(exeContext, fieldNodes, path);
|
|
540
428
|
// This is specified as a simple map, however we're optimizing the path
|
|
541
429
|
// where the list contains no Promises by avoiding creating another Promise.
|
|
542
430
|
let containsPromise = false;
|
|
543
|
-
|
|
544
|
-
const completedResults = [];
|
|
545
|
-
let index = 0;
|
|
546
|
-
for (const item of result) {
|
|
431
|
+
const completedResults = Array.from(result, (item, index) => {
|
|
547
432
|
// No need to modify the info object containing the path,
|
|
548
433
|
// since from here on it is not ever accessed by resolver functions.
|
|
549
434
|
const itemPath = (0, utils_1.addPath)(path, index, undefined);
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
435
|
+
try {
|
|
436
|
+
let completedItem;
|
|
437
|
+
if ((0, utils_1.isPromise)(item)) {
|
|
438
|
+
completedItem = item.then(resolved => completeValue(exeContext, itemType, fieldNodes, info, itemPath, resolved));
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
completedItem = completeValue(exeContext, itemType, fieldNodes, info, itemPath, item);
|
|
442
|
+
}
|
|
443
|
+
if ((0, utils_1.isPromise)(completedItem)) {
|
|
444
|
+
containsPromise = true;
|
|
445
|
+
// Note: we don't rely on a `catch` method, but we do expect "thenable"
|
|
446
|
+
// to take a second callback for the error case.
|
|
447
|
+
return completedItem.then(undefined, rawError => {
|
|
448
|
+
const error = (0, graphql_1.locatedError)(rawError, fieldNodes, (0, utils_1.pathToArray)(itemPath));
|
|
449
|
+
return handleFieldError(error, itemType, exeContext);
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
return completedItem;
|
|
554
453
|
}
|
|
555
|
-
|
|
556
|
-
|
|
454
|
+
catch (rawError) {
|
|
455
|
+
const error = (0, graphql_1.locatedError)(rawError, fieldNodes, (0, utils_1.pathToArray)(itemPath));
|
|
456
|
+
return handleFieldError(error, itemType, exeContext);
|
|
557
457
|
}
|
|
558
|
-
|
|
559
|
-
}
|
|
458
|
+
});
|
|
560
459
|
return containsPromise ? Promise.all(completedResults) : completedResults;
|
|
561
460
|
}
|
|
562
|
-
/**
|
|
563
|
-
* Complete a list item value by adding it to the completed results.
|
|
564
|
-
*
|
|
565
|
-
* Returns true if the value is a Promise.
|
|
566
|
-
*/
|
|
567
|
-
function completeListItemValue(item, completedResults, errors, exeContext, itemType, fieldNodes, info, itemPath, asyncPayloadRecord) {
|
|
568
|
-
try {
|
|
569
|
-
let completedItem;
|
|
570
|
-
if ((0, utils_1.isPromise)(item)) {
|
|
571
|
-
completedItem = item.then(resolved => completeValue(exeContext, itemType, fieldNodes, info, itemPath, resolved, asyncPayloadRecord));
|
|
572
|
-
}
|
|
573
|
-
else {
|
|
574
|
-
completedItem = completeValue(exeContext, itemType, fieldNodes, info, itemPath, item, asyncPayloadRecord);
|
|
575
|
-
}
|
|
576
|
-
if ((0, utils_1.isPromise)(completedItem)) {
|
|
577
|
-
// Note: we don't rely on a `catch` method, but we do expect "thenable"
|
|
578
|
-
// to take a second callback for the error case.
|
|
579
|
-
completedResults.push(completedItem.then(undefined, rawError => {
|
|
580
|
-
const error = (0, graphql_1.locatedError)(rawError, fieldNodes, (0, utils_1.pathToArray)(itemPath));
|
|
581
|
-
const handledError = handleFieldError(error, itemType, errors);
|
|
582
|
-
filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord);
|
|
583
|
-
return handledError;
|
|
584
|
-
}));
|
|
585
|
-
return true;
|
|
586
|
-
}
|
|
587
|
-
completedResults.push(completedItem);
|
|
588
|
-
}
|
|
589
|
-
catch (rawError) {
|
|
590
|
-
const error = (0, graphql_1.locatedError)(rawError, fieldNodes, (0, utils_1.pathToArray)(itemPath));
|
|
591
|
-
const handledError = handleFieldError(error, itemType, errors);
|
|
592
|
-
filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord);
|
|
593
|
-
completedResults.push(handledError);
|
|
594
|
-
}
|
|
595
|
-
return false;
|
|
596
|
-
}
|
|
597
461
|
/**
|
|
598
462
|
* Complete a Scalar or Enum by serializing to a valid value, returning
|
|
599
463
|
* null if serialization is not possible.
|
|
@@ -610,15 +474,15 @@ function completeLeafValue(returnType, result) {
|
|
|
610
474
|
* Complete a value of an abstract type by determining the runtime object type
|
|
611
475
|
* of that value, then complete the value for that type.
|
|
612
476
|
*/
|
|
613
|
-
function completeAbstractValue(exeContext, returnType, fieldNodes, info, path, result
|
|
477
|
+
function completeAbstractValue(exeContext, returnType, fieldNodes, info, path, result) {
|
|
614
478
|
var _a;
|
|
615
479
|
const resolveTypeFn = (_a = returnType.resolveType) !== null && _a !== void 0 ? _a : exeContext.typeResolver;
|
|
616
480
|
const contextValue = exeContext.contextValue;
|
|
617
481
|
const runtimeType = resolveTypeFn(result, contextValue, info, returnType);
|
|
618
482
|
if ((0, utils_1.isPromise)(runtimeType)) {
|
|
619
|
-
return runtimeType.then(resolvedRuntimeType => completeObjectValue(exeContext, ensureValidRuntimeType(resolvedRuntimeType, exeContext, returnType, fieldNodes, info, result), fieldNodes, info, path, result
|
|
483
|
+
return runtimeType.then(resolvedRuntimeType => completeObjectValue(exeContext, ensureValidRuntimeType(resolvedRuntimeType, exeContext, returnType, fieldNodes, info, result), fieldNodes, info, path, result));
|
|
620
484
|
}
|
|
621
|
-
return completeObjectValue(exeContext, ensureValidRuntimeType(runtimeType, exeContext, returnType, fieldNodes, info, result), fieldNodes, info, path, result
|
|
485
|
+
return completeObjectValue(exeContext, ensureValidRuntimeType(runtimeType, exeContext, returnType, fieldNodes, info, result), fieldNodes, info, path, result);
|
|
622
486
|
}
|
|
623
487
|
function ensureValidRuntimeType(runtimeTypeName, exeContext, returnType, fieldNodes, info, result) {
|
|
624
488
|
if (runtimeTypeName == null) {
|
|
@@ -648,7 +512,9 @@ function ensureValidRuntimeType(runtimeTypeName, exeContext, returnType, fieldNo
|
|
|
648
512
|
/**
|
|
649
513
|
* Complete an Object value by executing all sub-selections.
|
|
650
514
|
*/
|
|
651
|
-
function completeObjectValue(exeContext, returnType, fieldNodes, info, path, result
|
|
515
|
+
function completeObjectValue(exeContext, returnType, fieldNodes, info, path, result) {
|
|
516
|
+
// Collect sub-fields to execute to complete this value.
|
|
517
|
+
const subFieldNodes = (0, utils_1.collectSubFields)(exeContext.schema, exeContext.fragments, exeContext.variableValues, returnType, fieldNodes);
|
|
652
518
|
// If there is an isTypeOf predicate function, call it with the
|
|
653
519
|
// current result. If isTypeOf returns false, then raise an error rather
|
|
654
520
|
// than continuing execution.
|
|
@@ -659,30 +525,20 @@ function completeObjectValue(exeContext, returnType, fieldNodes, info, path, res
|
|
|
659
525
|
if (!resolvedIsTypeOf) {
|
|
660
526
|
throw invalidReturnTypeError(returnType, result, fieldNodes);
|
|
661
527
|
}
|
|
662
|
-
return
|
|
528
|
+
return executeFields(exeContext, returnType, result, path, subFieldNodes);
|
|
663
529
|
});
|
|
664
530
|
}
|
|
665
531
|
if (!isTypeOf) {
|
|
666
532
|
throw invalidReturnTypeError(returnType, result, fieldNodes);
|
|
667
533
|
}
|
|
668
534
|
}
|
|
669
|
-
return
|
|
535
|
+
return executeFields(exeContext, returnType, result, path, subFieldNodes);
|
|
670
536
|
}
|
|
671
537
|
function invalidReturnTypeError(returnType, result, fieldNodes) {
|
|
672
538
|
return (0, utils_1.createGraphQLError)(`Expected value of type "${returnType.name}" but got: ${(0, utils_1.inspect)(result)}.`, {
|
|
673
539
|
nodes: fieldNodes,
|
|
674
540
|
});
|
|
675
541
|
}
|
|
676
|
-
function collectAndExecuteSubfields(exeContext, returnType, fieldNodes, path, result, asyncPayloadRecord) {
|
|
677
|
-
// Collect sub-fields to execute to complete this value.
|
|
678
|
-
const { fields: subFieldNodes, patches: subPatches } = collectSubfields(exeContext, returnType, fieldNodes);
|
|
679
|
-
const subFields = executeFields(exeContext, returnType, result, path, subFieldNodes, asyncPayloadRecord);
|
|
680
|
-
for (const subPatch of subPatches) {
|
|
681
|
-
const { label, fields: subPatchFieldNodes } = subPatch;
|
|
682
|
-
executeDeferredFragment(exeContext, returnType, result, subPatchFieldNodes, label, path, asyncPayloadRecord);
|
|
683
|
-
}
|
|
684
|
-
return subFields;
|
|
685
|
-
}
|
|
686
542
|
/**
|
|
687
543
|
* If a resolveType function is not given, then a default resolve behavior is
|
|
688
544
|
* used which attempts two strategies:
|
|
@@ -750,78 +606,19 @@ exports.defaultFieldResolver = defaultFieldResolver;
|
|
|
750
606
|
* is not an async iterable.
|
|
751
607
|
*
|
|
752
608
|
* If the client-provided arguments to this function do not result in a
|
|
753
|
-
* compliant subscription, a GraphQL Response (ExecutionResult) with
|
|
754
|
-
* errors and no data will be returned.
|
|
609
|
+
* compliant subscription, a GraphQL Response (ExecutionResult) with
|
|
610
|
+
* descriptive errors and no data will be returned.
|
|
755
611
|
*
|
|
756
|
-
* If the source stream could not be created due to faulty subscription
|
|
757
|
-
* logic or underlying systems, the promise will resolve to a single
|
|
612
|
+
* If the source stream could not be created due to faulty subscription
|
|
613
|
+
* resolver logic or underlying systems, the promise will resolve to a single
|
|
758
614
|
* ExecutionResult containing `errors` and no `data`.
|
|
759
615
|
*
|
|
760
616
|
* If the operation succeeded, the promise resolves to an AsyncIterator, which
|
|
761
617
|
* yields a stream of ExecutionResults representing the response stream.
|
|
762
618
|
*
|
|
763
|
-
*
|
|
764
|
-
* If an operation which would defer or stream data is executed with this
|
|
765
|
-
* function, each `InitialIncrementalExecutionResult` and
|
|
766
|
-
* `SubsequentIncrementalExecutionResult` in the result stream will be replaced
|
|
767
|
-
* with an `ExecutionResult` with a single error stating that defer/stream is
|
|
768
|
-
* not supported. Use `experimentalSubscribeIncrementally` if you want to
|
|
769
|
-
* support incremental delivery.
|
|
770
|
-
*
|
|
771
|
-
* Accepts an object with named arguments.
|
|
619
|
+
* Accepts either an object with named arguments, or individual arguments.
|
|
772
620
|
*/
|
|
773
621
|
function subscribe(args) {
|
|
774
|
-
const maybePromise = experimentalSubscribeIncrementally(args);
|
|
775
|
-
if ((0, utils_1.isPromise)(maybePromise)) {
|
|
776
|
-
return maybePromise.then(resultOrIterable => (0, utils_1.isAsyncIterable)(resultOrIterable)
|
|
777
|
-
? (0, utils_1.mapAsyncIterator)(resultOrIterable, ensureSingleExecutionResult)
|
|
778
|
-
: resultOrIterable);
|
|
779
|
-
}
|
|
780
|
-
return (0, utils_1.isAsyncIterable)(maybePromise) ? (0, utils_1.mapAsyncIterator)(maybePromise, ensureSingleExecutionResult) : maybePromise;
|
|
781
|
-
}
|
|
782
|
-
exports.subscribe = subscribe;
|
|
783
|
-
function ensureSingleExecutionResult(result) {
|
|
784
|
-
if ('hasNext' in result) {
|
|
785
|
-
return {
|
|
786
|
-
errors: [(0, utils_1.createGraphQLError)(UNEXPECTED_MULTIPLE_PAYLOADS)],
|
|
787
|
-
};
|
|
788
|
-
}
|
|
789
|
-
return result;
|
|
790
|
-
}
|
|
791
|
-
/**
|
|
792
|
-
* Implements the "Subscribe" algorithm described in the GraphQL specification,
|
|
793
|
-
* including `@defer` and `@stream` as proposed in
|
|
794
|
-
* https://github.com/graphql/graphql-spec/pull/742
|
|
795
|
-
*
|
|
796
|
-
* Returns a Promise which resolves to either an AsyncIterator (if successful)
|
|
797
|
-
* or an ExecutionResult (error). The promise will be rejected if the schema or
|
|
798
|
-
* other arguments to this function are invalid, or if the resolved event stream
|
|
799
|
-
* is not an async iterable.
|
|
800
|
-
*
|
|
801
|
-
* If the client-provided arguments to this function do not result in a
|
|
802
|
-
* compliant subscription, a GraphQL Response (ExecutionResult) with descriptive
|
|
803
|
-
* errors and no data will be returned.
|
|
804
|
-
*
|
|
805
|
-
* If the source stream could not be created due to faulty subscription resolver
|
|
806
|
-
* logic or underlying systems, the promise will resolve to a single
|
|
807
|
-
* ExecutionResult containing `errors` and no `data`.
|
|
808
|
-
*
|
|
809
|
-
* If the operation succeeded, the promise resolves to an AsyncIterator, which
|
|
810
|
-
* yields a stream of result representing the response stream.
|
|
811
|
-
*
|
|
812
|
-
* Each result may be an ExecutionResult with no `hasNext` (if executing the
|
|
813
|
-
* event did not use `@defer` or `@stream`), or an
|
|
814
|
-
* `InitialIncrementalExecutionResult` or `SubsequentIncrementalExecutionResult`
|
|
815
|
-
* (if executing the event used `@defer` or `@stream`). In the case of
|
|
816
|
-
* incremental execution results, each event produces a single
|
|
817
|
-
* `InitialIncrementalExecutionResult` followed by one or more
|
|
818
|
-
* `SubsequentIncrementalExecutionResult`s; all but the last have `hasNext: true`,
|
|
819
|
-
* and the last has `hasNext: false`. There is no interleaving between results
|
|
820
|
-
* generated from the same original event.
|
|
821
|
-
*
|
|
822
|
-
* Accepts an object with named arguments.
|
|
823
|
-
*/
|
|
824
|
-
function experimentalSubscribeIncrementally(args) {
|
|
825
622
|
// If a valid execution context cannot be created due to incorrect arguments,
|
|
826
623
|
// a "Response" with only errors is returned.
|
|
827
624
|
const exeContext = buildExecutionContext(args);
|
|
@@ -835,16 +632,7 @@ function experimentalSubscribeIncrementally(args) {
|
|
|
835
632
|
}
|
|
836
633
|
return mapSourceToResponse(exeContext, resultOrStream);
|
|
837
634
|
}
|
|
838
|
-
exports.
|
|
839
|
-
async function* ensureAsyncIterable(someExecutionResult) {
|
|
840
|
-
if ('initialResult' in someExecutionResult) {
|
|
841
|
-
yield someExecutionResult.initialResult;
|
|
842
|
-
yield* someExecutionResult.subsequentResults;
|
|
843
|
-
}
|
|
844
|
-
else {
|
|
845
|
-
yield someExecutionResult;
|
|
846
|
-
}
|
|
847
|
-
}
|
|
635
|
+
exports.subscribe = subscribe;
|
|
848
636
|
function mapSourceToResponse(exeContext, resultOrStream) {
|
|
849
637
|
if (!(0, utils_1.isAsyncIterable)(resultOrStream)) {
|
|
850
638
|
return resultOrStream;
|
|
@@ -855,7 +643,7 @@ function mapSourceToResponse(exeContext, resultOrStream) {
|
|
|
855
643
|
// the GraphQL specification. The `execute` function provides the
|
|
856
644
|
// "ExecuteSubscriptionEvent" algorithm, as it is nearly identical to the
|
|
857
645
|
// "ExecuteQuery" algorithm, for which `execute` is also used.
|
|
858
|
-
return (0,
|
|
646
|
+
return (0, utils_1.mapAsyncIterator)(resultOrStream[Symbol.asyncIterator](), (payload) => executeImpl(buildPerEventExecutionContext(exeContext, payload)));
|
|
859
647
|
}
|
|
860
648
|
/**
|
|
861
649
|
* Implements the "CreateSourceEventStream" algorithm described in the
|
|
@@ -915,7 +703,7 @@ function executeSubscription(exeContext) {
|
|
|
915
703
|
if (rootType == null) {
|
|
916
704
|
throw (0, utils_1.createGraphQLError)('Schema is not configured to execute subscription operation.', { nodes: operation });
|
|
917
705
|
}
|
|
918
|
-
const
|
|
706
|
+
const rootFields = (0, utils_1.collectFields)(schema, fragments, variableValues, rootType, operation.selectionSet);
|
|
919
707
|
const [responseName, fieldNodes] = [...rootFields.entries()][0];
|
|
920
708
|
const fieldName = fieldNodes[0].name.value;
|
|
921
709
|
const fieldDef = getFieldDef(schema, rootType, fieldNodes[0]);
|
|
@@ -959,339 +747,6 @@ function assertEventStream(result) {
|
|
|
959
747
|
}
|
|
960
748
|
return result;
|
|
961
749
|
}
|
|
962
|
-
function executeDeferredFragment(exeContext, parentType, sourceValue, fields, label, path, parentContext) {
|
|
963
|
-
const asyncPayloadRecord = new DeferredFragmentRecord({
|
|
964
|
-
label,
|
|
965
|
-
path,
|
|
966
|
-
parentContext,
|
|
967
|
-
exeContext,
|
|
968
|
-
});
|
|
969
|
-
let promiseOrData;
|
|
970
|
-
try {
|
|
971
|
-
promiseOrData = executeFields(exeContext, parentType, sourceValue, path, fields, asyncPayloadRecord);
|
|
972
|
-
if ((0, utils_1.isPromise)(promiseOrData)) {
|
|
973
|
-
promiseOrData = promiseOrData.then(null, e => {
|
|
974
|
-
asyncPayloadRecord.errors.push(e);
|
|
975
|
-
return null;
|
|
976
|
-
});
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
catch (e) {
|
|
980
|
-
asyncPayloadRecord.errors.push(e);
|
|
981
|
-
promiseOrData = null;
|
|
982
|
-
}
|
|
983
|
-
asyncPayloadRecord.addData(promiseOrData);
|
|
984
|
-
}
|
|
985
|
-
function executeStreamField(path, itemPath, item, exeContext, fieldNodes, info, itemType, label, parentContext) {
|
|
986
|
-
const asyncPayloadRecord = new StreamRecord({
|
|
987
|
-
label,
|
|
988
|
-
path: itemPath,
|
|
989
|
-
parentContext,
|
|
990
|
-
exeContext,
|
|
991
|
-
});
|
|
992
|
-
let completedItem;
|
|
993
|
-
try {
|
|
994
|
-
try {
|
|
995
|
-
if ((0, utils_1.isPromise)(item)) {
|
|
996
|
-
completedItem = item.then(resolved => completeValue(exeContext, itemType, fieldNodes, info, itemPath, resolved, asyncPayloadRecord));
|
|
997
|
-
}
|
|
998
|
-
else {
|
|
999
|
-
completedItem = completeValue(exeContext, itemType, fieldNodes, info, itemPath, item, asyncPayloadRecord);
|
|
1000
|
-
}
|
|
1001
|
-
if ((0, utils_1.isPromise)(completedItem)) {
|
|
1002
|
-
// Note: we don't rely on a `catch` method, but we do expect "thenable"
|
|
1003
|
-
// to take a second callback for the error case.
|
|
1004
|
-
completedItem = completedItem.then(undefined, rawError => {
|
|
1005
|
-
const error = (0, graphql_1.locatedError)(rawError, fieldNodes, (0, utils_1.pathToArray)(itemPath));
|
|
1006
|
-
const handledError = handleFieldError(error, itemType, asyncPayloadRecord.errors);
|
|
1007
|
-
filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord);
|
|
1008
|
-
return handledError;
|
|
1009
|
-
});
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
catch (rawError) {
|
|
1013
|
-
const error = (0, graphql_1.locatedError)(rawError, fieldNodes, (0, utils_1.pathToArray)(itemPath));
|
|
1014
|
-
completedItem = handleFieldError(error, itemType, asyncPayloadRecord.errors);
|
|
1015
|
-
filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord);
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
catch (error) {
|
|
1019
|
-
asyncPayloadRecord.errors.push(error);
|
|
1020
|
-
filterSubsequentPayloads(exeContext, path, asyncPayloadRecord);
|
|
1021
|
-
asyncPayloadRecord.addItems(null);
|
|
1022
|
-
return asyncPayloadRecord;
|
|
1023
|
-
}
|
|
1024
|
-
let completedItems;
|
|
1025
|
-
if ((0, utils_1.isPromise)(completedItem)) {
|
|
1026
|
-
completedItems = completedItem.then(value => [value], error => {
|
|
1027
|
-
asyncPayloadRecord.errors.push(error);
|
|
1028
|
-
filterSubsequentPayloads(exeContext, path, asyncPayloadRecord);
|
|
1029
|
-
return null;
|
|
1030
|
-
});
|
|
1031
|
-
}
|
|
1032
|
-
else {
|
|
1033
|
-
completedItems = [completedItem];
|
|
1034
|
-
}
|
|
1035
|
-
asyncPayloadRecord.addItems(completedItems);
|
|
1036
|
-
return asyncPayloadRecord;
|
|
1037
|
-
}
|
|
1038
|
-
async function executeStreamIteratorItem(iterator, exeContext, fieldNodes, info, itemType, asyncPayloadRecord, itemPath) {
|
|
1039
|
-
let item;
|
|
1040
|
-
try {
|
|
1041
|
-
const { value, done } = await iterator.next();
|
|
1042
|
-
if (done) {
|
|
1043
|
-
asyncPayloadRecord.setIsCompletedIterator();
|
|
1044
|
-
return { done, value: undefined };
|
|
1045
|
-
}
|
|
1046
|
-
item = value;
|
|
1047
|
-
}
|
|
1048
|
-
catch (rawError) {
|
|
1049
|
-
const error = (0, graphql_1.locatedError)(rawError, fieldNodes, (0, utils_1.pathToArray)(itemPath));
|
|
1050
|
-
const value = handleFieldError(error, itemType, asyncPayloadRecord.errors);
|
|
1051
|
-
// don't continue if iterator throws
|
|
1052
|
-
return { done: true, value };
|
|
1053
|
-
}
|
|
1054
|
-
let completedItem;
|
|
1055
|
-
try {
|
|
1056
|
-
completedItem = completeValue(exeContext, itemType, fieldNodes, info, itemPath, item, asyncPayloadRecord);
|
|
1057
|
-
if ((0, utils_1.isPromise)(completedItem)) {
|
|
1058
|
-
completedItem = completedItem.then(undefined, rawError => {
|
|
1059
|
-
const error = (0, graphql_1.locatedError)(rawError, fieldNodes, (0, utils_1.pathToArray)(itemPath));
|
|
1060
|
-
const handledError = handleFieldError(error, itemType, asyncPayloadRecord.errors);
|
|
1061
|
-
filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord);
|
|
1062
|
-
return handledError;
|
|
1063
|
-
});
|
|
1064
|
-
}
|
|
1065
|
-
return { done: false, value: completedItem };
|
|
1066
|
-
}
|
|
1067
|
-
catch (rawError) {
|
|
1068
|
-
const error = (0, graphql_1.locatedError)(rawError, fieldNodes, (0, utils_1.pathToArray)(itemPath));
|
|
1069
|
-
const value = handleFieldError(error, itemType, asyncPayloadRecord.errors);
|
|
1070
|
-
filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord);
|
|
1071
|
-
return { done: false, value };
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
async function executeStreamIterator(initialIndex, iterator, exeContext, fieldNodes, info, itemType, path, label, parentContext) {
|
|
1075
|
-
let index = initialIndex;
|
|
1076
|
-
let previousAsyncPayloadRecord = parentContext !== null && parentContext !== void 0 ? parentContext : undefined;
|
|
1077
|
-
while (true) {
|
|
1078
|
-
const itemPath = (0, utils_1.addPath)(path, index, undefined);
|
|
1079
|
-
const asyncPayloadRecord = new StreamRecord({
|
|
1080
|
-
label,
|
|
1081
|
-
path: itemPath,
|
|
1082
|
-
parentContext: previousAsyncPayloadRecord,
|
|
1083
|
-
iterator,
|
|
1084
|
-
exeContext,
|
|
1085
|
-
});
|
|
1086
|
-
let iteration;
|
|
1087
|
-
try {
|
|
1088
|
-
iteration = await executeStreamIteratorItem(iterator, exeContext, fieldNodes, info, itemType, asyncPayloadRecord, itemPath);
|
|
1089
|
-
}
|
|
1090
|
-
catch (error) {
|
|
1091
|
-
asyncPayloadRecord.errors.push(error);
|
|
1092
|
-
filterSubsequentPayloads(exeContext, path, asyncPayloadRecord);
|
|
1093
|
-
asyncPayloadRecord.addItems(null);
|
|
1094
|
-
// entire stream has errored and bubbled upwards
|
|
1095
|
-
if (iterator === null || iterator === void 0 ? void 0 : iterator.return) {
|
|
1096
|
-
iterator.return().catch(() => {
|
|
1097
|
-
// ignore errors
|
|
1098
|
-
});
|
|
1099
|
-
}
|
|
1100
|
-
return;
|
|
1101
|
-
}
|
|
1102
|
-
const { done, value: completedItem } = iteration;
|
|
1103
|
-
let completedItems;
|
|
1104
|
-
if ((0, utils_1.isPromise)(completedItem)) {
|
|
1105
|
-
completedItems = completedItem.then(value => [value], error => {
|
|
1106
|
-
asyncPayloadRecord.errors.push(error);
|
|
1107
|
-
filterSubsequentPayloads(exeContext, path, asyncPayloadRecord);
|
|
1108
|
-
return null;
|
|
1109
|
-
});
|
|
1110
|
-
}
|
|
1111
|
-
else {
|
|
1112
|
-
completedItems = [completedItem];
|
|
1113
|
-
}
|
|
1114
|
-
asyncPayloadRecord.addItems(completedItems);
|
|
1115
|
-
if (done) {
|
|
1116
|
-
break;
|
|
1117
|
-
}
|
|
1118
|
-
previousAsyncPayloadRecord = asyncPayloadRecord;
|
|
1119
|
-
index++;
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
function filterSubsequentPayloads(exeContext, nullPath, currentAsyncRecord) {
|
|
1123
|
-
const nullPathArray = (0, utils_1.pathToArray)(nullPath);
|
|
1124
|
-
exeContext.subsequentPayloads.forEach(asyncRecord => {
|
|
1125
|
-
var _a;
|
|
1126
|
-
if (asyncRecord === currentAsyncRecord) {
|
|
1127
|
-
// don't remove payload from where error originates
|
|
1128
|
-
return;
|
|
1129
|
-
}
|
|
1130
|
-
for (let i = 0; i < nullPathArray.length; i++) {
|
|
1131
|
-
if (asyncRecord.path[i] !== nullPathArray[i]) {
|
|
1132
|
-
// asyncRecord points to a path unaffected by this payload
|
|
1133
|
-
return;
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
// asyncRecord path points to nulled error field
|
|
1137
|
-
if (isStreamPayload(asyncRecord) && ((_a = asyncRecord.iterator) === null || _a === void 0 ? void 0 : _a.return)) {
|
|
1138
|
-
asyncRecord.iterator.return().catch(() => {
|
|
1139
|
-
// ignore error
|
|
1140
|
-
});
|
|
1141
|
-
}
|
|
1142
|
-
exeContext.subsequentPayloads.delete(asyncRecord);
|
|
1143
|
-
});
|
|
1144
|
-
}
|
|
1145
|
-
function getCompletedIncrementalResults(exeContext) {
|
|
1146
|
-
const incrementalResults = [];
|
|
1147
|
-
for (const asyncPayloadRecord of exeContext.subsequentPayloads) {
|
|
1148
|
-
const incrementalResult = {};
|
|
1149
|
-
if (!asyncPayloadRecord.isCompleted) {
|
|
1150
|
-
continue;
|
|
1151
|
-
}
|
|
1152
|
-
exeContext.subsequentPayloads.delete(asyncPayloadRecord);
|
|
1153
|
-
if (isStreamPayload(asyncPayloadRecord)) {
|
|
1154
|
-
const items = asyncPayloadRecord.items;
|
|
1155
|
-
if (asyncPayloadRecord.isCompletedIterator) {
|
|
1156
|
-
// async iterable resolver just finished but there may be pending payloads
|
|
1157
|
-
continue;
|
|
1158
|
-
}
|
|
1159
|
-
incrementalResult.items = items;
|
|
1160
|
-
}
|
|
1161
|
-
else {
|
|
1162
|
-
const data = asyncPayloadRecord.data;
|
|
1163
|
-
incrementalResult.data = data !== null && data !== void 0 ? data : null;
|
|
1164
|
-
}
|
|
1165
|
-
incrementalResult.path = asyncPayloadRecord.path;
|
|
1166
|
-
if (asyncPayloadRecord.label) {
|
|
1167
|
-
incrementalResult.label = asyncPayloadRecord.label;
|
|
1168
|
-
}
|
|
1169
|
-
if (asyncPayloadRecord.errors.length > 0) {
|
|
1170
|
-
incrementalResult.errors = asyncPayloadRecord.errors;
|
|
1171
|
-
}
|
|
1172
|
-
incrementalResults.push(incrementalResult);
|
|
1173
|
-
}
|
|
1174
|
-
return incrementalResults;
|
|
1175
|
-
}
|
|
1176
|
-
function yieldSubsequentPayloads(exeContext) {
|
|
1177
|
-
let isDone = false;
|
|
1178
|
-
async function next() {
|
|
1179
|
-
if (isDone) {
|
|
1180
|
-
return { value: undefined, done: true };
|
|
1181
|
-
}
|
|
1182
|
-
await Promise.race(Array.from(exeContext.subsequentPayloads).map(p => p.promise));
|
|
1183
|
-
if (isDone) {
|
|
1184
|
-
// a different call to next has exhausted all payloads
|
|
1185
|
-
return { value: undefined, done: true };
|
|
1186
|
-
}
|
|
1187
|
-
const incremental = getCompletedIncrementalResults(exeContext);
|
|
1188
|
-
const hasNext = exeContext.subsequentPayloads.size > 0;
|
|
1189
|
-
if (!incremental.length && hasNext) {
|
|
1190
|
-
return next();
|
|
1191
|
-
}
|
|
1192
|
-
if (!hasNext) {
|
|
1193
|
-
isDone = true;
|
|
1194
|
-
}
|
|
1195
|
-
return {
|
|
1196
|
-
value: incremental.length ? { incremental, hasNext } : { hasNext },
|
|
1197
|
-
done: false,
|
|
1198
|
-
};
|
|
1199
|
-
}
|
|
1200
|
-
function returnStreamIterators() {
|
|
1201
|
-
const promises = [];
|
|
1202
|
-
exeContext.subsequentPayloads.forEach(asyncPayloadRecord => {
|
|
1203
|
-
var _a;
|
|
1204
|
-
if (isStreamPayload(asyncPayloadRecord) && ((_a = asyncPayloadRecord.iterator) === null || _a === void 0 ? void 0 : _a.return)) {
|
|
1205
|
-
promises.push(asyncPayloadRecord.iterator.return());
|
|
1206
|
-
}
|
|
1207
|
-
});
|
|
1208
|
-
return Promise.all(promises);
|
|
1209
|
-
}
|
|
1210
|
-
return {
|
|
1211
|
-
[Symbol.asyncIterator]() {
|
|
1212
|
-
return this;
|
|
1213
|
-
},
|
|
1214
|
-
next,
|
|
1215
|
-
async return() {
|
|
1216
|
-
await returnStreamIterators();
|
|
1217
|
-
isDone = true;
|
|
1218
|
-
return { value: undefined, done: true };
|
|
1219
|
-
},
|
|
1220
|
-
async throw(error) {
|
|
1221
|
-
await returnStreamIterators();
|
|
1222
|
-
isDone = true;
|
|
1223
|
-
return Promise.reject(error);
|
|
1224
|
-
},
|
|
1225
|
-
};
|
|
1226
|
-
}
|
|
1227
|
-
class DeferredFragmentRecord {
|
|
1228
|
-
constructor(opts) {
|
|
1229
|
-
this.type = 'defer';
|
|
1230
|
-
this.label = opts.label;
|
|
1231
|
-
this.path = (0, utils_1.pathToArray)(opts.path);
|
|
1232
|
-
this.parentContext = opts.parentContext;
|
|
1233
|
-
this.errors = [];
|
|
1234
|
-
this._exeContext = opts.exeContext;
|
|
1235
|
-
this._exeContext.subsequentPayloads.add(this);
|
|
1236
|
-
this.isCompleted = false;
|
|
1237
|
-
this.data = null;
|
|
1238
|
-
this.promise = new Promise(resolve => {
|
|
1239
|
-
this._resolve = MaybePromise => {
|
|
1240
|
-
resolve(MaybePromise);
|
|
1241
|
-
};
|
|
1242
|
-
}).then(data => {
|
|
1243
|
-
this.data = data;
|
|
1244
|
-
this.isCompleted = true;
|
|
1245
|
-
});
|
|
1246
|
-
}
|
|
1247
|
-
addData(data) {
|
|
1248
|
-
var _a, _b, _c;
|
|
1249
|
-
const parentData = (_a = this.parentContext) === null || _a === void 0 ? void 0 : _a.promise;
|
|
1250
|
-
if (parentData) {
|
|
1251
|
-
(_b = this._resolve) === null || _b === void 0 ? void 0 : _b.call(this, parentData.then(() => data));
|
|
1252
|
-
return;
|
|
1253
|
-
}
|
|
1254
|
-
(_c = this._resolve) === null || _c === void 0 ? void 0 : _c.call(this, data);
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1257
|
-
class StreamRecord {
|
|
1258
|
-
constructor(opts) {
|
|
1259
|
-
this.type = 'stream';
|
|
1260
|
-
this.items = null;
|
|
1261
|
-
this.label = opts.label;
|
|
1262
|
-
this.path = (0, utils_1.pathToArray)(opts.path);
|
|
1263
|
-
this.parentContext = opts.parentContext;
|
|
1264
|
-
this.iterator = opts.iterator;
|
|
1265
|
-
this.errors = [];
|
|
1266
|
-
this._exeContext = opts.exeContext;
|
|
1267
|
-
this._exeContext.subsequentPayloads.add(this);
|
|
1268
|
-
this.isCompleted = false;
|
|
1269
|
-
this.items = null;
|
|
1270
|
-
this.promise = new Promise(resolve => {
|
|
1271
|
-
this._resolve = MaybePromise => {
|
|
1272
|
-
resolve(MaybePromise);
|
|
1273
|
-
};
|
|
1274
|
-
}).then(items => {
|
|
1275
|
-
this.items = items;
|
|
1276
|
-
this.isCompleted = true;
|
|
1277
|
-
});
|
|
1278
|
-
}
|
|
1279
|
-
addItems(items) {
|
|
1280
|
-
var _a, _b, _c;
|
|
1281
|
-
const parentData = (_a = this.parentContext) === null || _a === void 0 ? void 0 : _a.promise;
|
|
1282
|
-
if (parentData) {
|
|
1283
|
-
(_b = this._resolve) === null || _b === void 0 ? void 0 : _b.call(this, parentData.then(() => items));
|
|
1284
|
-
return;
|
|
1285
|
-
}
|
|
1286
|
-
(_c = this._resolve) === null || _c === void 0 ? void 0 : _c.call(this, items);
|
|
1287
|
-
}
|
|
1288
|
-
setIsCompletedIterator() {
|
|
1289
|
-
this.isCompletedIterator = true;
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
function isStreamPayload(asyncPayload) {
|
|
1293
|
-
return asyncPayload.type === 'stream';
|
|
1294
|
-
}
|
|
1295
750
|
/**
|
|
1296
751
|
* This method looks up the field on the given type definition.
|
|
1297
752
|
* It has special casing for the three introspection fields,
|