graphql-jit 0.8.4 → 0.8.5
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/README.md +4 -1
- package/dist/{ast.d.ts → cjs/ast.d.ts} +1 -1
- package/dist/cjs/ast.js.map +1 -0
- package/dist/{compat.js → cjs/compat.js} +5 -1
- package/dist/cjs/compat.js.map +1 -0
- package/dist/cjs/error.js.map +1 -0
- package/dist/{execution.js → cjs/execution.js} +1 -1
- package/dist/cjs/execution.js.map +1 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/inspect.js.map +1 -0
- package/dist/cjs/json.js.map +1 -0
- package/dist/{memoize.d.ts → cjs/memoize.d.ts} +1 -1
- package/dist/cjs/memoize.js.map +1 -0
- package/dist/{non-null.d.ts → cjs/non-null.d.ts} +1 -1
- package/dist/{non-null.js → cjs/non-null.js} +4 -0
- package/dist/cjs/non-null.js.map +1 -0
- package/dist/{resolve-info.d.ts → cjs/resolve-info.d.ts} +1 -1
- package/dist/cjs/resolve-info.js.map +1 -0
- package/dist/cjs/types.d.ts +1 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/{variables.d.ts → cjs/variables.d.ts} +1 -1
- package/dist/cjs/variables.js.map +1 -0
- package/dist/esm/ast.d.ts +89 -0
- package/dist/esm/ast.js +704 -0
- package/dist/esm/ast.js.map +1 -0
- package/dist/esm/compat.d.ts +43 -0
- package/dist/esm/compat.js +101 -0
- package/dist/esm/compat.js.map +1 -0
- package/dist/esm/error.d.ts +7 -0
- package/dist/esm/error.js +59 -0
- package/dist/esm/error.js.map +1 -0
- package/dist/esm/execution.d.ts +148 -0
- package/dist/esm/execution.js +1200 -0
- package/dist/esm/execution.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/inspect.d.ts +5 -0
- package/dist/esm/inspect.js +110 -0
- package/dist/esm/inspect.js.map +1 -0
- package/dist/esm/json.d.ts +9 -0
- package/dist/esm/json.js +145 -0
- package/dist/esm/json.js.map +1 -0
- package/dist/esm/memoize.d.ts +5 -0
- package/dist/esm/memoize.js +29 -0
- package/dist/esm/memoize.js.map +1 -0
- package/dist/esm/non-null.d.ts +9 -0
- package/dist/esm/non-null.js +207 -0
- package/dist/esm/non-null.js.map +1 -0
- package/dist/esm/resolve-info.d.ts +40 -0
- package/dist/esm/resolve-info.js +233 -0
- package/dist/esm/resolve-info.js.map +1 -0
- package/dist/esm/types.d.ts +1 -0
- package/dist/esm/types.js +3 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/variables.d.ts +15 -0
- package/dist/esm/variables.js +348 -0
- package/dist/esm/variables.js.map +1 -0
- package/package.json +47 -37
- package/dist/ast.js.map +0 -1
- package/dist/compat.js.map +0 -1
- package/dist/error.js.map +0 -1
- package/dist/execution.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/inspect.js.map +0 -1
- package/dist/json.js.map +0 -1
- package/dist/memoize.js.map +0 -1
- package/dist/non-null.js.map +0 -1
- package/dist/resolve-info.js.map +0 -1
- package/dist/types.d.ts +0 -1
- package/dist/types.js.map +0 -1
- package/dist/variables.js.map +0 -1
- /package/dist/{ast.js → cjs/ast.js} +0 -0
- /package/dist/{compat.d.ts → cjs/compat.d.ts} +0 -0
- /package/dist/{error.d.ts → cjs/error.d.ts} +0 -0
- /package/dist/{error.js → cjs/error.js} +0 -0
- /package/dist/{execution.d.ts → cjs/execution.d.ts} +0 -0
- /package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
- /package/dist/{index.js → cjs/index.js} +0 -0
- /package/dist/{inspect.d.ts → cjs/inspect.d.ts} +0 -0
- /package/dist/{inspect.js → cjs/inspect.js} +0 -0
- /package/dist/{json.d.ts → cjs/json.d.ts} +0 -0
- /package/dist/{json.js → cjs/json.js} +0 -0
- /package/dist/{memoize.js → cjs/memoize.js} +0 -0
- /package/dist/{resolve-info.js → cjs/resolve-info.js} +0 -0
- /package/dist/{types.js → cjs/types.js} +0 -0
- /package/dist/{variables.js → cjs/variables.js} +0 -0
|
@@ -0,0 +1,1200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isAsyncIterable = exports.isPromiseInliner = exports.isPromise = exports.createBoundQuery = exports.isCompiledQuery = exports.compileQuery = exports.GLOBAL_VARIABLES_NAME = void 0;
|
|
7
|
+
const fast_json_stringify_1 = __importDefault(require("fast-json-stringify"));
|
|
8
|
+
const generate_function_1 = __importDefault(require("generate-function"));
|
|
9
|
+
const graphql_1 = require("graphql");
|
|
10
|
+
const Path_1 = require("graphql/jsutils/Path");
|
|
11
|
+
const ast_1 = require("./ast");
|
|
12
|
+
const error_1 = require("./error");
|
|
13
|
+
const inspect_1 = __importDefault(require("./inspect"));
|
|
14
|
+
const json_1 = require("./json");
|
|
15
|
+
const non_null_1 = require("./non-null");
|
|
16
|
+
const resolve_info_1 = require("./resolve-info");
|
|
17
|
+
const variables_1 = require("./variables");
|
|
18
|
+
const compat_1 = require("./compat");
|
|
19
|
+
const inspect = (0, inspect_1.default)();
|
|
20
|
+
// prefix for the variable used ot cache validation results
|
|
21
|
+
const SAFETY_CHECK_PREFIX = "__validNode";
|
|
22
|
+
const GLOBAL_DATA_NAME = "__context.data";
|
|
23
|
+
const GLOBAL_ERRORS_NAME = "__context.errors";
|
|
24
|
+
const GLOBAL_NULL_ERRORS_NAME = "__context.nullErrors";
|
|
25
|
+
const GLOBAL_ROOT_NAME = "__context.rootValue";
|
|
26
|
+
exports.GLOBAL_VARIABLES_NAME = "__context.variables";
|
|
27
|
+
const GLOBAL_CONTEXT_NAME = "__context.context";
|
|
28
|
+
const GLOBAL_EXECUTION_CONTEXT = "__context";
|
|
29
|
+
const GLOBAL_PROMISE_COUNTER = "__context.promiseCounter";
|
|
30
|
+
const GLOBAL_INSPECT_NAME = "__context.inspect";
|
|
31
|
+
const GLOBAL_SAFE_MAP_NAME = "__context.safeMap";
|
|
32
|
+
const GRAPHQL_ERROR = "__context.GraphQLError";
|
|
33
|
+
const GLOBAL_RESOLVE = "__context.resolve";
|
|
34
|
+
const GLOBAL_PARENT_NAME = "__parent";
|
|
35
|
+
const LOCAL_JS_FIELD_NAME_PREFIX = "__field";
|
|
36
|
+
/**
|
|
37
|
+
* It compiles a GraphQL query to an executable function
|
|
38
|
+
* @param {GraphQLSchema} schema GraphQL schema
|
|
39
|
+
* @param {DocumentNode} document Query being submitted
|
|
40
|
+
* @param {string} operationName name of the operation
|
|
41
|
+
* @param partialOptions compilation options to tune the compiler features
|
|
42
|
+
* @returns {CompiledQuery} the cacheable result
|
|
43
|
+
*/
|
|
44
|
+
function compileQuery(schema, document, operationName, partialOptions) {
|
|
45
|
+
if (!schema) {
|
|
46
|
+
throw new Error(`Expected ${schema} to be a GraphQL schema.`);
|
|
47
|
+
}
|
|
48
|
+
if (!document) {
|
|
49
|
+
throw new Error("Must provide document.");
|
|
50
|
+
}
|
|
51
|
+
if (partialOptions &&
|
|
52
|
+
partialOptions.resolverInfoEnricher &&
|
|
53
|
+
typeof partialOptions.resolverInfoEnricher !== "function") {
|
|
54
|
+
throw new Error("resolverInfoEnricher must be a function");
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const options = {
|
|
58
|
+
disablingCapturingStackErrors: false,
|
|
59
|
+
customJSONSerializer: false,
|
|
60
|
+
disableLeafSerialization: false,
|
|
61
|
+
customSerializers: {},
|
|
62
|
+
useExperimentalPathBasedSkipInclude: false,
|
|
63
|
+
...partialOptions
|
|
64
|
+
};
|
|
65
|
+
// If a valid context cannot be created due to incorrect arguments,
|
|
66
|
+
// a "Response" with only errors is returned.
|
|
67
|
+
const context = buildCompilationContext(schema, document, options, operationName);
|
|
68
|
+
let stringify;
|
|
69
|
+
if (options.customJSONSerializer) {
|
|
70
|
+
const jsonSchema = (0, json_1.queryToJSONSchema)(context);
|
|
71
|
+
stringify = (0, fast_json_stringify_1.default)(jsonSchema);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
stringify = JSON.stringify;
|
|
75
|
+
}
|
|
76
|
+
const getVariables = (0, variables_1.compileVariableParsing)(schema, context.operation.variableDefinitions || []);
|
|
77
|
+
const type = (0, compat_1.getOperationRootType)(context.schema, context.operation);
|
|
78
|
+
const fieldMap = (0, ast_1.collectFields)(context, type, context.operation.selectionSet, Object.create(null), Object.create(null));
|
|
79
|
+
const functionBody = compileOperation(context, type, fieldMap);
|
|
80
|
+
const compiledQuery = {
|
|
81
|
+
query: createBoundQuery(context, document,
|
|
82
|
+
// eslint-disable-next-line no-new-func
|
|
83
|
+
new Function("return " + functionBody)(), getVariables, context.operation.name != null
|
|
84
|
+
? context.operation.name.value
|
|
85
|
+
: undefined),
|
|
86
|
+
stringify
|
|
87
|
+
};
|
|
88
|
+
if (context.operation.operation === "subscription") {
|
|
89
|
+
compiledQuery.subscribe = createBoundSubscribe(context, document, compileSubscriptionOperation(context, type, fieldMap, compiledQuery.query), getVariables, context.operation.name != null
|
|
90
|
+
? context.operation.name.value
|
|
91
|
+
: undefined);
|
|
92
|
+
}
|
|
93
|
+
if (options.debug) {
|
|
94
|
+
// result of the compilation useful for debugging issues
|
|
95
|
+
// and visualization tools like try-jit.
|
|
96
|
+
compiledQuery.__DO_NOT_USE_THIS_OR_YOU_WILL_BE_FIRED_compilation =
|
|
97
|
+
functionBody;
|
|
98
|
+
}
|
|
99
|
+
return compiledQuery;
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
return {
|
|
103
|
+
errors: normalizeErrors(err)
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.compileQuery = compileQuery;
|
|
108
|
+
function isCompiledQuery(query) {
|
|
109
|
+
return "query" in query && typeof query.query === "function";
|
|
110
|
+
}
|
|
111
|
+
exports.isCompiledQuery = isCompiledQuery;
|
|
112
|
+
// Exported only for an error test
|
|
113
|
+
function createBoundQuery(compilationContext, document, func, getVariableValues, operationName) {
|
|
114
|
+
const { resolvers, typeResolvers, isTypeOfs, serializers, resolveInfos } = compilationContext;
|
|
115
|
+
const trimmer = (0, non_null_1.createNullTrimmer)(compilationContext);
|
|
116
|
+
const fnName = operationName || "query";
|
|
117
|
+
/* eslint-disable */
|
|
118
|
+
/**
|
|
119
|
+
* In-order to assign a debuggable name to the bound query function,
|
|
120
|
+
* we create an intermediate object with a method named as the
|
|
121
|
+
* intended function name. This is because Function.prototype.name
|
|
122
|
+
* is not writeable.
|
|
123
|
+
*
|
|
124
|
+
* http://www.ecma-international.org/ecma-262/6.0/#sec-method-definitions-runtime-semantics-propertydefinitionevaluation
|
|
125
|
+
*
|
|
126
|
+
* section: 14.3.9.3 - calls SetFunctionName
|
|
127
|
+
*/
|
|
128
|
+
/* eslint-enable */
|
|
129
|
+
const ret = {
|
|
130
|
+
[fnName](rootValue, context, variables) {
|
|
131
|
+
// this can be shared across in a batch request
|
|
132
|
+
const parsedVariables = getVariableValues(variables || {});
|
|
133
|
+
// Return early errors if variable coercing failed.
|
|
134
|
+
if ((0, variables_1.failToParseVariables)(parsedVariables)) {
|
|
135
|
+
return { errors: parsedVariables.errors };
|
|
136
|
+
}
|
|
137
|
+
const executionContext = {
|
|
138
|
+
rootValue,
|
|
139
|
+
context,
|
|
140
|
+
variables: parsedVariables.coerced,
|
|
141
|
+
safeMap,
|
|
142
|
+
inspect,
|
|
143
|
+
GraphQLError: error_1.GraphQLError,
|
|
144
|
+
resolvers,
|
|
145
|
+
typeResolvers,
|
|
146
|
+
isTypeOfs,
|
|
147
|
+
serializers,
|
|
148
|
+
resolveInfos,
|
|
149
|
+
trimmer,
|
|
150
|
+
promiseCounter: 0,
|
|
151
|
+
data: {},
|
|
152
|
+
nullErrors: [],
|
|
153
|
+
errors: []
|
|
154
|
+
};
|
|
155
|
+
// eslint-disable-next-line no-useless-call
|
|
156
|
+
const result = func.call(null, executionContext);
|
|
157
|
+
if (isPromise(result)) {
|
|
158
|
+
return result.then(postProcessResult);
|
|
159
|
+
}
|
|
160
|
+
return postProcessResult(executionContext);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
return ret[fnName];
|
|
164
|
+
}
|
|
165
|
+
exports.createBoundQuery = createBoundQuery;
|
|
166
|
+
function postProcessResult({ data, nullErrors, errors, trimmer }) {
|
|
167
|
+
if (nullErrors.length > 0) {
|
|
168
|
+
const trimmed = trimmer(data, nullErrors);
|
|
169
|
+
return {
|
|
170
|
+
data: trimmed.data,
|
|
171
|
+
errors: errors.concat(trimmed.errors)
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
else if (errors.length > 0) {
|
|
175
|
+
return {
|
|
176
|
+
data,
|
|
177
|
+
errors
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return { data };
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Create the main function body.
|
|
184
|
+
*
|
|
185
|
+
* Implements the "Evaluating operations" section of the spec.
|
|
186
|
+
*
|
|
187
|
+
* It defers all top level field for consistency and protection for null root values,
|
|
188
|
+
* all the fields are deferred regardless of presence of resolver or not.
|
|
189
|
+
*
|
|
190
|
+
* @param {CompilationContext} context compilation context with the execution context
|
|
191
|
+
* @returns {string} a function body to be instantiated together with the header, footer
|
|
192
|
+
*/
|
|
193
|
+
function compileOperation(context, type, fieldMap) {
|
|
194
|
+
const serialExecution = context.operation.operation === "mutation";
|
|
195
|
+
const topLevel = compileObjectType(context, type, [], [GLOBAL_ROOT_NAME], [GLOBAL_DATA_NAME], undefined, GLOBAL_ERRORS_NAME, fieldMap, true);
|
|
196
|
+
let body = `function query (${GLOBAL_EXECUTION_CONTEXT}) {
|
|
197
|
+
"use strict";
|
|
198
|
+
`;
|
|
199
|
+
if (serialExecution) {
|
|
200
|
+
body += `${GLOBAL_EXECUTION_CONTEXT}.queue = [];`;
|
|
201
|
+
}
|
|
202
|
+
body += generateUniqueDeclarations(context, true);
|
|
203
|
+
body += `${GLOBAL_DATA_NAME} = ${topLevel}\n`;
|
|
204
|
+
if (serialExecution) {
|
|
205
|
+
body += compileDeferredFieldsSerially(context);
|
|
206
|
+
body += `
|
|
207
|
+
${GLOBAL_EXECUTION_CONTEXT}.finalResolve = () => {};
|
|
208
|
+
${GLOBAL_RESOLVE} = (context) => {
|
|
209
|
+
if (context.jobCounter >= context.queue.length) {
|
|
210
|
+
// All mutations have finished
|
|
211
|
+
context.finalResolve(context);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
context.queue[context.jobCounter++](context);
|
|
215
|
+
};
|
|
216
|
+
// There might not be a job to run due to invalid queries
|
|
217
|
+
if (${GLOBAL_EXECUTION_CONTEXT}.queue.length > 0) {
|
|
218
|
+
${GLOBAL_EXECUTION_CONTEXT}.jobCounter = 1; // since the first one will be run manually
|
|
219
|
+
${GLOBAL_EXECUTION_CONTEXT}.queue[0](${GLOBAL_EXECUTION_CONTEXT});
|
|
220
|
+
}
|
|
221
|
+
// Promises have been scheduled so a new promise is returned
|
|
222
|
+
// that will be resolved once every promise is done
|
|
223
|
+
if (${GLOBAL_PROMISE_COUNTER} > 0) {
|
|
224
|
+
return new Promise(resolve => ${GLOBAL_EXECUTION_CONTEXT}.finalResolve = resolve);
|
|
225
|
+
}
|
|
226
|
+
`;
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
body += compileDeferredFields(context);
|
|
230
|
+
body += `
|
|
231
|
+
// Promises have been scheduled so a new promise is returned
|
|
232
|
+
// that will be resolved once every promise is done
|
|
233
|
+
if (${GLOBAL_PROMISE_COUNTER} > 0) {
|
|
234
|
+
return new Promise(resolve => ${GLOBAL_RESOLVE} = resolve);
|
|
235
|
+
}`;
|
|
236
|
+
}
|
|
237
|
+
body += `
|
|
238
|
+
// sync execution, the results are ready
|
|
239
|
+
return undefined;
|
|
240
|
+
}`;
|
|
241
|
+
body += context.hoistedFunctions.join("\n");
|
|
242
|
+
return body;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Processes the deferred node list in the compilation context.
|
|
246
|
+
*
|
|
247
|
+
* Each deferred node get a copy of the compilation context with
|
|
248
|
+
* a new empty list for deferred nodes to properly scope the nodes.
|
|
249
|
+
* @param {CompilationContext} context compilation context
|
|
250
|
+
* @returns {string} compiled transformations all of deferred nodes
|
|
251
|
+
*/
|
|
252
|
+
function compileDeferredFields(context) {
|
|
253
|
+
let body = "";
|
|
254
|
+
context.deferred.forEach((deferredField, index) => {
|
|
255
|
+
body += `
|
|
256
|
+
if (${SAFETY_CHECK_PREFIX}${index}) {
|
|
257
|
+
${compileDeferredField(context, deferredField)}
|
|
258
|
+
}`;
|
|
259
|
+
});
|
|
260
|
+
return body;
|
|
261
|
+
}
|
|
262
|
+
function compileDeferredField(context, deferredField, appendix) {
|
|
263
|
+
const { name, originPaths, destinationPaths, fieldNodes, fieldType, fieldName, jsFieldName, responsePath, parentType, args } = deferredField;
|
|
264
|
+
const subContext = createSubCompilationContext(context);
|
|
265
|
+
const nodeBody = compileType(subContext, parentType, fieldType, fieldNodes, [jsFieldName], [`${GLOBAL_PARENT_NAME}.${name}`], responsePath);
|
|
266
|
+
const parentIndexes = getParentArgIndexes(context);
|
|
267
|
+
const resolverName = getResolverName(parentType.name, fieldName);
|
|
268
|
+
const resolverHandler = getHoistedFunctionName(context, `${name}${resolverName}Handler`);
|
|
269
|
+
const topLevelArgs = getArgumentsName(resolverName);
|
|
270
|
+
const validArgs = getValidArgumentsVarName(resolverName);
|
|
271
|
+
const executionError = createErrorObject(context, fieldNodes, responsePath, "err.message != null ? err.message : err", "err");
|
|
272
|
+
const executionInfo = getExecutionInfo(subContext, parentType, fieldType, fieldName, fieldNodes, responsePath);
|
|
273
|
+
const emptyError = createErrorObject(context, fieldNodes, responsePath, '""');
|
|
274
|
+
const resolverParentPath = originPaths.join(".");
|
|
275
|
+
const resolverCall = `${GLOBAL_EXECUTION_CONTEXT}.resolvers.${resolverName}(
|
|
276
|
+
${resolverParentPath},${topLevelArgs},${GLOBAL_CONTEXT_NAME}, ${executionInfo})`;
|
|
277
|
+
const resultParentPath = destinationPaths.join(".");
|
|
278
|
+
const compiledArgs = compileArguments(subContext, args, topLevelArgs, validArgs, fieldType, responsePath);
|
|
279
|
+
const body = `
|
|
280
|
+
${compiledArgs}
|
|
281
|
+
if (${validArgs} === true) {
|
|
282
|
+
var __value = null;
|
|
283
|
+
try {
|
|
284
|
+
__value = ${resolverCall};
|
|
285
|
+
} catch (err) {
|
|
286
|
+
${getErrorDestination(fieldType)}.push(${executionError});
|
|
287
|
+
}
|
|
288
|
+
if (${isPromiseInliner("__value")}) {
|
|
289
|
+
${promiseStarted()}
|
|
290
|
+
__value.then(result => {
|
|
291
|
+
${resolverHandler}(${GLOBAL_EXECUTION_CONTEXT}, ${resultParentPath}, result, ${parentIndexes});
|
|
292
|
+
${promiseDone()}
|
|
293
|
+
}, err => {
|
|
294
|
+
if (err) {
|
|
295
|
+
${getErrorDestination(fieldType)}.push(${executionError});
|
|
296
|
+
} else {
|
|
297
|
+
${getErrorDestination(fieldType)}.push(${emptyError});
|
|
298
|
+
}
|
|
299
|
+
${promiseDone()}
|
|
300
|
+
});
|
|
301
|
+
} else {
|
|
302
|
+
${resolverHandler}(${GLOBAL_EXECUTION_CONTEXT}, ${resultParentPath}, __value, ${parentIndexes});
|
|
303
|
+
}
|
|
304
|
+
}`;
|
|
305
|
+
context.hoistedFunctions.push(`
|
|
306
|
+
function ${resolverHandler}(${GLOBAL_EXECUTION_CONTEXT}, ${GLOBAL_PARENT_NAME}, ${jsFieldName}, ${parentIndexes}) {
|
|
307
|
+
${generateUniqueDeclarations(subContext)}
|
|
308
|
+
${GLOBAL_PARENT_NAME}.${name} = ${nodeBody};
|
|
309
|
+
${compileDeferredFields(subContext)}
|
|
310
|
+
${appendix || ""}
|
|
311
|
+
}
|
|
312
|
+
`);
|
|
313
|
+
return body;
|
|
314
|
+
}
|
|
315
|
+
function compileDeferredFieldsSerially(context) {
|
|
316
|
+
let body = "";
|
|
317
|
+
context.deferred.forEach((deferredField, index) => {
|
|
318
|
+
const { name, fieldName, parentType } = deferredField;
|
|
319
|
+
const resolverName = getResolverName(parentType.name, fieldName);
|
|
320
|
+
const mutationHandler = getHoistedFunctionName(context, `${name}${resolverName}Mutation`);
|
|
321
|
+
body += `
|
|
322
|
+
if (${SAFETY_CHECK_PREFIX}${index}) {
|
|
323
|
+
${GLOBAL_EXECUTION_CONTEXT}.queue.push(${mutationHandler});
|
|
324
|
+
}
|
|
325
|
+
`;
|
|
326
|
+
const appendix = `
|
|
327
|
+
if (${GLOBAL_PROMISE_COUNTER} === 0) {
|
|
328
|
+
${GLOBAL_RESOLVE}(${GLOBAL_EXECUTION_CONTEXT});
|
|
329
|
+
}
|
|
330
|
+
`;
|
|
331
|
+
context.hoistedFunctions.push(`
|
|
332
|
+
function ${mutationHandler}(${GLOBAL_EXECUTION_CONTEXT}) {
|
|
333
|
+
${compileDeferredField(context, deferredField, appendix)}
|
|
334
|
+
}
|
|
335
|
+
`);
|
|
336
|
+
});
|
|
337
|
+
return body;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Processes a generic node.
|
|
341
|
+
*
|
|
342
|
+
* The type is analysed and later reprocessed in dedicated functions.
|
|
343
|
+
* @param {CompilationContext} context compilation context to hold deferred nodes
|
|
344
|
+
* @param parentType
|
|
345
|
+
* @param {GraphQLType} type type of current parent node
|
|
346
|
+
* @param {FieldNode[]} fieldNodes array of the field nodes
|
|
347
|
+
* @param originPaths originPaths path in the parent object from where to fetch results
|
|
348
|
+
* @param destinationPaths path in the where to write the result
|
|
349
|
+
* @param previousPath response path until this node
|
|
350
|
+
* @returns {string} body of the resolvable fieldNodes
|
|
351
|
+
*/
|
|
352
|
+
function compileType(context, parentType, type, fieldNodes, originPaths, destinationPaths, previousPath) {
|
|
353
|
+
const sourcePath = originPaths.join(".");
|
|
354
|
+
let body = `${sourcePath} == null ? `;
|
|
355
|
+
let errorDestination;
|
|
356
|
+
if ((0, graphql_1.isNonNullType)(type)) {
|
|
357
|
+
type = type.ofType;
|
|
358
|
+
const nullErrorStr = `"Cannot return null for non-nullable field ${parentType.name}.${getFieldNodesName(fieldNodes)}."`;
|
|
359
|
+
body += `(${GLOBAL_NULL_ERRORS_NAME}.push(${createErrorObject(context, fieldNodes, previousPath, nullErrorStr)}), null) :`;
|
|
360
|
+
errorDestination = GLOBAL_NULL_ERRORS_NAME;
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
body += "null : ";
|
|
364
|
+
errorDestination = GLOBAL_ERRORS_NAME;
|
|
365
|
+
}
|
|
366
|
+
body += "(";
|
|
367
|
+
// value can be an error obj
|
|
368
|
+
const errorPath = `${sourcePath}.message != null ? ${sourcePath}.message : ${sourcePath}`;
|
|
369
|
+
body += `${sourcePath} instanceof Error ? (${errorDestination}.push(${createErrorObject(context, fieldNodes, previousPath, errorPath, sourcePath)}), null) : `;
|
|
370
|
+
if ((0, graphql_1.isLeafType)(type)) {
|
|
371
|
+
body += compileLeafType(context, type, originPaths, fieldNodes, previousPath, errorDestination);
|
|
372
|
+
}
|
|
373
|
+
else if ((0, graphql_1.isObjectType)(type)) {
|
|
374
|
+
const fieldMap = (0, ast_1.collectSubfields)(context, type, fieldNodes, previousPath);
|
|
375
|
+
body += compileObjectType(context, type, fieldNodes, originPaths, destinationPaths, previousPath, errorDestination, fieldMap, false);
|
|
376
|
+
}
|
|
377
|
+
else if ((0, graphql_1.isAbstractType)(type)) {
|
|
378
|
+
body += compileAbstractType(context, parentType, type, fieldNodes, originPaths, previousPath, errorDestination);
|
|
379
|
+
}
|
|
380
|
+
else if ((0, graphql_1.isListType)(type)) {
|
|
381
|
+
body += compileListType(context, parentType, type, fieldNodes, originPaths, previousPath, errorDestination);
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
/* istanbul ignore next */
|
|
385
|
+
throw new Error(`unsupported type: ${type.toString()}`);
|
|
386
|
+
}
|
|
387
|
+
body += ")";
|
|
388
|
+
return body;
|
|
389
|
+
}
|
|
390
|
+
function compileLeafType(context, type, originPaths, fieldNodes, previousPath, errorDestination) {
|
|
391
|
+
let body = "";
|
|
392
|
+
if (context.options.disableLeafSerialization &&
|
|
393
|
+
(type instanceof graphql_1.GraphQLEnumType || (0, graphql_1.isSpecifiedScalarType)(type))) {
|
|
394
|
+
body += `${originPaths.join(".")}`;
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
const serializerName = getSerializerName(type.name);
|
|
398
|
+
context.serializers[serializerName] = getSerializer(type, context.options.customSerializers[type.name]);
|
|
399
|
+
const parentIndexes = getParentArgIndexes(context);
|
|
400
|
+
const serializerErrorHandler = getHoistedFunctionName(context, `${type.name}${originPaths.join("")}SerializerErrorHandler`);
|
|
401
|
+
context.hoistedFunctions.push(`
|
|
402
|
+
function ${serializerErrorHandler}(${GLOBAL_EXECUTION_CONTEXT}, message, ${parentIndexes}) {
|
|
403
|
+
${errorDestination}.push(${createErrorObject(context, fieldNodes, previousPath, "message")});}
|
|
404
|
+
`);
|
|
405
|
+
body += `${GLOBAL_EXECUTION_CONTEXT}.serializers.${serializerName}(${GLOBAL_EXECUTION_CONTEXT}, ${originPaths.join(".")}, ${serializerErrorHandler}, ${parentIndexes})`;
|
|
406
|
+
}
|
|
407
|
+
return body;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Compile a node of object type.
|
|
411
|
+
* @param {CompilationContext} context
|
|
412
|
+
* @param {GraphQLObjectType} type type of the node
|
|
413
|
+
* @param fieldNodes fieldNodes array with the nodes references
|
|
414
|
+
* @param originPaths originPaths path in the parent object from where to fetch results
|
|
415
|
+
* @param destinationPaths path in the where to write the result
|
|
416
|
+
* @param responsePath response path until this node
|
|
417
|
+
* @param errorDestination Path for error array
|
|
418
|
+
* @param fieldMap map of fields to fieldNodes array with the nodes references
|
|
419
|
+
* @param alwaysDefer used to force the field to be resolved with a resolver ala graphql-js
|
|
420
|
+
* @returns {string}
|
|
421
|
+
*/
|
|
422
|
+
function compileObjectType(context, type, fieldNodes, originPaths, destinationPaths, responsePath, errorDestination, fieldMap, alwaysDefer) {
|
|
423
|
+
const body = (0, generate_function_1.default)();
|
|
424
|
+
// Begin object compilation paren
|
|
425
|
+
body("(");
|
|
426
|
+
if (typeof type.isTypeOf === "function" && !alwaysDefer) {
|
|
427
|
+
context.isTypeOfs[type.name + "IsTypeOf"] = type.isTypeOf;
|
|
428
|
+
body(`!${GLOBAL_EXECUTION_CONTEXT}.isTypeOfs["${type.name}IsTypeOf"](${originPaths.join(".")}) ? (${errorDestination}.push(${createErrorObject(context, fieldNodes, responsePath, `\`Expected value of type "${type.name}" but got: $\{${GLOBAL_INSPECT_NAME}(${originPaths.join(".")})}.\``)}), null) :`);
|
|
429
|
+
}
|
|
430
|
+
// object start
|
|
431
|
+
body("{");
|
|
432
|
+
for (const name of Object.keys(fieldMap)) {
|
|
433
|
+
const fieldNodes = fieldMap[name];
|
|
434
|
+
const field = (0, ast_1.resolveFieldDef)(context, type, fieldNodes);
|
|
435
|
+
if (!field) {
|
|
436
|
+
// Field is invalid, should have been caught in validation
|
|
437
|
+
// but the error is swallowed for compatibility reasons.
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
// Key of the object
|
|
441
|
+
// `name` is the field name or an alias supplied by the user
|
|
442
|
+
body(`"${name}": `);
|
|
443
|
+
/**
|
|
444
|
+
* Value of the object
|
|
445
|
+
*
|
|
446
|
+
* The combined condition for whether a field should be included
|
|
447
|
+
* in the object.
|
|
448
|
+
*
|
|
449
|
+
* Here, the logical operation is `||` because every fieldNode
|
|
450
|
+
* is at the same level in the tree, if at least "one of" the nodes
|
|
451
|
+
* is included, then the field is included.
|
|
452
|
+
*
|
|
453
|
+
* For example,
|
|
454
|
+
*
|
|
455
|
+
* ```graphql
|
|
456
|
+
* {
|
|
457
|
+
* foo @skip(if: $c1)
|
|
458
|
+
* ... { foo @skip(if: $c2) }
|
|
459
|
+
* }
|
|
460
|
+
* ```
|
|
461
|
+
*
|
|
462
|
+
* The logic for `foo` becomes -
|
|
463
|
+
*
|
|
464
|
+
* `compilationFor($c1) || compilationFor($c2)`
|
|
465
|
+
*/
|
|
466
|
+
const serializedResponsePath = (0, ast_1.joinSkipIncludePath)((0, ast_1.serializeObjectPathForSkipInclude)(responsePath), name);
|
|
467
|
+
const fieldCondition = context.options.useExperimentalPathBasedSkipInclude
|
|
468
|
+
? fieldNodes
|
|
469
|
+
.map((it) => it.__internalShouldIncludePath?.[serializedResponsePath])
|
|
470
|
+
.filter((it) => it)
|
|
471
|
+
.join(" || ") || /* if(true) - default */ "true"
|
|
472
|
+
: fieldNodes
|
|
473
|
+
.map((it) => it.__internalShouldInclude)
|
|
474
|
+
.filter((it) => it)
|
|
475
|
+
.join(" || ") || /* if(true) - default */ "true";
|
|
476
|
+
body(`
|
|
477
|
+
(
|
|
478
|
+
${fieldCondition}
|
|
479
|
+
)
|
|
480
|
+
`);
|
|
481
|
+
// Inline __typename
|
|
482
|
+
// No need to call a resolver for typename
|
|
483
|
+
if (field === graphql_1.TypeNameMetaFieldDef) {
|
|
484
|
+
// type.name if field is included else undefined - to remove from object
|
|
485
|
+
// during serialization
|
|
486
|
+
body(`? "${type.name}" : undefined,`);
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
let resolver = field.resolve;
|
|
490
|
+
if (!resolver && alwaysDefer) {
|
|
491
|
+
const fieldName = field.name;
|
|
492
|
+
resolver = (parent) => parent && parent[fieldName];
|
|
493
|
+
}
|
|
494
|
+
if (resolver) {
|
|
495
|
+
context.deferred.push({
|
|
496
|
+
name,
|
|
497
|
+
responsePath: (0, ast_1.addPath)(responsePath, name),
|
|
498
|
+
originPaths,
|
|
499
|
+
destinationPaths,
|
|
500
|
+
parentType: type,
|
|
501
|
+
fieldName: field.name,
|
|
502
|
+
jsFieldName: getJsFieldName(field.name),
|
|
503
|
+
fieldType: field.type,
|
|
504
|
+
fieldNodes,
|
|
505
|
+
args: (0, ast_1.getArgumentDefs)(field, fieldNodes[0])
|
|
506
|
+
});
|
|
507
|
+
context.resolvers[getResolverName(type.name, field.name)] = resolver;
|
|
508
|
+
body(`
|
|
509
|
+
? (
|
|
510
|
+
${SAFETY_CHECK_PREFIX}${context.deferred.length - 1} = true,
|
|
511
|
+
null
|
|
512
|
+
)
|
|
513
|
+
: (
|
|
514
|
+
${SAFETY_CHECK_PREFIX}${context.deferred.length - 1} = false,
|
|
515
|
+
undefined
|
|
516
|
+
)
|
|
517
|
+
`);
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
// if included
|
|
521
|
+
body("?");
|
|
522
|
+
body(compileType(context, type, field.type, fieldNodes, originPaths.concat(field.name), destinationPaths.concat(name), (0, ast_1.addPath)(responsePath, name)));
|
|
523
|
+
// if not included
|
|
524
|
+
body(": undefined");
|
|
525
|
+
}
|
|
526
|
+
// End object property
|
|
527
|
+
body(",");
|
|
528
|
+
}
|
|
529
|
+
// End object
|
|
530
|
+
body("}");
|
|
531
|
+
// End object compilation paren
|
|
532
|
+
body(")");
|
|
533
|
+
return body.toString();
|
|
534
|
+
}
|
|
535
|
+
function compileAbstractType(context, parentType, type, fieldNodes, originPaths, previousPath, errorDestination) {
|
|
536
|
+
let resolveType;
|
|
537
|
+
if (type.resolveType) {
|
|
538
|
+
resolveType = type.resolveType;
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
resolveType = (value, context, info) => defaultResolveTypeFn(value, context, info, type);
|
|
542
|
+
}
|
|
543
|
+
const typeResolverName = getTypeResolverName(type.name);
|
|
544
|
+
context.typeResolvers[typeResolverName] = resolveType;
|
|
545
|
+
const collectedTypes = context.schema
|
|
546
|
+
.getPossibleTypes(type)
|
|
547
|
+
.map((objectType) => {
|
|
548
|
+
const subContext = createSubCompilationContext(context);
|
|
549
|
+
const object = compileType(subContext, parentType, objectType, fieldNodes, originPaths, ["__concrete"], (0, ast_1.addPath)(previousPath, objectType.name, "meta"));
|
|
550
|
+
return `case "${objectType.name}": {
|
|
551
|
+
${generateUniqueDeclarations(subContext)}
|
|
552
|
+
const __concrete = ${object};
|
|
553
|
+
${compileDeferredFields(subContext)}
|
|
554
|
+
return __concrete;
|
|
555
|
+
}`;
|
|
556
|
+
})
|
|
557
|
+
.join("\n");
|
|
558
|
+
const finalTypeName = "finalType";
|
|
559
|
+
const nullTypeError = `"Runtime Object type is not a possible type for \\"${type.name}\\"."`;
|
|
560
|
+
/* eslint-disable max-len */
|
|
561
|
+
const notPossibleTypeError =
|
|
562
|
+
// eslint-disable-next-line no-template-curly-in-string
|
|
563
|
+
'`Runtime Object type "${nodeType}" is not a possible type for "' +
|
|
564
|
+
type.name +
|
|
565
|
+
'".`';
|
|
566
|
+
const noTypeError = `${finalTypeName} ? ${notPossibleTypeError} : "Abstract type ${type.name} must resolve to an Object type at runtime for field ${parentType.name}.${getFieldNodesName(fieldNodes)}. Either the ${type.name} type should provide a \\"resolveType\\" function or each possible types should provide an \\"isTypeOf\\" function."`;
|
|
567
|
+
/* eslint-enable max-len */
|
|
568
|
+
return `((nodeType, err) =>
|
|
569
|
+
{
|
|
570
|
+
if (err != null) {
|
|
571
|
+
${errorDestination}.push(${createErrorObject(context, fieldNodes, previousPath, "err.message != null ? err.message : err", "err")});
|
|
572
|
+
return null;
|
|
573
|
+
}
|
|
574
|
+
if (nodeType == null) {
|
|
575
|
+
${errorDestination}.push(${createErrorObject(context, fieldNodes, previousPath, nullTypeError)})
|
|
576
|
+
return null;
|
|
577
|
+
}
|
|
578
|
+
const ${finalTypeName} = typeof nodeType === "string" ? nodeType : nodeType.name;
|
|
579
|
+
switch(${finalTypeName}) {
|
|
580
|
+
${collectedTypes}
|
|
581
|
+
default:
|
|
582
|
+
${errorDestination}.push(${createErrorObject(context, fieldNodes, previousPath, noTypeError)})
|
|
583
|
+
return null;
|
|
584
|
+
}
|
|
585
|
+
})(
|
|
586
|
+
${GLOBAL_EXECUTION_CONTEXT}.typeResolvers.${typeResolverName}(${originPaths.join(".")},
|
|
587
|
+
${GLOBAL_CONTEXT_NAME},
|
|
588
|
+
${getExecutionInfo(context, parentType, type, type.name, fieldNodes, previousPath)}))`;
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Compile a list transformation.
|
|
592
|
+
*
|
|
593
|
+
* @param {CompilationContext} context
|
|
594
|
+
* @param {GraphQLObjectType} parentType type of the parent of object which contained this type
|
|
595
|
+
* @param {GraphQLList<GraphQLType>} type list type being compiled
|
|
596
|
+
* @param {FieldNode[]} fieldNodes
|
|
597
|
+
* @param originalObjectPaths
|
|
598
|
+
* @param {ObjectPath} responsePath
|
|
599
|
+
* @param errorDestination
|
|
600
|
+
* @returns {string} compiled list transformation
|
|
601
|
+
*/
|
|
602
|
+
function compileListType(context, parentType, type, fieldNodes, originalObjectPaths, responsePath, errorDestination) {
|
|
603
|
+
const name = originalObjectPaths.join(".");
|
|
604
|
+
const listContext = createSubCompilationContext(context);
|
|
605
|
+
// context depth will be mutated, so we cache the current value.
|
|
606
|
+
const newDepth = ++listContext.depth;
|
|
607
|
+
const fieldType = type.ofType;
|
|
608
|
+
const dataBody = compileType(listContext, parentType, fieldType, fieldNodes, ["__currentItem"], [`${GLOBAL_PARENT_NAME}[idx${newDepth}]`], (0, ast_1.addPath)(responsePath, "idx" + newDepth, "variable"));
|
|
609
|
+
const errorMessage = `"Expected Iterable, but did not find one for field ${parentType.name}.${getFieldNodesName(fieldNodes)}."`;
|
|
610
|
+
const errorCase = `(${errorDestination}.push(${createErrorObject(context, fieldNodes, responsePath, errorMessage)}), null)`;
|
|
611
|
+
const executionError = createErrorObject(context, fieldNodes, (0, ast_1.addPath)(responsePath, "idx" + newDepth, "variable"), "err.message != null ? err.message : err", "err");
|
|
612
|
+
const emptyError = createErrorObject(context, fieldNodes, responsePath, '""');
|
|
613
|
+
const uniqueDeclarations = generateUniqueDeclarations(listContext);
|
|
614
|
+
const deferredFields = compileDeferredFields(listContext);
|
|
615
|
+
const itemHandler = getHoistedFunctionName(context, `${parentType.name}${originalObjectPaths.join("")}MapItemHandler`);
|
|
616
|
+
const childIndexes = getParentArgIndexes(listContext);
|
|
617
|
+
listContext.hoistedFunctions.push(`
|
|
618
|
+
function ${itemHandler}(${GLOBAL_EXECUTION_CONTEXT}, ${GLOBAL_PARENT_NAME}, __currentItem, ${childIndexes}) {
|
|
619
|
+
${uniqueDeclarations}
|
|
620
|
+
${GLOBAL_PARENT_NAME}[idx${newDepth}] = ${dataBody};
|
|
621
|
+
${deferredFields}
|
|
622
|
+
}
|
|
623
|
+
`);
|
|
624
|
+
const safeMapHandler = getHoistedFunctionName(context, `${parentType.name}${originalObjectPaths.join("")}MapHandler`);
|
|
625
|
+
const parentIndexes = getParentArgIndexes(context);
|
|
626
|
+
listContext.hoistedFunctions.push(`
|
|
627
|
+
function ${safeMapHandler}(${GLOBAL_EXECUTION_CONTEXT}, __currentItem, idx${newDepth}, resultArray, ${parentIndexes}) {
|
|
628
|
+
if (${isPromiseInliner("__currentItem")}) {
|
|
629
|
+
${promiseStarted()}
|
|
630
|
+
__currentItem.then(result => {
|
|
631
|
+
${itemHandler}(${GLOBAL_EXECUTION_CONTEXT}, resultArray, result, ${childIndexes});
|
|
632
|
+
${promiseDone()}
|
|
633
|
+
}, err => {
|
|
634
|
+
resultArray.push(null);
|
|
635
|
+
if (err) {
|
|
636
|
+
${getErrorDestination(fieldType)}.push(${executionError});
|
|
637
|
+
} else {
|
|
638
|
+
${getErrorDestination(fieldType)}.push(${emptyError});
|
|
639
|
+
}
|
|
640
|
+
${promiseDone()}
|
|
641
|
+
});
|
|
642
|
+
} else {
|
|
643
|
+
${itemHandler}(${GLOBAL_EXECUTION_CONTEXT}, resultArray, __currentItem, ${childIndexes});
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
`);
|
|
647
|
+
return `(typeof ${name} === "string" || typeof ${name}[Symbol.iterator] !== "function") ? ${errorCase} :
|
|
648
|
+
${GLOBAL_SAFE_MAP_NAME}(${GLOBAL_EXECUTION_CONTEXT}, ${name}, ${safeMapHandler}, ${parentIndexes})`;
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Implements a generic map operation for any iterable.
|
|
652
|
+
*
|
|
653
|
+
* If the iterable is not valid, null is returned.
|
|
654
|
+
* @param context
|
|
655
|
+
* @param {Iterable<any> | string} iterable possible iterable
|
|
656
|
+
* @param {(a: any) => any} cb callback that receives the item being iterated
|
|
657
|
+
* @param idx
|
|
658
|
+
* @returns {any[]} a new array with the result of the callback
|
|
659
|
+
*/
|
|
660
|
+
function safeMap(context, iterable, cb, ...idx) {
|
|
661
|
+
let index = 0;
|
|
662
|
+
const result = [];
|
|
663
|
+
for (const a of iterable) {
|
|
664
|
+
cb(context, a, index, result, ...idx);
|
|
665
|
+
++index;
|
|
666
|
+
}
|
|
667
|
+
return result;
|
|
668
|
+
}
|
|
669
|
+
const MAGIC_MINUS_INFINITY = "__MAGIC_MINUS_INFINITY__71d4310a_d4a3_4a05_b1fe_e60779d24998";
|
|
670
|
+
const MAGIC_PLUS_INFINITY = "__MAGIC_PLUS_INFINITY__bb201c39_3333_4695_b4ad_7f1722e7aa7a";
|
|
671
|
+
const MAGIC_NAN = "__MAGIC_NAN__57f286b9_4c20_487f_b409_79804ddcb4f8";
|
|
672
|
+
const MAGIC_DATE = "__MAGIC_DATE__33a9e76d_02e0_4128_8e92_3530ad3da74d";
|
|
673
|
+
function specialValueReplacer(key, value) {
|
|
674
|
+
if (Number.isNaN(value)) {
|
|
675
|
+
return MAGIC_NAN;
|
|
676
|
+
}
|
|
677
|
+
if (value === Infinity) {
|
|
678
|
+
return MAGIC_PLUS_INFINITY;
|
|
679
|
+
}
|
|
680
|
+
if (value === -Infinity) {
|
|
681
|
+
return MAGIC_MINUS_INFINITY;
|
|
682
|
+
}
|
|
683
|
+
if (this[key] instanceof Date) {
|
|
684
|
+
return MAGIC_DATE + this[key].getTime();
|
|
685
|
+
}
|
|
686
|
+
return value;
|
|
687
|
+
}
|
|
688
|
+
function objectStringify(val) {
|
|
689
|
+
return JSON.stringify(val, specialValueReplacer)
|
|
690
|
+
.replace(new RegExp(`"${MAGIC_NAN}"`, "g"), "NaN")
|
|
691
|
+
.replace(new RegExp(`"${MAGIC_PLUS_INFINITY}"`, "g"), "Infinity")
|
|
692
|
+
.replace(new RegExp(`"${MAGIC_MINUS_INFINITY}"`, "g"), "-Infinity")
|
|
693
|
+
.replace(new RegExp(`"${MAGIC_DATE}([^"]+)"`, "g"), "new Date($1)");
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Calculates a GraphQLResolveInfo object for the resolver calls.
|
|
697
|
+
*
|
|
698
|
+
* if the resolver does not use, it returns null.
|
|
699
|
+
* @param {CompilationContext} context compilation context to submit the resolveInfoResolver
|
|
700
|
+
* @param parentType
|
|
701
|
+
* @param fieldType
|
|
702
|
+
* @param fieldName
|
|
703
|
+
* @param fieldNodes
|
|
704
|
+
* @param responsePath
|
|
705
|
+
* @returns {string} a call to the resolve info creator or "{}" if unused
|
|
706
|
+
*/
|
|
707
|
+
function getExecutionInfo(context, parentType, fieldType, fieldName, fieldNodes, responsePath) {
|
|
708
|
+
const resolveInfoName = createResolveInfoName(responsePath);
|
|
709
|
+
const { schema, fragments, operation } = context;
|
|
710
|
+
context.resolveInfos[resolveInfoName] = (0, resolve_info_1.createResolveInfoThunk)({
|
|
711
|
+
schema,
|
|
712
|
+
fragments,
|
|
713
|
+
operation,
|
|
714
|
+
parentType,
|
|
715
|
+
fieldName,
|
|
716
|
+
fieldType,
|
|
717
|
+
fieldNodes
|
|
718
|
+
}, context.options.resolverInfoEnricher);
|
|
719
|
+
return `${GLOBAL_EXECUTION_CONTEXT}.resolveInfos.${resolveInfoName}(${GLOBAL_ROOT_NAME}, ${exports.GLOBAL_VARIABLES_NAME}, ${serializeResponsePath(responsePath)})`;
|
|
720
|
+
}
|
|
721
|
+
function getArgumentsName(prefixName) {
|
|
722
|
+
return `${prefixName}Args`;
|
|
723
|
+
}
|
|
724
|
+
function getValidArgumentsVarName(prefixName) {
|
|
725
|
+
return `${prefixName}ValidArgs`;
|
|
726
|
+
}
|
|
727
|
+
function objectPath(topLevel, path) {
|
|
728
|
+
if (!path) {
|
|
729
|
+
return topLevel;
|
|
730
|
+
}
|
|
731
|
+
let objectPath = topLevel;
|
|
732
|
+
const flattened = (0, ast_1.flattenPath)(path);
|
|
733
|
+
for (const section of flattened) {
|
|
734
|
+
if (section.type === "literal") {
|
|
735
|
+
objectPath += `["${section.key}"]`;
|
|
736
|
+
}
|
|
737
|
+
else {
|
|
738
|
+
/* istanbul ignore next */
|
|
739
|
+
throw new Error("should only have received literal paths");
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
return objectPath;
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Returns a static object with the all the arguments needed for the resolver
|
|
746
|
+
* @param context
|
|
747
|
+
* @param {Arguments} args
|
|
748
|
+
* @param topLevelArg name of the toplevel
|
|
749
|
+
* @param validArgs
|
|
750
|
+
* @param returnType
|
|
751
|
+
* @param path
|
|
752
|
+
* @returns {string}
|
|
753
|
+
*/
|
|
754
|
+
function compileArguments(context, args, topLevelArg, validArgs, returnType, path) {
|
|
755
|
+
// default to assuming arguments are valid
|
|
756
|
+
let body = `
|
|
757
|
+
let ${validArgs} = true;
|
|
758
|
+
const ${topLevelArg} = ${objectStringify(args.values)};
|
|
759
|
+
`;
|
|
760
|
+
const errorDestination = getErrorDestination(returnType);
|
|
761
|
+
for (const variable of args.missing) {
|
|
762
|
+
const varName = variable.valueNode.name.value;
|
|
763
|
+
body += `if (Object.prototype.hasOwnProperty.call(${exports.GLOBAL_VARIABLES_NAME}, "${varName}")) {`;
|
|
764
|
+
if (variable.argument && (0, graphql_1.isNonNullType)(variable.argument.definition.type)) {
|
|
765
|
+
const message = `'Argument "${variable.argument.definition.name}" of non-null type "${variable.argument.definition.type.toString()}" must not be null.'`;
|
|
766
|
+
body += `if (${exports.GLOBAL_VARIABLES_NAME}['${variable.valueNode.name.value}'] == null) {
|
|
767
|
+
${errorDestination}.push(${createErrorObject(context, [variable.argument.node.value], path, message)});
|
|
768
|
+
${validArgs} = false;
|
|
769
|
+
}`;
|
|
770
|
+
}
|
|
771
|
+
body += `
|
|
772
|
+
${objectPath(topLevelArg, variable.path)} = ${exports.GLOBAL_VARIABLES_NAME}['${variable.valueNode.name.value}'];
|
|
773
|
+
}`;
|
|
774
|
+
// If there is no default value and no variable input
|
|
775
|
+
// throw a field error
|
|
776
|
+
if (variable.argument &&
|
|
777
|
+
(0, graphql_1.isNonNullType)(variable.argument.definition.type) &&
|
|
778
|
+
variable.argument.definition.defaultValue === undefined) {
|
|
779
|
+
const message = `'Argument "${variable.argument.definition.name}" of required type "${variable.argument.definition.type.toString()}" was provided the variable "$${varName}" which was not provided a runtime value.'`;
|
|
780
|
+
body += ` else {
|
|
781
|
+
${errorDestination}.push(${createErrorObject(context, [variable.argument.node.value], path, message)});
|
|
782
|
+
${validArgs} = false;
|
|
783
|
+
}`;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
return body;
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Safety checks for resolver execution is done via side effects every time a resolver function
|
|
790
|
+
* is encountered.
|
|
791
|
+
*
|
|
792
|
+
* This function generates the declarations, so the side effect is valid code.
|
|
793
|
+
*
|
|
794
|
+
* @param {CompilationContext} context compilation context
|
|
795
|
+
* @param {boolean} defaultValue usually false, meant to be true at the top level
|
|
796
|
+
* @returns {string} a list of declarations eg: var __validNode0 = false;\nvar __validNode1 = false;
|
|
797
|
+
*/
|
|
798
|
+
function generateUniqueDeclarations(context, defaultValue = false) {
|
|
799
|
+
return context.deferred
|
|
800
|
+
.map((_, idx) => `
|
|
801
|
+
let ${SAFETY_CHECK_PREFIX}${idx} = ${defaultValue};
|
|
802
|
+
`)
|
|
803
|
+
.join("\n");
|
|
804
|
+
}
|
|
805
|
+
function createSubCompilationContext(context) {
|
|
806
|
+
return { ...context, deferred: [] };
|
|
807
|
+
}
|
|
808
|
+
function isPromise(value) {
|
|
809
|
+
return (value != null &&
|
|
810
|
+
typeof value === "object" &&
|
|
811
|
+
typeof value.then === "function");
|
|
812
|
+
}
|
|
813
|
+
exports.isPromise = isPromise;
|
|
814
|
+
function isPromiseInliner(value) {
|
|
815
|
+
return `${value} != null && typeof ${value} === "object" && typeof ${value}.then === "function"`;
|
|
816
|
+
}
|
|
817
|
+
exports.isPromiseInliner = isPromiseInliner;
|
|
818
|
+
/**
|
|
819
|
+
* Serializes the response path for an error response.
|
|
820
|
+
*
|
|
821
|
+
* @param {ObjectPath | undefined} path response path of a field
|
|
822
|
+
* @returns {string} filtered serialization of the response path
|
|
823
|
+
*/
|
|
824
|
+
function serializeResponsePathAsArray(path) {
|
|
825
|
+
const flattened = (0, ast_1.flattenPath)(path);
|
|
826
|
+
let src = "[";
|
|
827
|
+
for (let i = flattened.length - 1; i >= 0; i--) {
|
|
828
|
+
// meta is only used for the function name
|
|
829
|
+
if (flattened[i].type === "meta") {
|
|
830
|
+
continue;
|
|
831
|
+
}
|
|
832
|
+
src +=
|
|
833
|
+
flattened[i].type === "literal"
|
|
834
|
+
? `"${flattened[i].key}",`
|
|
835
|
+
: `${flattened[i].key},`;
|
|
836
|
+
}
|
|
837
|
+
return src + "]";
|
|
838
|
+
}
|
|
839
|
+
function getErrorDestination(type) {
|
|
840
|
+
return (0, graphql_1.isNonNullType)(type) ? GLOBAL_NULL_ERRORS_NAME : GLOBAL_ERRORS_NAME;
|
|
841
|
+
}
|
|
842
|
+
function createResolveInfoName(path) {
|
|
843
|
+
return ((0, ast_1.flattenPath)(path)
|
|
844
|
+
.map((p) => p.key)
|
|
845
|
+
.join("_") + "Info");
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Serializes the response path for the resolve info function
|
|
849
|
+
* @param {ObjectPath | undefined} path response path of a field
|
|
850
|
+
* @returns {string} filtered serialization of the response path
|
|
851
|
+
*/
|
|
852
|
+
function serializeResponsePath(path) {
|
|
853
|
+
if (!path) {
|
|
854
|
+
return "undefined";
|
|
855
|
+
}
|
|
856
|
+
if (path.type === "meta") {
|
|
857
|
+
// meta is ignored while serializing for the resolve info functions
|
|
858
|
+
return serializeResponsePath(path.prev);
|
|
859
|
+
}
|
|
860
|
+
const literalValue = `"${path.key}"`;
|
|
861
|
+
return `{
|
|
862
|
+
key: ${path.type === "literal" ? literalValue : path.key},
|
|
863
|
+
prev: ${serializeResponsePath(path.prev)}
|
|
864
|
+
}`;
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Returned a bound serialization function of a scalar or enum
|
|
868
|
+
* @param {GraphQLScalarType | GraphQLEnumType} scalar
|
|
869
|
+
* @param customSerializer custom serializer
|
|
870
|
+
* @returns {(v: any) => any} bound serializationFunction
|
|
871
|
+
*/
|
|
872
|
+
function getSerializer(scalar, customSerializer) {
|
|
873
|
+
const { name } = scalar;
|
|
874
|
+
const serialize = customSerializer || ((val) => scalar.serialize(val));
|
|
875
|
+
return function leafSerializer(context, v, onError, ...idx) {
|
|
876
|
+
try {
|
|
877
|
+
const value = serialize(v);
|
|
878
|
+
if (isInvalid(value)) {
|
|
879
|
+
onError(context, `Expected a value of type "${name}" but received: ${v}`, ...idx);
|
|
880
|
+
return null;
|
|
881
|
+
}
|
|
882
|
+
return value;
|
|
883
|
+
}
|
|
884
|
+
catch (e) {
|
|
885
|
+
onError(context, (e && e.message) ||
|
|
886
|
+
`Expected a value of type "${name}" but received an Error`, ...idx);
|
|
887
|
+
return null;
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
/**
|
|
892
|
+
* Default abstract type resolver.
|
|
893
|
+
*
|
|
894
|
+
* It only handle sync type resolving.
|
|
895
|
+
* @param value
|
|
896
|
+
* @param contextValue
|
|
897
|
+
* @param {GraphQLResolveInfo} info
|
|
898
|
+
* @param {GraphQLAbstractType} abstractType
|
|
899
|
+
* @returns {string}
|
|
900
|
+
*/
|
|
901
|
+
function defaultResolveTypeFn(value, contextValue, info, abstractType) {
|
|
902
|
+
// First, look for `__typename`.
|
|
903
|
+
if (value != null &&
|
|
904
|
+
typeof value === "object" &&
|
|
905
|
+
typeof value.__typename === "string") {
|
|
906
|
+
return value.__typename;
|
|
907
|
+
}
|
|
908
|
+
// Otherwise, test each possible type.
|
|
909
|
+
const possibleTypes = info.schema.getPossibleTypes(abstractType);
|
|
910
|
+
for (const type of possibleTypes) {
|
|
911
|
+
if (type.isTypeOf) {
|
|
912
|
+
const isTypeOfResult = type.isTypeOf(value, contextValue, info);
|
|
913
|
+
if (isPromise(isTypeOfResult)) {
|
|
914
|
+
throw new Error(`Promises are not supported for resolving type of ${value}`);
|
|
915
|
+
}
|
|
916
|
+
else if (isTypeOfResult) {
|
|
917
|
+
return type.name;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
throw new Error(`Could not resolve the object type in possible types of ${abstractType.name} for the value: ` +
|
|
922
|
+
inspect(value));
|
|
923
|
+
}
|
|
924
|
+
/**
|
|
925
|
+
* Constructs a ExecutionContext object from the arguments passed to
|
|
926
|
+
* execute, which we will pass throughout the other execution methods.
|
|
927
|
+
*
|
|
928
|
+
* Throws a GraphQLError if a valid execution context cannot be created.
|
|
929
|
+
*/
|
|
930
|
+
function buildCompilationContext(schema, document, options, operationName) {
|
|
931
|
+
const errors = [];
|
|
932
|
+
let operation = undefined;
|
|
933
|
+
let hasMultipleAssumedOperations = false;
|
|
934
|
+
const fragments = Object.create(null);
|
|
935
|
+
for (const definition of document.definitions) {
|
|
936
|
+
switch (definition.kind) {
|
|
937
|
+
case graphql_1.Kind.OPERATION_DEFINITION:
|
|
938
|
+
if (!operationName && operation) {
|
|
939
|
+
hasMultipleAssumedOperations = true;
|
|
940
|
+
}
|
|
941
|
+
else if (!operationName ||
|
|
942
|
+
(definition.name && definition.name.value === operationName)) {
|
|
943
|
+
operation = definition;
|
|
944
|
+
}
|
|
945
|
+
break;
|
|
946
|
+
case graphql_1.Kind.FRAGMENT_DEFINITION:
|
|
947
|
+
fragments[definition.name.value] = definition;
|
|
948
|
+
break;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
if (!operation) {
|
|
952
|
+
if (operationName) {
|
|
953
|
+
throw new graphql_1.GraphQLError(`Unknown operation named "${operationName}".`);
|
|
954
|
+
}
|
|
955
|
+
else {
|
|
956
|
+
throw new graphql_1.GraphQLError("Must provide an operation.");
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
else if (hasMultipleAssumedOperations) {
|
|
960
|
+
throw new graphql_1.GraphQLError("Must provide operation name if query contains multiple operations.");
|
|
961
|
+
}
|
|
962
|
+
return {
|
|
963
|
+
schema,
|
|
964
|
+
fragments,
|
|
965
|
+
rootValue: null,
|
|
966
|
+
contextValue: null,
|
|
967
|
+
operation,
|
|
968
|
+
options,
|
|
969
|
+
resolvers: {},
|
|
970
|
+
serializers: {},
|
|
971
|
+
typeResolvers: {},
|
|
972
|
+
isTypeOfs: {},
|
|
973
|
+
resolveInfos: {},
|
|
974
|
+
hoistedFunctions: [],
|
|
975
|
+
hoistedFunctionNames: new Map(),
|
|
976
|
+
deferred: [],
|
|
977
|
+
depth: -1,
|
|
978
|
+
variableValues: {},
|
|
979
|
+
errors
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
function getFieldNodesName(nodes) {
|
|
983
|
+
return nodes.length > 1
|
|
984
|
+
? "(" + nodes.map(({ name }) => name.value).join(",") + ")"
|
|
985
|
+
: nodes[0].name.value;
|
|
986
|
+
}
|
|
987
|
+
function getHoistedFunctionName(context, name) {
|
|
988
|
+
const count = context.hoistedFunctionNames.get(name);
|
|
989
|
+
if (count === undefined) {
|
|
990
|
+
context.hoistedFunctionNames.set(name, 0);
|
|
991
|
+
return name;
|
|
992
|
+
}
|
|
993
|
+
context.hoistedFunctionNames.set(name, count + 1);
|
|
994
|
+
return `${name}${count + 1}`;
|
|
995
|
+
}
|
|
996
|
+
function createErrorObject(context, nodes, path, message, originalError) {
|
|
997
|
+
return `new ${GRAPHQL_ERROR}(${message},
|
|
998
|
+
${JSON.stringify((0, ast_1.computeLocations)(nodes))},
|
|
999
|
+
${serializeResponsePathAsArray(path)},
|
|
1000
|
+
${originalError || "undefined"},
|
|
1001
|
+
${context.options.disablingCapturingStackErrors ? "true" : "false"})`;
|
|
1002
|
+
}
|
|
1003
|
+
function getResolverName(parentName, name) {
|
|
1004
|
+
return parentName + name + "Resolver";
|
|
1005
|
+
}
|
|
1006
|
+
function getTypeResolverName(name) {
|
|
1007
|
+
return name + "TypeResolver";
|
|
1008
|
+
}
|
|
1009
|
+
function getSerializerName(name) {
|
|
1010
|
+
return name + "Serializer";
|
|
1011
|
+
}
|
|
1012
|
+
function promiseStarted() {
|
|
1013
|
+
return `
|
|
1014
|
+
// increase the promise counter
|
|
1015
|
+
++${GLOBAL_PROMISE_COUNTER};
|
|
1016
|
+
`;
|
|
1017
|
+
}
|
|
1018
|
+
function promiseDone() {
|
|
1019
|
+
return `
|
|
1020
|
+
--${GLOBAL_PROMISE_COUNTER};
|
|
1021
|
+
if (${GLOBAL_PROMISE_COUNTER} === 0) {
|
|
1022
|
+
${GLOBAL_RESOLVE}(${GLOBAL_EXECUTION_CONTEXT});
|
|
1023
|
+
}
|
|
1024
|
+
`;
|
|
1025
|
+
}
|
|
1026
|
+
function normalizeErrors(err) {
|
|
1027
|
+
if (Array.isArray(err)) {
|
|
1028
|
+
return err.map((e) => normalizeError(e));
|
|
1029
|
+
}
|
|
1030
|
+
return [normalizeError(err)];
|
|
1031
|
+
}
|
|
1032
|
+
function normalizeError(err) {
|
|
1033
|
+
return err instanceof graphql_1.GraphQLError
|
|
1034
|
+
? err
|
|
1035
|
+
: new error_1.GraphQLError(err.message, err.locations, err.path, err);
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Returns true if a value is undefined, or NaN.
|
|
1039
|
+
*/
|
|
1040
|
+
function isInvalid(value) {
|
|
1041
|
+
// eslint-disable-next-line no-self-compare
|
|
1042
|
+
return value === undefined || value !== value;
|
|
1043
|
+
}
|
|
1044
|
+
function getParentArgIndexes(context) {
|
|
1045
|
+
let args = "";
|
|
1046
|
+
for (let i = 0; i <= context.depth; ++i) {
|
|
1047
|
+
if (i > 0) {
|
|
1048
|
+
args += ", ";
|
|
1049
|
+
}
|
|
1050
|
+
args += `idx${i}`;
|
|
1051
|
+
}
|
|
1052
|
+
return args;
|
|
1053
|
+
}
|
|
1054
|
+
function getJsFieldName(fieldName) {
|
|
1055
|
+
return `${LOCAL_JS_FIELD_NAME_PREFIX}${fieldName}`;
|
|
1056
|
+
}
|
|
1057
|
+
function isAsyncIterable(val) {
|
|
1058
|
+
return typeof Object(val)[Symbol.asyncIterator] === "function";
|
|
1059
|
+
}
|
|
1060
|
+
exports.isAsyncIterable = isAsyncIterable;
|
|
1061
|
+
function compileSubscriptionOperation(context, type, fieldMap, queryFn) {
|
|
1062
|
+
const fieldNodes = Object.values(fieldMap)[0];
|
|
1063
|
+
const fieldNode = fieldNodes[0];
|
|
1064
|
+
const fieldName = fieldNode.name.value;
|
|
1065
|
+
const field = (0, ast_1.resolveFieldDef)(context, type, fieldNodes);
|
|
1066
|
+
if (!field) {
|
|
1067
|
+
throw new graphql_1.GraphQLError(`The subscription field "${fieldName}" is not defined.`, (0, compat_1.getGraphQLErrorOptions)(fieldNodes));
|
|
1068
|
+
}
|
|
1069
|
+
const responsePath = (0, ast_1.addPath)(undefined, fieldName);
|
|
1070
|
+
const resolveInfoName = createResolveInfoName(responsePath);
|
|
1071
|
+
const subscriber = field.subscribe;
|
|
1072
|
+
async function executeSubscription(executionContext) {
|
|
1073
|
+
const resolveInfo = executionContext.resolveInfos[resolveInfoName](executionContext.rootValue, executionContext.variables, responsePath);
|
|
1074
|
+
try {
|
|
1075
|
+
const eventStream = await subscriber?.(executionContext.rootValue, executionContext.variables, executionContext.context, resolveInfo);
|
|
1076
|
+
if (eventStream instanceof Error) {
|
|
1077
|
+
throw eventStream;
|
|
1078
|
+
}
|
|
1079
|
+
return eventStream;
|
|
1080
|
+
}
|
|
1081
|
+
catch (error) {
|
|
1082
|
+
throw (0, graphql_1.locatedError)(error, resolveInfo.fieldNodes, (0, Path_1.pathToArray)(resolveInfo.path));
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
async function createSourceEventStream(executionContext) {
|
|
1086
|
+
try {
|
|
1087
|
+
const eventStream = await executeSubscription(executionContext);
|
|
1088
|
+
// Assert field returned an event stream, otherwise yield an error.
|
|
1089
|
+
if (!isAsyncIterable(eventStream)) {
|
|
1090
|
+
throw new Error("Subscription field must return Async Iterable. " +
|
|
1091
|
+
`Received: ${inspect(eventStream)}.`);
|
|
1092
|
+
}
|
|
1093
|
+
return eventStream;
|
|
1094
|
+
}
|
|
1095
|
+
catch (error) {
|
|
1096
|
+
// If it is a GraphQLError, report it as an ExecutionResult, containing only errors and no data.
|
|
1097
|
+
// Otherwise treat the error as a system-class error and re-throw it.
|
|
1098
|
+
if (error instanceof graphql_1.GraphQLError) {
|
|
1099
|
+
return { errors: [error] };
|
|
1100
|
+
}
|
|
1101
|
+
throw error;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
return async function subscribe(executionContext) {
|
|
1105
|
+
const resultOrStream = await createSourceEventStream(executionContext);
|
|
1106
|
+
if (!isAsyncIterable(resultOrStream)) {
|
|
1107
|
+
return resultOrStream;
|
|
1108
|
+
}
|
|
1109
|
+
// For each payload yielded from a subscription, map it over the normal
|
|
1110
|
+
// GraphQL `execute` function, with `payload` as the rootValue.
|
|
1111
|
+
// This implements the "MapSourceToResponseEvent" algorithm described in
|
|
1112
|
+
// the GraphQL specification. The `execute` function provides the
|
|
1113
|
+
// "ExecuteSubscriptionEvent" algorithm, as it is nearly identical to the
|
|
1114
|
+
// "ExecuteQuery" algorithm, for which `execute` is also used.
|
|
1115
|
+
// We use our `query` function in place of `execute`
|
|
1116
|
+
const mapSourceToResponse = (payload) => queryFn(payload, executionContext.context, executionContext.variables);
|
|
1117
|
+
return mapAsyncIterator(resultOrStream, mapSourceToResponse);
|
|
1118
|
+
};
|
|
1119
|
+
}
|
|
1120
|
+
function createBoundSubscribe(compilationContext, document, func, getVariableValues, operationName) {
|
|
1121
|
+
const { resolvers, typeResolvers, isTypeOfs, serializers, resolveInfos } = compilationContext;
|
|
1122
|
+
const trimmer = (0, non_null_1.createNullTrimmer)(compilationContext);
|
|
1123
|
+
const fnName = operationName || "subscribe";
|
|
1124
|
+
const ret = {
|
|
1125
|
+
async [fnName](rootValue, context, variables) {
|
|
1126
|
+
// this can be shared across in a batch request
|
|
1127
|
+
const parsedVariables = getVariableValues(variables || {});
|
|
1128
|
+
// Return early errors if variable coercing failed.
|
|
1129
|
+
if ((0, variables_1.failToParseVariables)(parsedVariables)) {
|
|
1130
|
+
return { errors: parsedVariables.errors };
|
|
1131
|
+
}
|
|
1132
|
+
const executionContext = {
|
|
1133
|
+
rootValue,
|
|
1134
|
+
context,
|
|
1135
|
+
variables: parsedVariables.coerced,
|
|
1136
|
+
safeMap,
|
|
1137
|
+
inspect,
|
|
1138
|
+
GraphQLError: error_1.GraphQLError,
|
|
1139
|
+
resolvers,
|
|
1140
|
+
typeResolvers,
|
|
1141
|
+
isTypeOfs,
|
|
1142
|
+
serializers,
|
|
1143
|
+
resolveInfos,
|
|
1144
|
+
trimmer,
|
|
1145
|
+
promiseCounter: 0,
|
|
1146
|
+
nullErrors: [],
|
|
1147
|
+
errors: [],
|
|
1148
|
+
data: {}
|
|
1149
|
+
};
|
|
1150
|
+
// eslint-disable-next-line no-useless-call
|
|
1151
|
+
return func.call(null, executionContext);
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
return ret[fnName];
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* Given an AsyncIterable and a callback function, return an AsyncIterator
|
|
1158
|
+
* which produces values mapped via calling the callback function.
|
|
1159
|
+
*/
|
|
1160
|
+
function mapAsyncIterator(iterable, callback) {
|
|
1161
|
+
const iterator = iterable[Symbol.asyncIterator]();
|
|
1162
|
+
async function mapResult(result) {
|
|
1163
|
+
if (result.done) {
|
|
1164
|
+
return result;
|
|
1165
|
+
}
|
|
1166
|
+
try {
|
|
1167
|
+
return { value: await callback(result.value), done: false };
|
|
1168
|
+
}
|
|
1169
|
+
catch (error) {
|
|
1170
|
+
if (typeof iterator.return === "function") {
|
|
1171
|
+
try {
|
|
1172
|
+
await iterator.return();
|
|
1173
|
+
}
|
|
1174
|
+
catch (e) {
|
|
1175
|
+
/* ignore error */
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
throw error;
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
return {
|
|
1182
|
+
async next() {
|
|
1183
|
+
return mapResult(await iterator.next());
|
|
1184
|
+
},
|
|
1185
|
+
async return() {
|
|
1186
|
+
return typeof iterator.return === "function"
|
|
1187
|
+
? mapResult(await iterator.return())
|
|
1188
|
+
: { value: undefined, done: true };
|
|
1189
|
+
},
|
|
1190
|
+
async throw(error) {
|
|
1191
|
+
return typeof iterator.throw === "function"
|
|
1192
|
+
? mapResult(await iterator.throw(error))
|
|
1193
|
+
: Promise.reject(error);
|
|
1194
|
+
},
|
|
1195
|
+
[Symbol.asyncIterator]() {
|
|
1196
|
+
return this;
|
|
1197
|
+
}
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
//# sourceMappingURL=execution.js.map
|