@graphql-tools/executor 2.0.0-alpha-20240620175016-1a4246713c9c2dcf5e3debfccfa47e0efd992528 → 2.0.0-alpha-20240702150434-510cb232d9e9dd0212d17ed8efc3e54d83ea25f4
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/collectFields.js +10 -10
- package/cjs/execution/execute.js +19 -42
- package/cjs/execution/flattenAsyncIterable.js +89 -0
- package/esm/execution/collectFields.js +10 -10
- package/esm/execution/execute.js +19 -42
- package/esm/execution/flattenAsyncIterable.js +85 -0
- package/package.json +2 -2
- package/typings/execution/collectFields.d.cts +3 -3
- package/typings/execution/collectFields.d.ts +3 -3
- package/typings/execution/execute.d.cts +5 -0
- package/typings/execution/execute.d.ts +5 -0
- package/typings/execution/flattenAsyncIterable.d.cts +7 -0
- package/typings/execution/flattenAsyncIterable.d.ts +7 -0
|
@@ -14,7 +14,7 @@ const invariant_js_1 = require("./invariant.js");
|
|
|
14
14
|
*
|
|
15
15
|
* @internal
|
|
16
16
|
*/
|
|
17
|
-
function collectFields(schema, fragments, variableValues, runtimeType,
|
|
17
|
+
function collectFields(schema, fragments, variableValues, runtimeType, selectionSet, errorWithIncrementalSubscription) {
|
|
18
18
|
const groupedFieldSet = new AccumulatorMap_js_1.AccumulatorMap();
|
|
19
19
|
const newDeferUsages = [];
|
|
20
20
|
const context = {
|
|
@@ -22,10 +22,10 @@ function collectFields(schema, fragments, variableValues, runtimeType, operation
|
|
|
22
22
|
fragments,
|
|
23
23
|
variableValues,
|
|
24
24
|
runtimeType,
|
|
25
|
-
|
|
25
|
+
errorWithIncrementalSubscription,
|
|
26
26
|
visitedFragmentNames: new Set(),
|
|
27
27
|
};
|
|
28
|
-
collectFieldsImpl(context,
|
|
28
|
+
collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsages);
|
|
29
29
|
return { groupedFieldSet, newDeferUsages };
|
|
30
30
|
}
|
|
31
31
|
exports.collectFields = collectFields;
|
|
@@ -39,13 +39,13 @@ exports.collectFields = collectFields;
|
|
|
39
39
|
*
|
|
40
40
|
* @internal
|
|
41
41
|
*/
|
|
42
|
-
function collectSubfields(schema, fragments, variableValues,
|
|
42
|
+
function collectSubfields(schema, fragments, variableValues, errorWithIncrementalSubscription, returnType, fieldGroup) {
|
|
43
43
|
const context = {
|
|
44
44
|
schema,
|
|
45
45
|
fragments,
|
|
46
46
|
variableValues,
|
|
47
47
|
runtimeType: returnType,
|
|
48
|
-
|
|
48
|
+
errorWithIncrementalSubscription,
|
|
49
49
|
visitedFragmentNames: new Set(),
|
|
50
50
|
};
|
|
51
51
|
const subGroupedFieldSet = new AccumulatorMap_js_1.AccumulatorMap();
|
|
@@ -63,7 +63,7 @@ function collectSubfields(schema, fragments, variableValues, operation, returnTy
|
|
|
63
63
|
}
|
|
64
64
|
exports.collectSubfields = collectSubfields;
|
|
65
65
|
function collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsages, deferUsage) {
|
|
66
|
-
const { schema, fragments, variableValues, runtimeType,
|
|
66
|
+
const { schema, fragments, variableValues, runtimeType, errorWithIncrementalSubscription, visitedFragmentNames, } = context;
|
|
67
67
|
for (const selection of selectionSet.selections) {
|
|
68
68
|
switch (selection.kind) {
|
|
69
69
|
case graphql_1.Kind.FIELD: {
|
|
@@ -81,7 +81,7 @@ function collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsage
|
|
|
81
81
|
!doesFragmentConditionMatch(schema, selection, runtimeType)) {
|
|
82
82
|
continue;
|
|
83
83
|
}
|
|
84
|
-
const newDeferUsage = getDeferUsage(
|
|
84
|
+
const newDeferUsage = getDeferUsage(errorWithIncrementalSubscription, variableValues, selection, deferUsage);
|
|
85
85
|
if (!newDeferUsage) {
|
|
86
86
|
collectFieldsImpl(context, selection.selectionSet, groupedFieldSet, newDeferUsages, deferUsage);
|
|
87
87
|
}
|
|
@@ -93,7 +93,7 @@ function collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsage
|
|
|
93
93
|
}
|
|
94
94
|
case graphql_1.Kind.FRAGMENT_SPREAD: {
|
|
95
95
|
const fragName = selection.name.value;
|
|
96
|
-
const newDeferUsage = getDeferUsage(
|
|
96
|
+
const newDeferUsage = getDeferUsage(errorWithIncrementalSubscription, variableValues, selection, deferUsage);
|
|
97
97
|
if (!newDeferUsage &&
|
|
98
98
|
(visitedFragmentNames.has(fragName) || !shouldIncludeNode(variableValues, selection))) {
|
|
99
99
|
continue;
|
|
@@ -120,7 +120,7 @@ function collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsage
|
|
|
120
120
|
* deferred based on the experimental flag, defer directive present and
|
|
121
121
|
* not disabled by the "if" argument.
|
|
122
122
|
*/
|
|
123
|
-
function getDeferUsage(
|
|
123
|
+
function getDeferUsage(errorWithIncrementalSubscription, variableValues, node, parentDeferUsage) {
|
|
124
124
|
const defer = (0, graphql_1.getDirectiveValues)(utils_1.GraphQLDeferDirective, node, variableValues);
|
|
125
125
|
if (!defer) {
|
|
126
126
|
return;
|
|
@@ -128,7 +128,7 @@ function getDeferUsage(operation, variableValues, node, parentDeferUsage) {
|
|
|
128
128
|
if (defer['if'] === false) {
|
|
129
129
|
return;
|
|
130
130
|
}
|
|
131
|
-
(0, invariant_js_1.invariant)(
|
|
131
|
+
(0, invariant_js_1.invariant)(!errorWithIncrementalSubscription, '`@defer` directive not supported on subscription operations. Disable `@defer` by setting the `if` argument to `false`.');
|
|
132
132
|
return {
|
|
133
133
|
label: typeof defer['label'] === 'string' ? defer['label'] : undefined,
|
|
134
134
|
parentDeferUsage,
|
package/cjs/execution/execute.js
CHANGED
|
@@ -7,6 +7,7 @@ const BoxedPromiseOrValue_js_1 = require("./BoxedPromiseOrValue.js");
|
|
|
7
7
|
const buildFieldPlan_js_1 = require("./buildFieldPlan.js");
|
|
8
8
|
const coerceError_js_1 = require("./coerceError.js");
|
|
9
9
|
const collectFields_js_1 = require("./collectFields.js");
|
|
10
|
+
const flattenAsyncIterable_js_1 = require("./flattenAsyncIterable.js");
|
|
10
11
|
const IncrementalPublisher_js_1 = require("./IncrementalPublisher.js");
|
|
11
12
|
const invariant_js_1 = require("./invariant.js");
|
|
12
13
|
const promiseForObject_js_1 = require("./promiseForObject.js");
|
|
@@ -17,7 +18,7 @@ const values_js_1 = require("./values.js");
|
|
|
17
18
|
* type. Memoizing ensures the subfields are not repeatedly calculated, which
|
|
18
19
|
* saves overhead when resolving lists of values.
|
|
19
20
|
*/
|
|
20
|
-
const collectSubfields = (0, utils_1.memoize3)((exeContext, returnType, fieldGroup) => (0, collectFields_js_1.collectSubfields)(exeContext.schema, exeContext.fragments, exeContext.variableValues, exeContext.
|
|
21
|
+
const collectSubfields = (0, utils_1.memoize3)((exeContext, returnType, fieldGroup) => (0, collectFields_js_1.collectSubfields)(exeContext.schema, exeContext.fragments, exeContext.variableValues, exeContext.errorWithIncrementalSubscription, returnType, fieldGroup));
|
|
21
22
|
/**
|
|
22
23
|
* Implements the "Executing requests" section of the GraphQL specification,
|
|
23
24
|
* including `@defer` and `@stream` as proposed in
|
|
@@ -149,7 +150,7 @@ exports.getFragmentsFromDocument = (0, utils_1.memoize1)(function getFragmentsFr
|
|
|
149
150
|
* @internal
|
|
150
151
|
*/
|
|
151
152
|
function buildExecutionContext(args) {
|
|
152
|
-
const { schema, document, rootValue, contextValue, variableValues: rawVariableValues, operationName, fieldResolver, typeResolver, subscribeFieldResolver, enableEarlyExecution, signal, } = args;
|
|
153
|
+
const { schema, document, rootValue, contextValue, variableValues: rawVariableValues, operationName, fieldResolver, typeResolver, subscribeFieldResolver, enableEarlyExecution, errorWithIncrementalSubscription, signal, } = args;
|
|
153
154
|
// If the schema used for execution is invalid, throw an error.
|
|
154
155
|
(0, graphql_1.assertValidSchema)(schema);
|
|
155
156
|
const fragments = (0, exports.getFragmentsFromDocument)(document);
|
|
@@ -199,6 +200,7 @@ function buildExecutionContext(args) {
|
|
|
199
200
|
typeResolver: typeResolver ?? exports.defaultTypeResolver,
|
|
200
201
|
subscribeFieldResolver: subscribeFieldResolver ?? exports.defaultFieldResolver,
|
|
201
202
|
enableEarlyExecution: enableEarlyExecution !== false,
|
|
203
|
+
errorWithIncrementalSubscription: operation.operation === 'subscription' && errorWithIncrementalSubscription !== false,
|
|
202
204
|
signal,
|
|
203
205
|
errors: undefined,
|
|
204
206
|
cancellableStreams: undefined,
|
|
@@ -221,14 +223,14 @@ function executeOperation(exeContext) {
|
|
|
221
223
|
throw exeContext.signal.reason;
|
|
222
224
|
}
|
|
223
225
|
try {
|
|
224
|
-
const { operation, schema, fragments, variableValues, rootValue } = exeContext;
|
|
226
|
+
const { operation, schema, fragments, variableValues, rootValue, errorWithIncrementalSubscription, } = exeContext;
|
|
225
227
|
const rootType = (0, utils_1.getDefinedRootType)(schema, operation.operation, [operation]);
|
|
226
228
|
if (rootType == null) {
|
|
227
229
|
(0, utils_1.createGraphQLError)(`Schema is not configured to execute ${operation.operation} operation.`, {
|
|
228
230
|
nodes: operation,
|
|
229
231
|
});
|
|
230
232
|
}
|
|
231
|
-
const collectedFields = (0, collectFields_js_1.collectFields)(schema, fragments, variableValues, rootType, operation);
|
|
233
|
+
const collectedFields = (0, collectFields_js_1.collectFields)(schema, fragments, variableValues, rootType, operation.selectionSet, errorWithIncrementalSubscription);
|
|
232
234
|
let groupedFieldSet = collectedFields.groupedFieldSet;
|
|
233
235
|
const newDeferUsages = collectedFields.newDeferUsages;
|
|
234
236
|
let data;
|
|
@@ -537,7 +539,7 @@ function getStreamUsage(exeContext, fieldGroup, path) {
|
|
|
537
539
|
}
|
|
538
540
|
(0, invariant_js_1.invariant)(typeof stream['initialCount'] === 'number', 'initialCount must be a number');
|
|
539
541
|
(0, invariant_js_1.invariant)(stream['initialCount'] >= 0, 'initialCount must be a positive integer');
|
|
540
|
-
(0, invariant_js_1.invariant)(exeContext.
|
|
542
|
+
(0, invariant_js_1.invariant)(!exeContext.errorWithIncrementalSubscription, '`@stream` directive not supported on subscription operations. Disable `@stream` by setting the `if` argument to `false`.');
|
|
541
543
|
const streamedFieldGroup = fieldGroup.map(fieldDetails => ({
|
|
542
544
|
node: fieldDetails.node,
|
|
543
545
|
deferUsage: undefined,
|
|
@@ -908,39 +910,6 @@ const defaultFieldResolver = function (source, args, contextValue, info) {
|
|
|
908
910
|
}
|
|
909
911
|
};
|
|
910
912
|
exports.defaultFieldResolver = defaultFieldResolver;
|
|
911
|
-
/**
|
|
912
|
-
* Implements the "Subscribe" algorithm described in the GraphQL specification,
|
|
913
|
-
* including `@defer` and `@stream` as proposed in
|
|
914
|
-
* https://github.com/graphql/graphql-spec/pull/742
|
|
915
|
-
*
|
|
916
|
-
* Returns a Promise which resolves to either an AsyncIterator (if successful)
|
|
917
|
-
* or an ExecutionResult (error). The promise will be rejected if the schema or
|
|
918
|
-
* other arguments to this function are invalid, or if the resolved event stream
|
|
919
|
-
* is not an async iterable.
|
|
920
|
-
*
|
|
921
|
-
* If the client-provided arguments to this function do not result in a
|
|
922
|
-
* compliant subscription, a GraphQL Response (ExecutionResult) with descriptive
|
|
923
|
-
* errors and no data will be returned.
|
|
924
|
-
*
|
|
925
|
-
* If the source stream could not be created due to faulty subscription resolver
|
|
926
|
-
* logic or underlying systems, the promise will resolve to a single
|
|
927
|
-
* ExecutionResult containing `errors` and no `data`.
|
|
928
|
-
*
|
|
929
|
-
* If the operation succeeded, the promise resolves to an AsyncIterator, which
|
|
930
|
-
* yields a stream of result representing the response stream.
|
|
931
|
-
*
|
|
932
|
-
* Each result may be an ExecutionResult with no `hasNext` (if executing the
|
|
933
|
-
* event did not use `@defer` or `@stream`), or an
|
|
934
|
-
* `InitialIncrementalExecutionResult` or `SubsequentIncrementalExecutionResult`
|
|
935
|
-
* (if executing the event used `@defer` or `@stream`). In the case of
|
|
936
|
-
* incremental execution results, each event produces a single
|
|
937
|
-
* `InitialIncrementalExecutionResult` followed by one or more
|
|
938
|
-
* `SubsequentIncrementalExecutionResult`s; all but the last have `hasNext: true`,
|
|
939
|
-
* and the last has `hasNext: false`. There is no interleaving between results
|
|
940
|
-
* generated from the same original event.
|
|
941
|
-
*
|
|
942
|
-
* Accepts an object with named arguments.
|
|
943
|
-
*/
|
|
944
913
|
function subscribe(args) {
|
|
945
914
|
// If a valid execution context cannot be created due to incorrect arguments,
|
|
946
915
|
// a "Response" with only errors is returned.
|
|
@@ -1004,6 +973,14 @@ function flattenIncrementalResults(incrementalResults) {
|
|
|
1004
973
|
};
|
|
1005
974
|
}
|
|
1006
975
|
exports.flattenIncrementalResults = flattenIncrementalResults;
|
|
976
|
+
async function* ensureAsyncIterable(someExecutionResult) {
|
|
977
|
+
if ('initialResult' in someExecutionResult) {
|
|
978
|
+
yield* flattenIncrementalResults(someExecutionResult);
|
|
979
|
+
}
|
|
980
|
+
else {
|
|
981
|
+
yield someExecutionResult;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
1007
984
|
function mapSourceToResponse(exeContext, resultOrStream) {
|
|
1008
985
|
if (!(0, utils_1.isAsyncIterable)(resultOrStream)) {
|
|
1009
986
|
return resultOrStream;
|
|
@@ -1014,13 +991,13 @@ function mapSourceToResponse(exeContext, resultOrStream) {
|
|
|
1014
991
|
// the GraphQL specification. The `execute` function provides the
|
|
1015
992
|
// "ExecuteSubscriptionEvent" algorithm, as it is nearly identical to the
|
|
1016
993
|
// "ExecuteQuery" algorithm, for which `execute` is also used.
|
|
1017
|
-
return (0, utils_1.mapAsyncIterator)(resultOrStream[Symbol.asyncIterator](), (payload) => executeOperation(buildPerEventExecutionContext(exeContext, payload)), (error) => {
|
|
994
|
+
return (0, flattenAsyncIterable_js_1.flattenAsyncIterable)((0, utils_1.mapAsyncIterator)(resultOrStream[Symbol.asyncIterator](), async (payload) => ensureAsyncIterable(await executeOperation(buildPerEventExecutionContext(exeContext, payload))), (error) => {
|
|
1018
995
|
const wrappedError = (0, utils_1.createGraphQLError)(error.message, {
|
|
1019
996
|
originalError: error,
|
|
1020
997
|
nodes: [exeContext.operation],
|
|
1021
998
|
});
|
|
1022
999
|
throw wrappedError;
|
|
1023
|
-
});
|
|
1000
|
+
}));
|
|
1024
1001
|
}
|
|
1025
1002
|
function createSourceEventStreamImpl(exeContext) {
|
|
1026
1003
|
try {
|
|
@@ -1035,14 +1012,14 @@ function createSourceEventStreamImpl(exeContext) {
|
|
|
1035
1012
|
}
|
|
1036
1013
|
}
|
|
1037
1014
|
function executeSubscription(exeContext) {
|
|
1038
|
-
const { schema, fragments, operation, variableValues, rootValue } = exeContext;
|
|
1015
|
+
const { schema, fragments, operation, variableValues, rootValue, errorWithIncrementalSubscription, } = exeContext;
|
|
1039
1016
|
const rootType = schema.getSubscriptionType();
|
|
1040
1017
|
if (rootType == null) {
|
|
1041
1018
|
throw (0, utils_1.createGraphQLError)('Schema is not configured to execute subscription operation.', {
|
|
1042
1019
|
nodes: operation,
|
|
1043
1020
|
});
|
|
1044
1021
|
}
|
|
1045
|
-
const { groupedFieldSet } = (0, collectFields_js_1.collectFields)(schema, fragments, variableValues, rootType, operation);
|
|
1022
|
+
const { groupedFieldSet } = (0, collectFields_js_1.collectFields)(schema, fragments, variableValues, rootType, operation.selectionSet, errorWithIncrementalSubscription);
|
|
1046
1023
|
const firstRootField = [...groupedFieldSet.entries()][0];
|
|
1047
1024
|
const [responseName, fieldGroup] = firstRootField;
|
|
1048
1025
|
const fieldName = fieldGroup[0].node.name.value;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.flattenAsyncIterable = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Given an AsyncIterable of AsyncIterables, flatten all yielded results into a
|
|
6
|
+
* single AsyncIterable.
|
|
7
|
+
*/
|
|
8
|
+
function flattenAsyncIterable(iterable) {
|
|
9
|
+
// You might think this whole function could be replaced with
|
|
10
|
+
//
|
|
11
|
+
// async function* flattenAsyncIterable(iterable) {
|
|
12
|
+
// for await (const subIterator of iterable) {
|
|
13
|
+
// yield* subIterator;
|
|
14
|
+
// }
|
|
15
|
+
// }
|
|
16
|
+
//
|
|
17
|
+
// but calling `.return()` on the iterator it returns won't interrupt the `for await`.
|
|
18
|
+
const topIterator = iterable[Symbol.asyncIterator]();
|
|
19
|
+
let currentNestedIterator;
|
|
20
|
+
let waitForCurrentNestedIterator;
|
|
21
|
+
let done = false;
|
|
22
|
+
async function next() {
|
|
23
|
+
if (done) {
|
|
24
|
+
return { value: undefined, done: true };
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
if (!currentNestedIterator) {
|
|
28
|
+
// Somebody else is getting it already.
|
|
29
|
+
if (waitForCurrentNestedIterator) {
|
|
30
|
+
await waitForCurrentNestedIterator;
|
|
31
|
+
return await next();
|
|
32
|
+
}
|
|
33
|
+
// Nobody else is getting it. We should!
|
|
34
|
+
let resolve;
|
|
35
|
+
waitForCurrentNestedIterator = new Promise(r => {
|
|
36
|
+
resolve = r;
|
|
37
|
+
});
|
|
38
|
+
const topIteratorResult = await topIterator.next();
|
|
39
|
+
if (topIteratorResult.done) {
|
|
40
|
+
// Given that done only ever transitions from false to true,
|
|
41
|
+
// require-atomic-updates is being unnecessarily cautious.
|
|
42
|
+
done = true;
|
|
43
|
+
return await next();
|
|
44
|
+
}
|
|
45
|
+
// eslint is making a reasonable point here, but we've explicitly protected
|
|
46
|
+
// ourself from the race condition by ensuring that only the single call
|
|
47
|
+
// that assigns to waitForCurrentNestedIterator is allowed to assign to
|
|
48
|
+
// currentNestedIterator or waitForCurrentNestedIterator.
|
|
49
|
+
currentNestedIterator = topIteratorResult.value[Symbol.asyncIterator]();
|
|
50
|
+
waitForCurrentNestedIterator = undefined;
|
|
51
|
+
resolve();
|
|
52
|
+
return await next();
|
|
53
|
+
}
|
|
54
|
+
const rememberCurrentNestedIterator = currentNestedIterator;
|
|
55
|
+
const nestedIteratorResult = await currentNestedIterator.next();
|
|
56
|
+
if (!nestedIteratorResult.done) {
|
|
57
|
+
return nestedIteratorResult;
|
|
58
|
+
}
|
|
59
|
+
// The nested iterator is done. If it's still the current one, make it not
|
|
60
|
+
// current. (If it's not the current one, somebody else has made us move on.)
|
|
61
|
+
if (currentNestedIterator === rememberCurrentNestedIterator) {
|
|
62
|
+
currentNestedIterator = undefined;
|
|
63
|
+
}
|
|
64
|
+
return await next();
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
done = true;
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
next,
|
|
73
|
+
async return() {
|
|
74
|
+
done = true;
|
|
75
|
+
await Promise.all([currentNestedIterator?.return?.(), topIterator.return?.()]);
|
|
76
|
+
return { value: undefined, done: true };
|
|
77
|
+
},
|
|
78
|
+
async throw(error) {
|
|
79
|
+
done = true;
|
|
80
|
+
await Promise.all([currentNestedIterator?.throw?.(error), topIterator.throw?.(error)]);
|
|
81
|
+
/* c8 ignore next */
|
|
82
|
+
throw error;
|
|
83
|
+
},
|
|
84
|
+
[Symbol.asyncIterator]() {
|
|
85
|
+
return this;
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
exports.flattenAsyncIterable = flattenAsyncIterable;
|
|
@@ -11,7 +11,7 @@ import { invariant } from './invariant.js';
|
|
|
11
11
|
*
|
|
12
12
|
* @internal
|
|
13
13
|
*/
|
|
14
|
-
export function collectFields(schema, fragments, variableValues, runtimeType,
|
|
14
|
+
export function collectFields(schema, fragments, variableValues, runtimeType, selectionSet, errorWithIncrementalSubscription) {
|
|
15
15
|
const groupedFieldSet = new AccumulatorMap();
|
|
16
16
|
const newDeferUsages = [];
|
|
17
17
|
const context = {
|
|
@@ -19,10 +19,10 @@ export function collectFields(schema, fragments, variableValues, runtimeType, op
|
|
|
19
19
|
fragments,
|
|
20
20
|
variableValues,
|
|
21
21
|
runtimeType,
|
|
22
|
-
|
|
22
|
+
errorWithIncrementalSubscription,
|
|
23
23
|
visitedFragmentNames: new Set(),
|
|
24
24
|
};
|
|
25
|
-
collectFieldsImpl(context,
|
|
25
|
+
collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsages);
|
|
26
26
|
return { groupedFieldSet, newDeferUsages };
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
@@ -35,13 +35,13 @@ export function collectFields(schema, fragments, variableValues, runtimeType, op
|
|
|
35
35
|
*
|
|
36
36
|
* @internal
|
|
37
37
|
*/
|
|
38
|
-
export function collectSubfields(schema, fragments, variableValues,
|
|
38
|
+
export function collectSubfields(schema, fragments, variableValues, errorWithIncrementalSubscription, returnType, fieldGroup) {
|
|
39
39
|
const context = {
|
|
40
40
|
schema,
|
|
41
41
|
fragments,
|
|
42
42
|
variableValues,
|
|
43
43
|
runtimeType: returnType,
|
|
44
|
-
|
|
44
|
+
errorWithIncrementalSubscription,
|
|
45
45
|
visitedFragmentNames: new Set(),
|
|
46
46
|
};
|
|
47
47
|
const subGroupedFieldSet = new AccumulatorMap();
|
|
@@ -58,7 +58,7 @@ export function collectSubfields(schema, fragments, variableValues, operation, r
|
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
function collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsages, deferUsage) {
|
|
61
|
-
const { schema, fragments, variableValues, runtimeType,
|
|
61
|
+
const { schema, fragments, variableValues, runtimeType, errorWithIncrementalSubscription, visitedFragmentNames, } = context;
|
|
62
62
|
for (const selection of selectionSet.selections) {
|
|
63
63
|
switch (selection.kind) {
|
|
64
64
|
case Kind.FIELD: {
|
|
@@ -76,7 +76,7 @@ function collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsage
|
|
|
76
76
|
!doesFragmentConditionMatch(schema, selection, runtimeType)) {
|
|
77
77
|
continue;
|
|
78
78
|
}
|
|
79
|
-
const newDeferUsage = getDeferUsage(
|
|
79
|
+
const newDeferUsage = getDeferUsage(errorWithIncrementalSubscription, variableValues, selection, deferUsage);
|
|
80
80
|
if (!newDeferUsage) {
|
|
81
81
|
collectFieldsImpl(context, selection.selectionSet, groupedFieldSet, newDeferUsages, deferUsage);
|
|
82
82
|
}
|
|
@@ -88,7 +88,7 @@ function collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsage
|
|
|
88
88
|
}
|
|
89
89
|
case Kind.FRAGMENT_SPREAD: {
|
|
90
90
|
const fragName = selection.name.value;
|
|
91
|
-
const newDeferUsage = getDeferUsage(
|
|
91
|
+
const newDeferUsage = getDeferUsage(errorWithIncrementalSubscription, variableValues, selection, deferUsage);
|
|
92
92
|
if (!newDeferUsage &&
|
|
93
93
|
(visitedFragmentNames.has(fragName) || !shouldIncludeNode(variableValues, selection))) {
|
|
94
94
|
continue;
|
|
@@ -115,7 +115,7 @@ function collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsage
|
|
|
115
115
|
* deferred based on the experimental flag, defer directive present and
|
|
116
116
|
* not disabled by the "if" argument.
|
|
117
117
|
*/
|
|
118
|
-
function getDeferUsage(
|
|
118
|
+
function getDeferUsage(errorWithIncrementalSubscription, variableValues, node, parentDeferUsage) {
|
|
119
119
|
const defer = getDirectiveValues(GraphQLDeferDirective, node, variableValues);
|
|
120
120
|
if (!defer) {
|
|
121
121
|
return;
|
|
@@ -123,7 +123,7 @@ function getDeferUsage(operation, variableValues, node, parentDeferUsage) {
|
|
|
123
123
|
if (defer['if'] === false) {
|
|
124
124
|
return;
|
|
125
125
|
}
|
|
126
|
-
invariant(
|
|
126
|
+
invariant(!errorWithIncrementalSubscription, '`@defer` directive not supported on subscription operations. Disable `@defer` by setting the `if` argument to `false`.');
|
|
127
127
|
return {
|
|
128
128
|
label: typeof defer['label'] === 'string' ? defer['label'] : undefined,
|
|
129
129
|
parentDeferUsage,
|
package/esm/execution/execute.js
CHANGED
|
@@ -4,6 +4,7 @@ import { BoxedPromiseOrValue } from './BoxedPromiseOrValue.js';
|
|
|
4
4
|
import { buildFieldPlan } from './buildFieldPlan.js';
|
|
5
5
|
import { coerceError } from './coerceError.js';
|
|
6
6
|
import { collectSubfields as _collectSubfields, collectFields, } from './collectFields.js';
|
|
7
|
+
import { flattenAsyncIterable } from './flattenAsyncIterable.js';
|
|
7
8
|
import { buildIncrementalResponse } from './IncrementalPublisher.js';
|
|
8
9
|
import { invariant } from './invariant.js';
|
|
9
10
|
import { promiseForObject } from './promiseForObject.js';
|
|
@@ -14,7 +15,7 @@ import { getVariableValues } from './values.js';
|
|
|
14
15
|
* type. Memoizing ensures the subfields are not repeatedly calculated, which
|
|
15
16
|
* saves overhead when resolving lists of values.
|
|
16
17
|
*/
|
|
17
|
-
const collectSubfields = memoize3((exeContext, returnType, fieldGroup) => _collectSubfields(exeContext.schema, exeContext.fragments, exeContext.variableValues, exeContext.
|
|
18
|
+
const collectSubfields = memoize3((exeContext, returnType, fieldGroup) => _collectSubfields(exeContext.schema, exeContext.fragments, exeContext.variableValues, exeContext.errorWithIncrementalSubscription, returnType, fieldGroup));
|
|
18
19
|
/**
|
|
19
20
|
* Implements the "Executing requests" section of the GraphQL specification,
|
|
20
21
|
* including `@defer` and `@stream` as proposed in
|
|
@@ -143,7 +144,7 @@ export const getFragmentsFromDocument = memoize1(function getFragmentsFromDocume
|
|
|
143
144
|
* @internal
|
|
144
145
|
*/
|
|
145
146
|
export function buildExecutionContext(args) {
|
|
146
|
-
const { schema, document, rootValue, contextValue, variableValues: rawVariableValues, operationName, fieldResolver, typeResolver, subscribeFieldResolver, enableEarlyExecution, signal, } = args;
|
|
147
|
+
const { schema, document, rootValue, contextValue, variableValues: rawVariableValues, operationName, fieldResolver, typeResolver, subscribeFieldResolver, enableEarlyExecution, errorWithIncrementalSubscription, signal, } = args;
|
|
147
148
|
// If the schema used for execution is invalid, throw an error.
|
|
148
149
|
assertValidSchema(schema);
|
|
149
150
|
const fragments = getFragmentsFromDocument(document);
|
|
@@ -193,6 +194,7 @@ export function buildExecutionContext(args) {
|
|
|
193
194
|
typeResolver: typeResolver ?? defaultTypeResolver,
|
|
194
195
|
subscribeFieldResolver: subscribeFieldResolver ?? defaultFieldResolver,
|
|
195
196
|
enableEarlyExecution: enableEarlyExecution !== false,
|
|
197
|
+
errorWithIncrementalSubscription: operation.operation === 'subscription' && errorWithIncrementalSubscription !== false,
|
|
196
198
|
signal,
|
|
197
199
|
errors: undefined,
|
|
198
200
|
cancellableStreams: undefined,
|
|
@@ -214,14 +216,14 @@ function executeOperation(exeContext) {
|
|
|
214
216
|
throw exeContext.signal.reason;
|
|
215
217
|
}
|
|
216
218
|
try {
|
|
217
|
-
const { operation, schema, fragments, variableValues, rootValue } = exeContext;
|
|
219
|
+
const { operation, schema, fragments, variableValues, rootValue, errorWithIncrementalSubscription, } = exeContext;
|
|
218
220
|
const rootType = getDefinedRootType(schema, operation.operation, [operation]);
|
|
219
221
|
if (rootType == null) {
|
|
220
222
|
createGraphQLError(`Schema is not configured to execute ${operation.operation} operation.`, {
|
|
221
223
|
nodes: operation,
|
|
222
224
|
});
|
|
223
225
|
}
|
|
224
|
-
const collectedFields = collectFields(schema, fragments, variableValues, rootType, operation);
|
|
226
|
+
const collectedFields = collectFields(schema, fragments, variableValues, rootType, operation.selectionSet, errorWithIncrementalSubscription);
|
|
225
227
|
let groupedFieldSet = collectedFields.groupedFieldSet;
|
|
226
228
|
const newDeferUsages = collectedFields.newDeferUsages;
|
|
227
229
|
let data;
|
|
@@ -529,7 +531,7 @@ function getStreamUsage(exeContext, fieldGroup, path) {
|
|
|
529
531
|
}
|
|
530
532
|
invariant(typeof stream['initialCount'] === 'number', 'initialCount must be a number');
|
|
531
533
|
invariant(stream['initialCount'] >= 0, 'initialCount must be a positive integer');
|
|
532
|
-
invariant(exeContext.
|
|
534
|
+
invariant(!exeContext.errorWithIncrementalSubscription, '`@stream` directive not supported on subscription operations. Disable `@stream` by setting the `if` argument to `false`.');
|
|
533
535
|
const streamedFieldGroup = fieldGroup.map(fieldDetails => ({
|
|
534
536
|
node: fieldDetails.node,
|
|
535
537
|
deferUsage: undefined,
|
|
@@ -898,39 +900,6 @@ export const defaultFieldResolver = function (source, args, contextValue, info)
|
|
|
898
900
|
return property;
|
|
899
901
|
}
|
|
900
902
|
};
|
|
901
|
-
/**
|
|
902
|
-
* Implements the "Subscribe" algorithm described in the GraphQL specification,
|
|
903
|
-
* including `@defer` and `@stream` as proposed in
|
|
904
|
-
* https://github.com/graphql/graphql-spec/pull/742
|
|
905
|
-
*
|
|
906
|
-
* Returns a Promise which resolves to either an AsyncIterator (if successful)
|
|
907
|
-
* or an ExecutionResult (error). The promise will be rejected if the schema or
|
|
908
|
-
* other arguments to this function are invalid, or if the resolved event stream
|
|
909
|
-
* is not an async iterable.
|
|
910
|
-
*
|
|
911
|
-
* If the client-provided arguments to this function do not result in a
|
|
912
|
-
* compliant subscription, a GraphQL Response (ExecutionResult) with descriptive
|
|
913
|
-
* errors and no data will be returned.
|
|
914
|
-
*
|
|
915
|
-
* If the source stream could not be created due to faulty subscription resolver
|
|
916
|
-
* logic or underlying systems, the promise will resolve to a single
|
|
917
|
-
* ExecutionResult containing `errors` and no `data`.
|
|
918
|
-
*
|
|
919
|
-
* If the operation succeeded, the promise resolves to an AsyncIterator, which
|
|
920
|
-
* yields a stream of result representing the response stream.
|
|
921
|
-
*
|
|
922
|
-
* Each result may be an ExecutionResult with no `hasNext` (if executing the
|
|
923
|
-
* event did not use `@defer` or `@stream`), or an
|
|
924
|
-
* `InitialIncrementalExecutionResult` or `SubsequentIncrementalExecutionResult`
|
|
925
|
-
* (if executing the event used `@defer` or `@stream`). In the case of
|
|
926
|
-
* incremental execution results, each event produces a single
|
|
927
|
-
* `InitialIncrementalExecutionResult` followed by one or more
|
|
928
|
-
* `SubsequentIncrementalExecutionResult`s; all but the last have `hasNext: true`,
|
|
929
|
-
* and the last has `hasNext: false`. There is no interleaving between results
|
|
930
|
-
* generated from the same original event.
|
|
931
|
-
*
|
|
932
|
-
* Accepts an object with named arguments.
|
|
933
|
-
*/
|
|
934
903
|
export function subscribe(args) {
|
|
935
904
|
// If a valid execution context cannot be created due to incorrect arguments,
|
|
936
905
|
// a "Response" with only errors is returned.
|
|
@@ -992,6 +961,14 @@ export function flattenIncrementalResults(incrementalResults) {
|
|
|
992
961
|
},
|
|
993
962
|
};
|
|
994
963
|
}
|
|
964
|
+
async function* ensureAsyncIterable(someExecutionResult) {
|
|
965
|
+
if ('initialResult' in someExecutionResult) {
|
|
966
|
+
yield* flattenIncrementalResults(someExecutionResult);
|
|
967
|
+
}
|
|
968
|
+
else {
|
|
969
|
+
yield someExecutionResult;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
995
972
|
function mapSourceToResponse(exeContext, resultOrStream) {
|
|
996
973
|
if (!isAsyncIterable(resultOrStream)) {
|
|
997
974
|
return resultOrStream;
|
|
@@ -1002,13 +979,13 @@ function mapSourceToResponse(exeContext, resultOrStream) {
|
|
|
1002
979
|
// the GraphQL specification. The `execute` function provides the
|
|
1003
980
|
// "ExecuteSubscriptionEvent" algorithm, as it is nearly identical to the
|
|
1004
981
|
// "ExecuteQuery" algorithm, for which `execute` is also used.
|
|
1005
|
-
return mapAsyncIterator(resultOrStream[Symbol.asyncIterator](), (payload) => executeOperation(buildPerEventExecutionContext(exeContext, payload)), (error) => {
|
|
982
|
+
return flattenAsyncIterable(mapAsyncIterator(resultOrStream[Symbol.asyncIterator](), async (payload) => ensureAsyncIterable(await executeOperation(buildPerEventExecutionContext(exeContext, payload))), (error) => {
|
|
1006
983
|
const wrappedError = createGraphQLError(error.message, {
|
|
1007
984
|
originalError: error,
|
|
1008
985
|
nodes: [exeContext.operation],
|
|
1009
986
|
});
|
|
1010
987
|
throw wrappedError;
|
|
1011
|
-
});
|
|
988
|
+
}));
|
|
1012
989
|
}
|
|
1013
990
|
function createSourceEventStreamImpl(exeContext) {
|
|
1014
991
|
try {
|
|
@@ -1023,14 +1000,14 @@ function createSourceEventStreamImpl(exeContext) {
|
|
|
1023
1000
|
}
|
|
1024
1001
|
}
|
|
1025
1002
|
function executeSubscription(exeContext) {
|
|
1026
|
-
const { schema, fragments, operation, variableValues, rootValue } = exeContext;
|
|
1003
|
+
const { schema, fragments, operation, variableValues, rootValue, errorWithIncrementalSubscription, } = exeContext;
|
|
1027
1004
|
const rootType = schema.getSubscriptionType();
|
|
1028
1005
|
if (rootType == null) {
|
|
1029
1006
|
throw createGraphQLError('Schema is not configured to execute subscription operation.', {
|
|
1030
1007
|
nodes: operation,
|
|
1031
1008
|
});
|
|
1032
1009
|
}
|
|
1033
|
-
const { groupedFieldSet } = collectFields(schema, fragments, variableValues, rootType, operation);
|
|
1010
|
+
const { groupedFieldSet } = collectFields(schema, fragments, variableValues, rootType, operation.selectionSet, errorWithIncrementalSubscription);
|
|
1034
1011
|
const firstRootField = [...groupedFieldSet.entries()][0];
|
|
1035
1012
|
const [responseName, fieldGroup] = firstRootField;
|
|
1036
1013
|
const fieldName = fieldGroup[0].node.name.value;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Given an AsyncIterable of AsyncIterables, flatten all yielded results into a
|
|
3
|
+
* single AsyncIterable.
|
|
4
|
+
*/
|
|
5
|
+
export function flattenAsyncIterable(iterable) {
|
|
6
|
+
// You might think this whole function could be replaced with
|
|
7
|
+
//
|
|
8
|
+
// async function* flattenAsyncIterable(iterable) {
|
|
9
|
+
// for await (const subIterator of iterable) {
|
|
10
|
+
// yield* subIterator;
|
|
11
|
+
// }
|
|
12
|
+
// }
|
|
13
|
+
//
|
|
14
|
+
// but calling `.return()` on the iterator it returns won't interrupt the `for await`.
|
|
15
|
+
const topIterator = iterable[Symbol.asyncIterator]();
|
|
16
|
+
let currentNestedIterator;
|
|
17
|
+
let waitForCurrentNestedIterator;
|
|
18
|
+
let done = false;
|
|
19
|
+
async function next() {
|
|
20
|
+
if (done) {
|
|
21
|
+
return { value: undefined, done: true };
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
if (!currentNestedIterator) {
|
|
25
|
+
// Somebody else is getting it already.
|
|
26
|
+
if (waitForCurrentNestedIterator) {
|
|
27
|
+
await waitForCurrentNestedIterator;
|
|
28
|
+
return await next();
|
|
29
|
+
}
|
|
30
|
+
// Nobody else is getting it. We should!
|
|
31
|
+
let resolve;
|
|
32
|
+
waitForCurrentNestedIterator = new Promise(r => {
|
|
33
|
+
resolve = r;
|
|
34
|
+
});
|
|
35
|
+
const topIteratorResult = await topIterator.next();
|
|
36
|
+
if (topIteratorResult.done) {
|
|
37
|
+
// Given that done only ever transitions from false to true,
|
|
38
|
+
// require-atomic-updates is being unnecessarily cautious.
|
|
39
|
+
done = true;
|
|
40
|
+
return await next();
|
|
41
|
+
}
|
|
42
|
+
// eslint is making a reasonable point here, but we've explicitly protected
|
|
43
|
+
// ourself from the race condition by ensuring that only the single call
|
|
44
|
+
// that assigns to waitForCurrentNestedIterator is allowed to assign to
|
|
45
|
+
// currentNestedIterator or waitForCurrentNestedIterator.
|
|
46
|
+
currentNestedIterator = topIteratorResult.value[Symbol.asyncIterator]();
|
|
47
|
+
waitForCurrentNestedIterator = undefined;
|
|
48
|
+
resolve();
|
|
49
|
+
return await next();
|
|
50
|
+
}
|
|
51
|
+
const rememberCurrentNestedIterator = currentNestedIterator;
|
|
52
|
+
const nestedIteratorResult = await currentNestedIterator.next();
|
|
53
|
+
if (!nestedIteratorResult.done) {
|
|
54
|
+
return nestedIteratorResult;
|
|
55
|
+
}
|
|
56
|
+
// The nested iterator is done. If it's still the current one, make it not
|
|
57
|
+
// current. (If it's not the current one, somebody else has made us move on.)
|
|
58
|
+
if (currentNestedIterator === rememberCurrentNestedIterator) {
|
|
59
|
+
currentNestedIterator = undefined;
|
|
60
|
+
}
|
|
61
|
+
return await next();
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
done = true;
|
|
65
|
+
throw err;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
next,
|
|
70
|
+
async return() {
|
|
71
|
+
done = true;
|
|
72
|
+
await Promise.all([currentNestedIterator?.return?.(), topIterator.return?.()]);
|
|
73
|
+
return { value: undefined, done: true };
|
|
74
|
+
},
|
|
75
|
+
async throw(error) {
|
|
76
|
+
done = true;
|
|
77
|
+
await Promise.all([currentNestedIterator?.throw?.(error), topIterator.throw?.(error)]);
|
|
78
|
+
/* c8 ignore next */
|
|
79
|
+
throw error;
|
|
80
|
+
},
|
|
81
|
+
[Symbol.asyncIterator]() {
|
|
82
|
+
return this;
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-tools/executor",
|
|
3
|
-
"version": "2.0.0-alpha-
|
|
3
|
+
"version": "2.0.0-alpha-20240702150434-510cb232d9e9dd0212d17ed8efc3e54d83ea25f4",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@graphql-tools/utils": "10.3.0-alpha-
|
|
9
|
+
"@graphql-tools/utils": "10.3.0-alpha-20240702150434-510cb232d9e9dd0212d17ed8efc3e54d83ea25f4",
|
|
10
10
|
"@graphql-typed-document-node/core": "3.2.0",
|
|
11
11
|
"@repeaterjs/repeater": "^3.0.4",
|
|
12
12
|
"tslib": "^2.4.0",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FieldNode, FragmentDefinitionNode, GraphQLObjectType, GraphQLSchema,
|
|
1
|
+
import type { FieldNode, FragmentDefinitionNode, GraphQLObjectType, GraphQLSchema, SelectionSetNode } from 'graphql';
|
|
2
2
|
export interface DeferUsage {
|
|
3
3
|
label: string | undefined;
|
|
4
4
|
parentDeferUsage: DeferUsage | undefined;
|
|
@@ -18,7 +18,7 @@ export type GroupedFieldSet = ReadonlyMap<string, FieldGroup>;
|
|
|
18
18
|
*
|
|
19
19
|
* @internal
|
|
20
20
|
*/
|
|
21
|
-
export declare function collectFields<TVariables = any>(schema: GraphQLSchema, fragments: Record<string, FragmentDefinitionNode>, variableValues: TVariables, runtimeType: GraphQLObjectType,
|
|
21
|
+
export declare function collectFields<TVariables = any>(schema: GraphQLSchema, fragments: Record<string, FragmentDefinitionNode>, variableValues: TVariables, runtimeType: GraphQLObjectType, selectionSet: SelectionSetNode, errorWithIncrementalSubscription: boolean): {
|
|
22
22
|
groupedFieldSet: GroupedFieldSet;
|
|
23
23
|
newDeferUsages: ReadonlyArray<DeferUsage>;
|
|
24
24
|
};
|
|
@@ -34,7 +34,7 @@ export declare function collectFields<TVariables = any>(schema: GraphQLSchema, f
|
|
|
34
34
|
*/
|
|
35
35
|
export declare function collectSubfields(schema: GraphQLSchema, fragments: Record<string, FragmentDefinitionNode>, variableValues: {
|
|
36
36
|
[variable: string]: unknown;
|
|
37
|
-
},
|
|
37
|
+
}, errorWithIncrementalSubscription: boolean, returnType: GraphQLObjectType, fieldGroup: FieldGroup): {
|
|
38
38
|
groupedFieldSet: GroupedFieldSet;
|
|
39
39
|
newDeferUsages: ReadonlyArray<DeferUsage>;
|
|
40
40
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FieldNode, FragmentDefinitionNode, GraphQLObjectType, GraphQLSchema,
|
|
1
|
+
import type { FieldNode, FragmentDefinitionNode, GraphQLObjectType, GraphQLSchema, SelectionSetNode } from 'graphql';
|
|
2
2
|
export interface DeferUsage {
|
|
3
3
|
label: string | undefined;
|
|
4
4
|
parentDeferUsage: DeferUsage | undefined;
|
|
@@ -18,7 +18,7 @@ export type GroupedFieldSet = ReadonlyMap<string, FieldGroup>;
|
|
|
18
18
|
*
|
|
19
19
|
* @internal
|
|
20
20
|
*/
|
|
21
|
-
export declare function collectFields<TVariables = any>(schema: GraphQLSchema, fragments: Record<string, FragmentDefinitionNode>, variableValues: TVariables, runtimeType: GraphQLObjectType,
|
|
21
|
+
export declare function collectFields<TVariables = any>(schema: GraphQLSchema, fragments: Record<string, FragmentDefinitionNode>, variableValues: TVariables, runtimeType: GraphQLObjectType, selectionSet: SelectionSetNode, errorWithIncrementalSubscription: boolean): {
|
|
22
22
|
groupedFieldSet: GroupedFieldSet;
|
|
23
23
|
newDeferUsages: ReadonlyArray<DeferUsage>;
|
|
24
24
|
};
|
|
@@ -34,7 +34,7 @@ export declare function collectFields<TVariables = any>(schema: GraphQLSchema, f
|
|
|
34
34
|
*/
|
|
35
35
|
export declare function collectSubfields(schema: GraphQLSchema, fragments: Record<string, FragmentDefinitionNode>, variableValues: {
|
|
36
36
|
[variable: string]: unknown;
|
|
37
|
-
},
|
|
37
|
+
}, errorWithIncrementalSubscription: boolean, returnType: GraphQLObjectType, fieldGroup: FieldGroup): {
|
|
38
38
|
groupedFieldSet: GroupedFieldSet;
|
|
39
39
|
newDeferUsages: ReadonlyArray<DeferUsage>;
|
|
40
40
|
};
|
|
@@ -38,6 +38,7 @@ export interface ExecutionContext<TVariables = any, TContext = any> {
|
|
|
38
38
|
typeResolver: GraphQLTypeResolver<any, TContext>;
|
|
39
39
|
subscribeFieldResolver: GraphQLFieldResolver<any, TContext>;
|
|
40
40
|
enableEarlyExecution: boolean;
|
|
41
|
+
errorWithIncrementalSubscription: boolean;
|
|
41
42
|
signal: AbortSignal | undefined;
|
|
42
43
|
errors: Map<Path | undefined, GraphQLError> | undefined;
|
|
43
44
|
cancellableStreams: Set<CancellableStreamRecord> | undefined;
|
|
@@ -54,6 +55,7 @@ export interface ExecutionArgs<TData = any, TVariables = any, TContext = any> {
|
|
|
54
55
|
typeResolver?: Maybe<GraphQLTypeResolver<any, TContext>>;
|
|
55
56
|
subscribeFieldResolver?: Maybe<GraphQLFieldResolver<any, TContext>>;
|
|
56
57
|
enableEarlyExecution?: Maybe<boolean>;
|
|
58
|
+
errorWithIncrementalSubscription?: Maybe<boolean>;
|
|
57
59
|
signal?: AbortSignal;
|
|
58
60
|
}
|
|
59
61
|
/**
|
|
@@ -149,6 +151,9 @@ export declare const defaultFieldResolver: GraphQLFieldResolver<unknown, unknown
|
|
|
149
151
|
*
|
|
150
152
|
* Accepts an object with named arguments.
|
|
151
153
|
*/
|
|
154
|
+
export declare function subscribe<TData = any, TVariables = any, TContext = any>(args: ExecutionArgs<TData, TVariables, TContext> & {
|
|
155
|
+
errorWithIncrementalSubscription: true | undefined | null;
|
|
156
|
+
}): MaybePromise<AsyncGenerator<SingularExecutionResult<TData>, void, void> | SingularExecutionResult<TData>>;
|
|
152
157
|
export declare function subscribe<TData = any, TVariables = any, TContext = any>(args: ExecutionArgs<TData, TVariables, TContext>): MaybePromise<AsyncGenerator<SingularExecutionResult<TData> | InitialIncrementalExecutionResult<TData> | SubsequentIncrementalExecutionResult<TData>, void, void> | SingularExecutionResult<TData>>;
|
|
153
158
|
export declare function flattenIncrementalResults<TData>(incrementalResults: IncrementalExecutionResults<TData>): AsyncGenerator<SubsequentIncrementalExecutionResult<TData, Record<string, unknown>>, void, void>;
|
|
154
159
|
/**
|
|
@@ -38,6 +38,7 @@ export interface ExecutionContext<TVariables = any, TContext = any> {
|
|
|
38
38
|
typeResolver: GraphQLTypeResolver<any, TContext>;
|
|
39
39
|
subscribeFieldResolver: GraphQLFieldResolver<any, TContext>;
|
|
40
40
|
enableEarlyExecution: boolean;
|
|
41
|
+
errorWithIncrementalSubscription: boolean;
|
|
41
42
|
signal: AbortSignal | undefined;
|
|
42
43
|
errors: Map<Path | undefined, GraphQLError> | undefined;
|
|
43
44
|
cancellableStreams: Set<CancellableStreamRecord> | undefined;
|
|
@@ -54,6 +55,7 @@ export interface ExecutionArgs<TData = any, TVariables = any, TContext = any> {
|
|
|
54
55
|
typeResolver?: Maybe<GraphQLTypeResolver<any, TContext>>;
|
|
55
56
|
subscribeFieldResolver?: Maybe<GraphQLFieldResolver<any, TContext>>;
|
|
56
57
|
enableEarlyExecution?: Maybe<boolean>;
|
|
58
|
+
errorWithIncrementalSubscription?: Maybe<boolean>;
|
|
57
59
|
signal?: AbortSignal;
|
|
58
60
|
}
|
|
59
61
|
/**
|
|
@@ -149,6 +151,9 @@ export declare const defaultFieldResolver: GraphQLFieldResolver<unknown, unknown
|
|
|
149
151
|
*
|
|
150
152
|
* Accepts an object with named arguments.
|
|
151
153
|
*/
|
|
154
|
+
export declare function subscribe<TData = any, TVariables = any, TContext = any>(args: ExecutionArgs<TData, TVariables, TContext> & {
|
|
155
|
+
errorWithIncrementalSubscription: true | undefined | null;
|
|
156
|
+
}): MaybePromise<AsyncGenerator<SingularExecutionResult<TData>, void, void> | SingularExecutionResult<TData>>;
|
|
152
157
|
export declare function subscribe<TData = any, TVariables = any, TContext = any>(args: ExecutionArgs<TData, TVariables, TContext>): MaybePromise<AsyncGenerator<SingularExecutionResult<TData> | InitialIncrementalExecutionResult<TData> | SubsequentIncrementalExecutionResult<TData>, void, void> | SingularExecutionResult<TData>>;
|
|
153
158
|
export declare function flattenIncrementalResults<TData>(incrementalResults: IncrementalExecutionResults<TData>): AsyncGenerator<SubsequentIncrementalExecutionResult<TData, Record<string, unknown>>, void, void>;
|
|
154
159
|
/**
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type AsyncIterableOrGenerator<T> = AsyncGenerator<T, void, void> | AsyncIterable<T>;
|
|
2
|
+
/**
|
|
3
|
+
* Given an AsyncIterable of AsyncIterables, flatten all yielded results into a
|
|
4
|
+
* single AsyncIterable.
|
|
5
|
+
*/
|
|
6
|
+
export declare function flattenAsyncIterable<T>(iterable: AsyncIterableOrGenerator<AsyncIterableOrGenerator<T>>): AsyncGenerator<T, void, void>;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type AsyncIterableOrGenerator<T> = AsyncGenerator<T, void, void> | AsyncIterable<T>;
|
|
2
|
+
/**
|
|
3
|
+
* Given an AsyncIterable of AsyncIterables, flatten all yielded results into a
|
|
4
|
+
* single AsyncIterable.
|
|
5
|
+
*/
|
|
6
|
+
export declare function flattenAsyncIterable<T>(iterable: AsyncIterableOrGenerator<AsyncIterableOrGenerator<T>>): AsyncGenerator<T, void, void>;
|
|
7
|
+
export {};
|