graphql-jit 0.8.9 → 0.9.0
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 +25 -0
- package/dist/cjs/ast.d.ts +89 -0
- package/dist/cjs/ast.js +766 -0
- package/dist/cjs/ast.js.map +1 -0
- package/dist/cjs/compat.d.ts +70 -0
- package/dist/cjs/compat.js +144 -0
- package/dist/cjs/compat.js.map +1 -0
- package/dist/cjs/debug.d.ts +29 -0
- package/dist/cjs/debug.js +46 -0
- package/dist/cjs/debug.js.map +1 -0
- package/dist/cjs/error.d.ts +7 -0
- package/dist/cjs/error.js +58 -0
- package/dist/cjs/error.js.map +1 -0
- package/dist/cjs/execution.d.ts +154 -0
- package/dist/cjs/execution.js +1240 -0
- package/dist/cjs/execution.js.map +1 -0
- package/dist/cjs/generate.d.ts +4 -0
- package/dist/cjs/generate.js +13 -0
- package/dist/cjs/generate.js.map +1 -0
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.js +10 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/inspect.d.ts +5 -0
- package/dist/cjs/inspect.js +110 -0
- package/dist/cjs/inspect.js.map +1 -0
- package/dist/cjs/json.d.ts +9 -0
- package/dist/cjs/json.js +144 -0
- package/dist/cjs/json.js.map +1 -0
- package/dist/cjs/memoize.d.ts +5 -0
- package/dist/cjs/memoize.js +28 -0
- package/dist/cjs/memoize.js.map +1 -0
- package/dist/cjs/non-null.d.ts +9 -0
- package/dist/cjs/non-null.js +205 -0
- package/dist/cjs/non-null.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/{resolve-info.d.ts → cjs/resolve-info.d.ts} +10 -12
- package/dist/cjs/resolve-info.js +232 -0
- package/dist/cjs/resolve-info.js.map +1 -0
- package/dist/cjs/runtime.d.ts +14 -0
- package/dist/cjs/runtime.js +92 -0
- package/dist/cjs/runtime.js.map +1 -0
- package/dist/cjs/types.d.ts +1 -0
- package/dist/cjs/types.js +3 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/variables.d.ts +20 -0
- package/dist/cjs/variables.js +357 -0
- package/dist/cjs/variables.js.map +1 -0
- package/dist/esm/ast.d.ts +89 -0
- package/dist/esm/ast.js +751 -0
- package/dist/esm/ast.js.map +1 -0
- package/dist/esm/compat.d.ts +70 -0
- package/dist/esm/compat.js +102 -0
- package/dist/esm/compat.js.map +1 -0
- package/dist/esm/debug.d.ts +29 -0
- package/dist/esm/debug.js +40 -0
- package/dist/esm/debug.js.map +1 -0
- package/dist/esm/error.d.ts +7 -0
- package/dist/esm/error.js +55 -0
- package/dist/esm/error.js.map +1 -0
- package/dist/esm/execution.d.ts +154 -0
- package/dist/esm/execution.js +1227 -0
- package/dist/esm/execution.js.map +1 -0
- package/dist/esm/generate.d.ts +4 -0
- package/dist/esm/generate.js +10 -0
- package/dist/esm/generate.js.map +1 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/inspect.d.ts +5 -0
- package/dist/esm/inspect.js +106 -0
- package/dist/esm/inspect.js.map +1 -0
- package/dist/esm/json.d.ts +9 -0
- package/dist/esm/json.js +141 -0
- package/dist/esm/json.js.map +1 -0
- package/dist/esm/memoize.d.ts +5 -0
- package/dist/esm/memoize.js +20 -0
- package/dist/esm/memoize.js.map +1 -0
- package/dist/esm/non-null.d.ts +9 -0
- package/dist/esm/non-null.js +199 -0
- package/dist/esm/non-null.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/{resolve-info.d.mts → esm/resolve-info.d.ts} +10 -12
- package/dist/esm/resolve-info.js +224 -0
- package/dist/esm/resolve-info.js.map +1 -0
- package/dist/esm/runtime.d.ts +14 -0
- package/dist/esm/runtime.js +89 -0
- package/dist/esm/runtime.js.map +1 -0
- package/dist/esm/types.d.ts +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/variables.d.ts +20 -0
- package/dist/esm/variables.js +350 -0
- package/dist/esm/variables.js.map +1 -0
- package/package.json +39 -35
- package/dist/ast.d.mts +0 -7
- package/dist/ast.d.ts +0 -7
- package/dist/ast.js +0 -635
- package/dist/ast.js.map +0 -1
- package/dist/ast.mjs +0 -612
- package/dist/ast.mjs.map +0 -1
- package/dist/compat.d.mts +0 -7
- package/dist/compat.d.ts +0 -7
- package/dist/compat.js +0 -113
- package/dist/compat.js.map +0 -1
- package/dist/compat.mjs +0 -75
- package/dist/compat.mjs.map +0 -1
- package/dist/error.d.mts +0 -11
- package/dist/error.d.ts +0 -11
- package/dist/error.js +0 -79
- package/dist/error.js.map +0 -1
- package/dist/error.mjs +0 -57
- package/dist/error.mjs.map +0 -1
- package/dist/execution.d.mts +0 -7
- package/dist/execution.d.ts +0 -7
- package/dist/execution.js +0 -1262
- package/dist/execution.js.map +0 -1
- package/dist/execution.mjs +0 -1248
- package/dist/execution.mjs.map +0 -1
- package/dist/generate.d.mts +0 -6
- package/dist/generate.d.ts +0 -6
- package/dist/generate.js +0 -37
- package/dist/generate.js.map +0 -1
- package/dist/generate.mjs +0 -13
- package/dist/generate.mjs.map +0 -1
- package/dist/index-CeluTkd4.d.mts +0 -329
- package/dist/index-mKv2zpdA.d.ts +0 -329
- package/dist/index.d.mts +0 -7
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -36
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -15
- package/dist/index.mjs.map +0 -1
- package/dist/inspect.d.mts +0 -7
- package/dist/inspect.d.ts +0 -7
- package/dist/inspect.js +0 -121
- package/dist/inspect.js.map +0 -1
- package/dist/inspect.mjs +0 -97
- package/dist/inspect.mjs.map +0 -1
- package/dist/json.d.mts +0 -18
- package/dist/json.d.ts +0 -18
- package/dist/json.js +0 -181
- package/dist/json.js.map +0 -1
- package/dist/json.mjs +0 -164
- package/dist/json.mjs.map +0 -1
- package/dist/memoize.d.mts +0 -6
- package/dist/memoize.d.ts +0 -6
- package/dist/memoize.js +0 -67
- package/dist/memoize.js.map +0 -1
- package/dist/memoize.mjs +0 -31
- package/dist/memoize.mjs.map +0 -1
- package/dist/non-null.d.mts +0 -7
- package/dist/non-null.d.ts +0 -7
- package/dist/non-null.js +0 -196
- package/dist/non-null.js.map +0 -1
- package/dist/non-null.mjs +0 -167
- package/dist/non-null.mjs.map +0 -1
- package/dist/resolve-info.js +0 -245
- package/dist/resolve-info.js.map +0 -1
- package/dist/resolve-info.mjs +0 -219
- package/dist/resolve-info.mjs.map +0 -1
- package/dist/runtime.d.mts +0 -7
- package/dist/runtime.d.ts +0 -7
- package/dist/runtime.js +0 -115
- package/dist/runtime.js.map +0 -1
- package/dist/runtime.mjs +0 -91
- package/dist/runtime.mjs.map +0 -1
- package/dist/types.d.mts +0 -3
- package/dist/types.d.ts +0 -3
- package/dist/types.js +0 -17
- package/dist/types.js.map +0 -1
- package/dist/types.mjs +0 -1
- package/dist/types.mjs.map +0 -1
- package/dist/variables.d.mts +0 -17
- package/dist/variables.d.ts +0 -17
- package/dist/variables.js +0 -412
- package/dist/variables.js.map +0 -1
- package/dist/variables.mjs +0 -391
- package/dist/variables.mjs.map +0 -1
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { isListType, isNonNullType, isObjectType, isAbstractType } from "graphql";
|
|
2
|
+
import merge from "lodash.merge";
|
|
3
|
+
import { collectFields, collectSubfields, resolveFieldDef } from "./ast.js";
|
|
4
|
+
import { getOperationRootType } from "./compat.js";
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {CompilationContext} compilationContext
|
|
8
|
+
* @returns {(data: any, errors: GraphQLError[]) => {data: any; errors: GraphQLError[]}}
|
|
9
|
+
*/
|
|
10
|
+
export function createNullTrimmer(compilationContext) {
|
|
11
|
+
return trimData(parseQueryNullables(compilationContext));
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Trims a data response according to the field errors in non null fields.
|
|
15
|
+
*
|
|
16
|
+
* Errors are filtered to ensure a single field error per field.
|
|
17
|
+
*
|
|
18
|
+
* @param {QueryMetadata} nullable Description of the query and their nullability
|
|
19
|
+
* @returns {(data: any, errors: GraphQLError[]) => {data: any; errors: GraphQLError[]}}
|
|
20
|
+
* the trimmed data and a filtered list of errors.
|
|
21
|
+
*/
|
|
22
|
+
function trimData(nullable) {
|
|
23
|
+
return (data, errors) => {
|
|
24
|
+
const finalErrors = [];
|
|
25
|
+
const processedErrors = new Set();
|
|
26
|
+
for (const error of errors) {
|
|
27
|
+
if (!error.path) {
|
|
28
|
+
// should never happen, it is a bug if it does
|
|
29
|
+
throw new Error("no path available for tree trimming");
|
|
30
|
+
}
|
|
31
|
+
if (processedErrors.has(error.path.join("."))) {
|
|
32
|
+
// there can be multiple field errors in some scenario
|
|
33
|
+
// there is no need to continue processing and it should not be part of the final response
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const ancestors = findNullableAncestor(nullable, error.path);
|
|
37
|
+
// The top level field is always nullable
|
|
38
|
+
// http://facebook.github.io/graphql/June2018/#sec-Errors-and-Non-Nullability
|
|
39
|
+
//
|
|
40
|
+
// There is no mention if the following errors need to be present in the response.
|
|
41
|
+
// For now we assume this is not needed.
|
|
42
|
+
if (ancestors.length === 0) {
|
|
43
|
+
data = null;
|
|
44
|
+
finalErrors.push(error);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
removeBranch(data, ancestors);
|
|
48
|
+
processedErrors.add(error.path.join("."));
|
|
49
|
+
finalErrors.push(error);
|
|
50
|
+
}
|
|
51
|
+
return { data, errors: finalErrors };
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Removes a branch out of the response data by mutating the original object.
|
|
56
|
+
*
|
|
57
|
+
* @param tree response data
|
|
58
|
+
* @param {Array<number | string>} branch array with the path that should be trimmed
|
|
59
|
+
*/
|
|
60
|
+
function removeBranch(tree, branch) {
|
|
61
|
+
for (let i = 0; i < branch.length - 1; ++i) {
|
|
62
|
+
// if ancestor has already been removed, there's nothing to do
|
|
63
|
+
if (tree[branch[i]] === null) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
tree = tree[branch[i]];
|
|
67
|
+
}
|
|
68
|
+
const toNull = branch[branch.length - 1];
|
|
69
|
+
tree[toNull] = null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Name of the child used in array to contain the description.
|
|
73
|
+
*
|
|
74
|
+
* Only used for list to contain the child description.
|
|
75
|
+
*/
|
|
76
|
+
const ARRAY_CHILD_NAME = "index";
|
|
77
|
+
/**
|
|
78
|
+
*
|
|
79
|
+
* @param {QueryMetadata} nullable Description of the query and their nullability
|
|
80
|
+
* @param {ReadonlyArray<string | number>} paths path of the error location
|
|
81
|
+
* @returns {Array<string | number>} path of the branch to be made null
|
|
82
|
+
*/
|
|
83
|
+
function findNullableAncestor(nullable, paths) {
|
|
84
|
+
let lastNullable = 0;
|
|
85
|
+
for (let i = 0; i < paths.length; ++i) {
|
|
86
|
+
const path = paths[i];
|
|
87
|
+
const child = nullable.children[typeof path === "string" ? path : ARRAY_CHILD_NAME];
|
|
88
|
+
if (!child) {
|
|
89
|
+
// Stopping the search since we reached a leaf node,
|
|
90
|
+
// the loop should be on its final iteration
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
if (child.isNullable) {
|
|
94
|
+
lastNullable = i + 1;
|
|
95
|
+
}
|
|
96
|
+
nullable = child;
|
|
97
|
+
}
|
|
98
|
+
return paths.slice(0, lastNullable);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Produce a description of the query regarding its nullability.
|
|
102
|
+
*
|
|
103
|
+
* Leaf nodes are not present in this representation since they are not
|
|
104
|
+
* interesting for removing branches of the response tree.
|
|
105
|
+
*
|
|
106
|
+
* The structure is recursive like the query.
|
|
107
|
+
* @param {CompilationContext} compilationContext Execution content
|
|
108
|
+
* @returns {QueryMetadata} description of the query
|
|
109
|
+
*/
|
|
110
|
+
function parseQueryNullables(compilationContext) {
|
|
111
|
+
const type = getOperationRootType(compilationContext.schema, compilationContext.operation);
|
|
112
|
+
const fields = collectFields(compilationContext, type, compilationContext.operation.selectionSet, Object.create(null), Object.create(null));
|
|
113
|
+
const properties = Object.create(null);
|
|
114
|
+
for (const responseName of Object.keys(fields)) {
|
|
115
|
+
const fieldType = resolveFieldDef(compilationContext, type, fields[responseName]);
|
|
116
|
+
if (!fieldType) {
|
|
117
|
+
// if field does not exist, it should be ignored for compatibility concerns.
|
|
118
|
+
// Usually, validation would stop it before getting here but this could be an old query
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const property = transformNode(compilationContext, fields[responseName], fieldType.type);
|
|
122
|
+
if (property != null) {
|
|
123
|
+
properties[responseName] = property;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
isNullable: true,
|
|
128
|
+
children: properties
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Processes a single node to produce a description of itself and its children.
|
|
133
|
+
*
|
|
134
|
+
* Leaf nodes are ignore and removed from the description
|
|
135
|
+
* @param {CompilationContext} compilationContext
|
|
136
|
+
* @param {FieldNode[]} fieldNodes list of fields
|
|
137
|
+
* @param {GraphQLType} type Current type being processed.
|
|
138
|
+
* @returns {QueryMetadata | null} null if node is a leaf, otherwise a description of the node and its children.
|
|
139
|
+
*/
|
|
140
|
+
function transformNode(compilationContext, fieldNodes, type) {
|
|
141
|
+
if (isNonNullType(type)) {
|
|
142
|
+
const nullable = transformNode(compilationContext, fieldNodes, type.ofType);
|
|
143
|
+
if (nullable != null) {
|
|
144
|
+
nullable.isNullable = false;
|
|
145
|
+
return nullable;
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
if (isObjectType(type)) {
|
|
150
|
+
const subfields = collectSubfields(compilationContext, type, fieldNodes);
|
|
151
|
+
const properties = Object.create(null);
|
|
152
|
+
for (const responseName of Object.keys(subfields)) {
|
|
153
|
+
const fieldType = resolveFieldDef(compilationContext, type, subfields[responseName]);
|
|
154
|
+
if (!fieldType) {
|
|
155
|
+
// if field does not exist, it should be ignored for compatibility concerns.
|
|
156
|
+
// Usually, validation would stop it before getting here but this could be an old query
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const property = transformNode(compilationContext, subfields[responseName], fieldType.type);
|
|
160
|
+
if (property != null) {
|
|
161
|
+
properties[responseName] = property;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
isNullable: true,
|
|
166
|
+
children: properties
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
if (isListType(type)) {
|
|
170
|
+
const child = transformNode(compilationContext, fieldNodes, type.ofType);
|
|
171
|
+
if (child != null) {
|
|
172
|
+
return {
|
|
173
|
+
isNullable: true,
|
|
174
|
+
children: { [ARRAY_CHILD_NAME]: child }
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
isNullable: true,
|
|
179
|
+
children: {}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
if (isAbstractType(type)) {
|
|
183
|
+
return compilationContext.schema.getPossibleTypes(type).reduce((res, t) => {
|
|
184
|
+
const property = transformNode(compilationContext, fieldNodes, t);
|
|
185
|
+
if (property != null) {
|
|
186
|
+
// We do a deep merge because children can have subset of properties
|
|
187
|
+
// TODO: Possible bug: two object with different nullability on objects.
|
|
188
|
+
res.children = merge(res.children, property.children);
|
|
189
|
+
}
|
|
190
|
+
return res;
|
|
191
|
+
}, {
|
|
192
|
+
isNullable: true,
|
|
193
|
+
children: {}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
// Scalars and enum are ignored since they are leaf values
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=non-null.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"non-null.js","sourceRoot":"","sources":["../../src/non-null.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type ExecutionResult,\n type FieldNode,\n type GraphQLError,\n type GraphQLType,\n isListType,\n isNonNullType,\n isObjectType,\n isAbstractType\n} from \"graphql\";\nimport merge from \"lodash.merge\";\nimport { collectFields, collectSubfields, resolveFieldDef } from \"./ast.js\";\nimport { getOperationRootType } from \"./compat.js\";\nimport { type CompilationContext } from \"./execution.js\";\n\ninterface QueryMetadata {\n isNullable: boolean;\n children: { [key: string]: QueryMetadata };\n}\n\nexport type NullTrimmer = (data: any, errors: GraphQLError[]) => any;\n\n/**\n *\n * @param {CompilationContext} compilationContext\n * @returns {(data: any, errors: GraphQLError[]) => {data: any; errors: GraphQLError[]}}\n */\nexport function createNullTrimmer(\n compilationContext: CompilationContext\n): NullTrimmer {\n return trimData(parseQueryNullables(compilationContext));\n}\n\n/**\n * Trims a data response according to the field errors in non null fields.\n *\n * Errors are filtered to ensure a single field error per field.\n *\n * @param {QueryMetadata} nullable Description of the query and their nullability\n * @returns {(data: any, errors: GraphQLError[]) => {data: any; errors: GraphQLError[]}}\n * the trimmed data and a filtered list of errors.\n */\nfunction trimData(nullable: QueryMetadata): NullTrimmer {\n return (data: any, errors: GraphQLError[]): ExecutionResult => {\n const finalErrors = [];\n const processedErrors = new Set<string>();\n for (const error of errors) {\n if (!error.path) {\n // should never happen, it is a bug if it does\n throw new Error(\"no path available for tree trimming\");\n }\n if (processedErrors.has(error.path.join(\".\"))) {\n // there can be multiple field errors in some scenario\n // there is no need to continue processing and it should not be part of the final response\n continue;\n }\n const ancestors = findNullableAncestor(nullable, error.path);\n // The top level field is always nullable\n // http://facebook.github.io/graphql/June2018/#sec-Errors-and-Non-Nullability\n //\n // There is no mention if the following errors need to be present in the response.\n // For now we assume this is not needed.\n if (ancestors.length === 0) {\n data = null;\n finalErrors.push(error);\n break;\n }\n removeBranch(data, ancestors);\n processedErrors.add(error.path.join(\".\"));\n finalErrors.push(error);\n }\n return { data, errors: finalErrors };\n };\n}\n\n/**\n * Removes a branch out of the response data by mutating the original object.\n *\n * @param tree response data\n * @param {Array<number | string>} branch array with the path that should be trimmed\n */\nfunction removeBranch(tree: any, branch: Array<number | string>): void {\n for (let i = 0; i < branch.length - 1; ++i) {\n // if ancestor has already been removed, there's nothing to do\n if (tree[branch[i]] === null) {\n return;\n }\n tree = tree[branch[i]];\n }\n const toNull = branch[branch.length - 1];\n tree[toNull] = null;\n}\n\n/**\n * Name of the child used in array to contain the description.\n *\n * Only used for list to contain the child description.\n */\nconst ARRAY_CHILD_NAME = \"index\";\n\n/**\n *\n * @param {QueryMetadata} nullable Description of the query and their nullability\n * @param {ReadonlyArray<string | number>} paths path of the error location\n * @returns {Array<string | number>} path of the branch to be made null\n */\nfunction findNullableAncestor(\n nullable: QueryMetadata,\n paths: ReadonlyArray<string | number>\n): Array<string | number> {\n let lastNullable = 0;\n for (let i = 0; i < paths.length; ++i) {\n const path = paths[i];\n const child =\n nullable.children[typeof path === \"string\" ? path : ARRAY_CHILD_NAME];\n if (!child) {\n // Stopping the search since we reached a leaf node,\n // the loop should be on its final iteration\n break;\n }\n if (child.isNullable) {\n lastNullable = i + 1;\n }\n nullable = child;\n }\n return paths.slice(0, lastNullable);\n}\n\n/**\n * Produce a description of the query regarding its nullability.\n *\n * Leaf nodes are not present in this representation since they are not\n * interesting for removing branches of the response tree.\n *\n * The structure is recursive like the query.\n * @param {CompilationContext} compilationContext Execution content\n * @returns {QueryMetadata} description of the query\n */\nfunction parseQueryNullables(\n compilationContext: CompilationContext\n): QueryMetadata {\n const type = getOperationRootType(\n compilationContext.schema,\n compilationContext.operation\n );\n const fields = collectFields(\n compilationContext,\n type,\n compilationContext.operation.selectionSet,\n Object.create(null),\n Object.create(null)\n );\n const properties = Object.create(null);\n for (const responseName of Object.keys(fields)) {\n const fieldType = resolveFieldDef(\n compilationContext,\n type,\n fields[responseName]\n );\n if (!fieldType) {\n // if field does not exist, it should be ignored for compatibility concerns.\n // Usually, validation would stop it before getting here but this could be an old query\n continue;\n }\n const property = transformNode(\n compilationContext,\n fields[responseName],\n fieldType.type\n );\n if (property != null) {\n properties[responseName] = property;\n }\n }\n return {\n isNullable: true,\n children: properties\n };\n}\n\n/**\n * Processes a single node to produce a description of itself and its children.\n *\n * Leaf nodes are ignore and removed from the description\n * @param {CompilationContext} compilationContext\n * @param {FieldNode[]} fieldNodes list of fields\n * @param {GraphQLType} type Current type being processed.\n * @returns {QueryMetadata | null} null if node is a leaf, otherwise a description of the node and its children.\n */\nfunction transformNode(\n compilationContext: CompilationContext,\n fieldNodes: FieldNode[],\n type: GraphQLType\n): QueryMetadata | null {\n if (isNonNullType(type)) {\n const nullable = transformNode(compilationContext, fieldNodes, type.ofType);\n if (nullable != null) {\n nullable.isNullable = false;\n return nullable;\n }\n return null;\n }\n if (isObjectType(type)) {\n const subfields = collectSubfields(compilationContext, type, fieldNodes);\n const properties = Object.create(null);\n for (const responseName of Object.keys(subfields)) {\n const fieldType = resolveFieldDef(\n compilationContext,\n type,\n subfields[responseName]\n );\n if (!fieldType) {\n // if field does not exist, it should be ignored for compatibility concerns.\n // Usually, validation would stop it before getting here but this could be an old query\n continue;\n }\n const property = transformNode(\n compilationContext,\n subfields[responseName],\n fieldType.type\n );\n if (property != null) {\n properties[responseName] = property;\n }\n }\n return {\n isNullable: true,\n children: properties\n };\n }\n if (isListType(type)) {\n const child = transformNode(compilationContext, fieldNodes, type.ofType);\n if (child != null) {\n return {\n isNullable: true,\n children: { [ARRAY_CHILD_NAME]: child }\n };\n }\n\n return {\n isNullable: true,\n children: {}\n };\n }\n if (isAbstractType(type)) {\n return compilationContext.schema.getPossibleTypes(type).reduce(\n (res, t) => {\n const property = transformNode(compilationContext, fieldNodes, t);\n if (property != null) {\n // We do a deep merge because children can have subset of properties\n // TODO: Possible bug: two object with different nullability on objects.\n res.children = merge(res.children, property.children);\n }\n return res;\n },\n {\n isNullable: true,\n children: {}\n }\n );\n }\n\n // Scalars and enum are ignored since they are leaf values\n return null;\n}\n"]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
interface ResolveInfoEnricherInput {
|
|
1
|
+
import { type FieldNode, GraphQLObjectType, type GraphQLOutputType, type GraphQLResolveInfo } from "graphql";
|
|
2
|
+
export type GraphQLJitResolveInfo<Enrichments> = GraphQLResolveInfo & Enrichments;
|
|
3
|
+
export interface ResolveInfoEnricherInput {
|
|
5
4
|
schema: GraphQLResolveInfo["schema"];
|
|
6
5
|
fragments: GraphQLResolveInfo["fragments"];
|
|
7
6
|
operation: GraphQLResolveInfo["operation"];
|
|
@@ -10,23 +9,23 @@ interface ResolveInfoEnricherInput {
|
|
|
10
9
|
fieldName: string;
|
|
11
10
|
fieldNodes: FieldNode[];
|
|
12
11
|
}
|
|
13
|
-
interface FieldExpansion {
|
|
12
|
+
export interface FieldExpansion {
|
|
14
13
|
[returnType: string]: TypeExpansion;
|
|
15
14
|
}
|
|
16
15
|
declare const LeafFieldSymbol: unique symbol;
|
|
17
|
-
interface LeafField {
|
|
16
|
+
export interface LeafField {
|
|
18
17
|
[LeafFieldSymbol]: true;
|
|
19
18
|
}
|
|
20
|
-
interface TypeExpansion {
|
|
19
|
+
export interface TypeExpansion {
|
|
21
20
|
[fieldName: string]: FieldExpansion | LeafField;
|
|
22
21
|
}
|
|
23
|
-
declare function isLeafField(obj: LeafField | FieldExpansion): obj is LeafField;
|
|
22
|
+
export declare function isLeafField(obj: LeafField | FieldExpansion): obj is LeafField;
|
|
24
23
|
/**
|
|
25
24
|
* Compute the GraphQLJitResolveInfo's `fieldExpansion` and return a function
|
|
26
25
|
* that returns the computed resolveInfo. This thunk is registered in
|
|
27
26
|
* context.dependencies for the field's resolveInfoName
|
|
28
27
|
*/
|
|
29
|
-
declare function createResolveInfoThunk<T>({ schema, fragments, operation, parentType, fieldName, fieldType, fieldNodes }: {
|
|
28
|
+
export declare function createResolveInfoThunk<T>({ schema, fragments, operation, parentType, fieldName, fieldType, fieldNodes }: {
|
|
30
29
|
schema: GraphQLResolveInfo["schema"];
|
|
31
30
|
fragments: GraphQLResolveInfo["fragments"];
|
|
32
31
|
operation: GraphQLResolveInfo["operation"];
|
|
@@ -35,8 +34,7 @@ declare function createResolveInfoThunk<T>({ schema, fragments, operation, paren
|
|
|
35
34
|
fieldName: string;
|
|
36
35
|
fieldNodes: FieldNode[];
|
|
37
36
|
}, enricher?: (inp: ResolveInfoEnricherInput) => T): any;
|
|
38
|
-
declare function fieldExpansionEnricher(input: ResolveInfoEnricherInput): {
|
|
37
|
+
export declare function fieldExpansionEnricher(input: ResolveInfoEnricherInput): {
|
|
39
38
|
fieldExpansion: FieldExpansion;
|
|
40
39
|
};
|
|
41
|
-
|
|
42
|
-
export { type FieldExpansion, type GraphQLJitResolveInfo, type LeafField, type ResolveInfoEnricherInput, type TypeExpansion, createResolveInfoThunk, fieldExpansionEnricher, isLeafField };
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { genFn } from "./generate.js";
|
|
2
|
+
import { doTypesOverlap, GraphQLError, isAbstractType, isCompositeType, isListType, isNonNullType, isObjectType, isUnionType, Kind } from "graphql";
|
|
3
|
+
import memoize from "lodash.memoize";
|
|
4
|
+
import mergeWith from "lodash.mergewith";
|
|
5
|
+
import { memoize2, memoize4 } from "./memoize.js";
|
|
6
|
+
const LeafFieldSymbol = Symbol("LeafFieldSymbol");
|
|
7
|
+
function createLeafField(props) {
|
|
8
|
+
return {
|
|
9
|
+
[LeafFieldSymbol]: true,
|
|
10
|
+
...props
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function isLeafField(obj) {
|
|
14
|
+
return (obj != null && Object.prototype.hasOwnProperty.call(obj, LeafFieldSymbol));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Compute the GraphQLJitResolveInfo's `fieldExpansion` and return a function
|
|
18
|
+
* that returns the computed resolveInfo. This thunk is registered in
|
|
19
|
+
* context.dependencies for the field's resolveInfoName
|
|
20
|
+
*/
|
|
21
|
+
export function createResolveInfoThunk({ schema, fragments, operation, parentType, fieldName, fieldType, fieldNodes }, enricher) {
|
|
22
|
+
let enrichedInfo = {};
|
|
23
|
+
if (typeof enricher === "function") {
|
|
24
|
+
enrichedInfo =
|
|
25
|
+
enricher({
|
|
26
|
+
fieldName,
|
|
27
|
+
fieldNodes,
|
|
28
|
+
returnType: fieldType,
|
|
29
|
+
parentType,
|
|
30
|
+
schema,
|
|
31
|
+
fragments,
|
|
32
|
+
operation
|
|
33
|
+
}) || {};
|
|
34
|
+
if (typeof enrichedInfo !== "object" || Array.isArray(enrichedInfo)) {
|
|
35
|
+
enrichedInfo = {};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const gen = genFn();
|
|
39
|
+
gen(`return function getGraphQLResolveInfo(rootValue, variableValues, path) {
|
|
40
|
+
return {
|
|
41
|
+
fieldName,
|
|
42
|
+
fieldNodes,
|
|
43
|
+
returnType: fieldType,
|
|
44
|
+
parentType,
|
|
45
|
+
path,
|
|
46
|
+
schema,
|
|
47
|
+
fragments,
|
|
48
|
+
rootValue,
|
|
49
|
+
operation,
|
|
50
|
+
variableValues,`);
|
|
51
|
+
Object.keys(enrichedInfo).forEach((key) => {
|
|
52
|
+
gen(`${key}: enrichedInfo["${key}"],\n`);
|
|
53
|
+
});
|
|
54
|
+
gen(`};};`);
|
|
55
|
+
// eslint-disable-next-line
|
|
56
|
+
return new Function("fieldName", "fieldNodes", "fieldType", "parentType", "schema", "fragments", "operation", "enrichedInfo", gen.toString()).call(null, fieldName, fieldNodes, fieldType, parentType, schema, fragments, operation, enrichedInfo);
|
|
57
|
+
}
|
|
58
|
+
export function fieldExpansionEnricher(input) {
|
|
59
|
+
const { schema, fragments, returnType, fieldNodes } = input;
|
|
60
|
+
const fieldExpansion = {};
|
|
61
|
+
for (const fieldNode of fieldNodes) {
|
|
62
|
+
deepMerge(fieldExpansion, memoizedExpandFieldNode(schema, fragments, fieldNode, returnType));
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
fieldExpansion
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const MEMOIZATION = true;
|
|
69
|
+
const memoizedGetReturnType = MEMOIZATION
|
|
70
|
+
? memoize2(getReturnType)
|
|
71
|
+
: getReturnType;
|
|
72
|
+
const memoizedHasField = MEMOIZATION ? memoize2(hasField) : hasField;
|
|
73
|
+
const memoizedResolveEndType = MEMOIZATION
|
|
74
|
+
? memoize(resolveEndType)
|
|
75
|
+
: resolveEndType;
|
|
76
|
+
const memoizedGetPossibleTypes = MEMOIZATION
|
|
77
|
+
? memoize2(getPossibleTypes)
|
|
78
|
+
: getPossibleTypes;
|
|
79
|
+
const memoizedExpandFieldNodeType = MEMOIZATION
|
|
80
|
+
? memoize4(expandFieldNodeType)
|
|
81
|
+
: expandFieldNodeType;
|
|
82
|
+
const memoizedExpandFieldNode = MEMOIZATION
|
|
83
|
+
? memoize4(expandFieldNode)
|
|
84
|
+
: expandFieldNode;
|
|
85
|
+
function expandFieldNode(schema, fragments, node, fieldType) {
|
|
86
|
+
if (node.selectionSet == null) {
|
|
87
|
+
return createLeafField({});
|
|
88
|
+
}
|
|
89
|
+
// there is a selectionSet which makes the fieldType a CompositeType
|
|
90
|
+
const typ = memoizedResolveEndType(fieldType);
|
|
91
|
+
const possibleTypes = memoizedGetPossibleTypes(schema, typ);
|
|
92
|
+
const fieldExpansion = {};
|
|
93
|
+
for (const possibleType of possibleTypes) {
|
|
94
|
+
if (!isUnionType(possibleType)) {
|
|
95
|
+
fieldExpansion[possibleType.name] = memoizedExpandFieldNodeType(schema, fragments, possibleType, node.selectionSet);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return fieldExpansion;
|
|
99
|
+
}
|
|
100
|
+
function expandFieldNodeType(schema, fragments, parentType, selectionSet) {
|
|
101
|
+
const typeExpansion = {};
|
|
102
|
+
for (const selection of selectionSet.selections) {
|
|
103
|
+
if (selection.kind === Kind.FIELD) {
|
|
104
|
+
if (!isUnionType(parentType) &&
|
|
105
|
+
memoizedHasField(parentType, selection.name.value)) {
|
|
106
|
+
typeExpansion[selection.name.value] = memoizedExpandFieldNode(schema, fragments, selection, memoizedGetReturnType(parentType, selection.name.value));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const selectionSet = selection.kind === Kind.INLINE_FRAGMENT
|
|
111
|
+
? selection.selectionSet
|
|
112
|
+
: fragments[selection.name.value].selectionSet;
|
|
113
|
+
const nextType = selection.kind === Kind.INLINE_FRAGMENT
|
|
114
|
+
? selection.typeCondition
|
|
115
|
+
? schema.getType(selection.typeCondition.name.value)
|
|
116
|
+
: parentType
|
|
117
|
+
: schema.getType(fragments[selection.name.value].typeCondition.name.value);
|
|
118
|
+
/**
|
|
119
|
+
* nextType (comes from query) is the type extracted from the fragment
|
|
120
|
+
* parentType (comes from schema) is the possibleType for which we are filling fields
|
|
121
|
+
*
|
|
122
|
+
* if the type from query (nextType) is the same as the type we are filling (parentType)
|
|
123
|
+
* or
|
|
124
|
+
* if the type from query (nextType) is an abstract type - this case is when we jump
|
|
125
|
+
* to a super type or sub type. Here we maintain the context (parentType) for which
|
|
126
|
+
* we are filling the fields. The super type / sub type will be filled in its own
|
|
127
|
+
* pass.
|
|
128
|
+
*/
|
|
129
|
+
if (nextType === parentType || isAbstractType(nextType)) {
|
|
130
|
+
deepMerge(typeExpansion, memoizedExpandFieldNodeType(schema, fragments, parentType, selectionSet));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return typeExpansion;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Returns a list of Possible types that one can get to from the
|
|
138
|
+
* resolvedType. As an analogy, these are the same types that one
|
|
139
|
+
* can use in a fragment's typeCondition.
|
|
140
|
+
*
|
|
141
|
+
* Note: This is different from schema.getPossibleTypes() that this
|
|
142
|
+
* returns all possible types and not just the ones from the type definition.
|
|
143
|
+
*
|
|
144
|
+
* Example:
|
|
145
|
+
* interface Node {
|
|
146
|
+
* id: ID!
|
|
147
|
+
* }
|
|
148
|
+
* type User implements Node {
|
|
149
|
+
* id: ID!
|
|
150
|
+
* name: String
|
|
151
|
+
* }
|
|
152
|
+
* type Article implements Node {
|
|
153
|
+
* id: ID!
|
|
154
|
+
* title: String
|
|
155
|
+
* }
|
|
156
|
+
* union Card = User | Article
|
|
157
|
+
*
|
|
158
|
+
* - schema.getPossibleTypes(Card) would give [User, Article]
|
|
159
|
+
* - This function getPossibleTypes(schema, Card) would give [User, Article, Node]
|
|
160
|
+
*
|
|
161
|
+
*/
|
|
162
|
+
function getPossibleTypes(schema, compositeType) {
|
|
163
|
+
if (isObjectType(compositeType)) {
|
|
164
|
+
return [compositeType];
|
|
165
|
+
}
|
|
166
|
+
const possibleTypes = [];
|
|
167
|
+
const types = schema.getTypeMap();
|
|
168
|
+
for (const typeName in types) {
|
|
169
|
+
if (Object.prototype.hasOwnProperty.call(types, typeName)) {
|
|
170
|
+
const typ = types[typeName];
|
|
171
|
+
if (isCompositeType(typ) && doTypesOverlap(schema, typ, compositeType)) {
|
|
172
|
+
possibleTypes.push(typ);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return possibleTypes;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Given an (Object|Interface)Type, and a fieldName, find the
|
|
180
|
+
* appropriate `end` return type for the field in the Composite Type.
|
|
181
|
+
*
|
|
182
|
+
* Note: The `end` return type is the type by unwrapping non-null types
|
|
183
|
+
* and list types. Check `resolveEndType`
|
|
184
|
+
*/
|
|
185
|
+
function getReturnType(parentType, fieldName) {
|
|
186
|
+
const fields = parentType.getFields();
|
|
187
|
+
if (!Object.prototype.hasOwnProperty.call(fields, fieldName)) {
|
|
188
|
+
throw new GraphQLError(`Field "${fieldName}" does not exist in "${parentType.name}"`);
|
|
189
|
+
}
|
|
190
|
+
const outputType = fields[fieldName].type;
|
|
191
|
+
return memoizedResolveEndType(outputType);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Resolve to the end type of the Output type unwrapping non-null types and lists
|
|
195
|
+
*/
|
|
196
|
+
function resolveEndType(typ) {
|
|
197
|
+
if (isListType(typ) || isNonNullType(typ)) {
|
|
198
|
+
return memoizedResolveEndType(typ.ofType);
|
|
199
|
+
}
|
|
200
|
+
return typ;
|
|
201
|
+
}
|
|
202
|
+
function hasField(typ, fieldName) {
|
|
203
|
+
return Object.prototype.hasOwnProperty.call(typ.getFields(), fieldName);
|
|
204
|
+
}
|
|
205
|
+
// This is because lodash does not support merging keys
|
|
206
|
+
// which are symbols. We require them for leaf fields
|
|
207
|
+
function deepMerge(obj, src) {
|
|
208
|
+
mergeWith(obj, src, (objValue, srcValue) => {
|
|
209
|
+
if (isLeafField(objValue)) {
|
|
210
|
+
if (isLeafField(srcValue)) {
|
|
211
|
+
return {
|
|
212
|
+
...objValue,
|
|
213
|
+
...srcValue
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
return objValue;
|
|
217
|
+
}
|
|
218
|
+
else if (isLeafField(srcValue)) {
|
|
219
|
+
return srcValue;
|
|
220
|
+
}
|
|
221
|
+
return undefined;
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=resolve-info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-info.js","sourceRoot":"","sources":["../../src/resolve-info.ts"],"names":[],"mappings":"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","sourcesContent":["import { genFn } from \"./generate.js\";\nimport {\n doTypesOverlap,\n type FieldNode,\n type GraphQLCompositeType,\n GraphQLError,\n GraphQLInterfaceType,\n type GraphQLNamedType,\n GraphQLObjectType,\n type GraphQLOutputType,\n type GraphQLResolveInfo,\n GraphQLSchema,\n isAbstractType,\n isCompositeType,\n isListType,\n isNonNullType,\n isObjectType,\n isUnionType,\n Kind,\n type SelectionSetNode\n} from \"graphql\";\nimport memoize from \"lodash.memoize\";\nimport mergeWith from \"lodash.mergewith\";\nimport { memoize2, memoize4 } from \"./memoize.js\";\n\n// TODO(boopathi): Use negated types to express\n// Enrichments<T> = { [key in (string & not keyof GraphQLResolveInfo)]: T[key] }\n// in TypeScript 3.5\n// https://github.com/Microsoft/TypeScript/pull/29317\nexport type GraphQLJitResolveInfo<Enrichments> = GraphQLResolveInfo &\n Enrichments;\n\nexport interface ResolveInfoEnricherInput {\n schema: GraphQLResolveInfo[\"schema\"];\n fragments: GraphQLResolveInfo[\"fragments\"];\n operation: GraphQLResolveInfo[\"operation\"];\n parentType: GraphQLObjectType;\n returnType: GraphQLOutputType;\n fieldName: string;\n fieldNodes: FieldNode[];\n}\n\nexport interface FieldExpansion {\n // The possible return types that the field can return\n // It includes all the types in the Schema that intersect with the actual return type\n [returnType: string]: TypeExpansion;\n}\n\nconst LeafFieldSymbol = Symbol(\"LeafFieldSymbol\");\n\nexport interface LeafField {\n [LeafFieldSymbol]: true;\n}\n\nexport interface TypeExpansion {\n // The fields that are requested in the Query for a particular type\n // `true` indicates a leaf node\n [fieldName: string]: FieldExpansion | LeafField;\n}\n\nfunction createLeafField<T extends object>(props: T): T & LeafField {\n return {\n [LeafFieldSymbol]: true,\n ...props\n };\n}\n\nexport function isLeafField(obj: LeafField | FieldExpansion): obj is LeafField {\n return (\n obj != null && Object.prototype.hasOwnProperty.call(obj, LeafFieldSymbol)\n );\n}\n\n/**\n * Compute the GraphQLJitResolveInfo's `fieldExpansion` and return a function\n * that returns the computed resolveInfo. This thunk is registered in\n * context.dependencies for the field's resolveInfoName\n */\nexport function createResolveInfoThunk<T>(\n {\n schema,\n fragments,\n operation,\n parentType,\n fieldName,\n fieldType,\n fieldNodes\n }: {\n schema: GraphQLResolveInfo[\"schema\"];\n fragments: GraphQLResolveInfo[\"fragments\"];\n operation: GraphQLResolveInfo[\"operation\"];\n parentType: GraphQLObjectType;\n fieldType: GraphQLOutputType;\n fieldName: string;\n fieldNodes: FieldNode[];\n },\n enricher?: (inp: ResolveInfoEnricherInput) => T\n) {\n let enrichedInfo = {};\n if (typeof enricher === \"function\") {\n enrichedInfo =\n enricher({\n fieldName,\n fieldNodes,\n returnType: fieldType,\n parentType,\n schema,\n fragments,\n operation\n }) || {};\n if (typeof enrichedInfo !== \"object\" || Array.isArray(enrichedInfo)) {\n enrichedInfo = {};\n }\n }\n const gen = genFn();\n gen(`return function getGraphQLResolveInfo(rootValue, variableValues, path) {\n return {\n fieldName,\n fieldNodes,\n returnType: fieldType,\n parentType,\n path,\n schema,\n fragments,\n rootValue,\n operation,\n variableValues,`);\n Object.keys(enrichedInfo).forEach((key) => {\n gen(`${key}: enrichedInfo[\"${key}\"],\\n`);\n });\n gen(`};};`);\n // eslint-disable-next-line\n return new Function(\n \"fieldName\",\n \"fieldNodes\",\n \"fieldType\",\n \"parentType\",\n \"schema\",\n \"fragments\",\n \"operation\",\n \"enrichedInfo\",\n gen.toString()\n ).call(\n null,\n fieldName,\n fieldNodes,\n fieldType,\n parentType,\n schema,\n fragments,\n operation,\n enrichedInfo\n );\n}\n\nexport function fieldExpansionEnricher(input: ResolveInfoEnricherInput) {\n const { schema, fragments, returnType, fieldNodes } = input;\n const fieldExpansion: FieldExpansion | LeafField = {};\n\n for (const fieldNode of fieldNodes) {\n deepMerge(\n fieldExpansion,\n memoizedExpandFieldNode(schema, fragments, fieldNode, returnType)\n );\n }\n\n return {\n fieldExpansion\n };\n}\n\ntype FragmentsType = GraphQLResolveInfo[\"fragments\"];\ntype GraphQLNamedOutputType = GraphQLNamedType & GraphQLOutputType;\ntype GraphQLObjectLike = GraphQLInterfaceType | GraphQLObjectType;\n\nconst MEMOIZATION = true;\n\nconst memoizedGetReturnType = MEMOIZATION\n ? memoize2(getReturnType)\n : getReturnType;\nconst memoizedHasField = MEMOIZATION ? memoize2(hasField) : hasField;\nconst memoizedResolveEndType = MEMOIZATION\n ? memoize(resolveEndType)\n : resolveEndType;\nconst memoizedGetPossibleTypes = MEMOIZATION\n ? memoize2(getPossibleTypes)\n : getPossibleTypes;\nconst memoizedExpandFieldNodeType = MEMOIZATION\n ? memoize4(expandFieldNodeType)\n : expandFieldNodeType;\nconst memoizedExpandFieldNode = MEMOIZATION\n ? memoize4(expandFieldNode)\n : expandFieldNode;\n\nfunction expandFieldNode(\n schema: GraphQLSchema,\n fragments: FragmentsType,\n node: FieldNode,\n fieldType: GraphQLOutputType\n): FieldExpansion | LeafField {\n if (node.selectionSet == null) {\n return createLeafField({});\n }\n\n // there is a selectionSet which makes the fieldType a CompositeType\n const typ = memoizedResolveEndType(fieldType) as GraphQLCompositeType;\n const possibleTypes = memoizedGetPossibleTypes(schema, typ);\n\n const fieldExpansion: FieldExpansion = {};\n for (const possibleType of possibleTypes) {\n if (!isUnionType(possibleType)) {\n fieldExpansion[possibleType.name] = memoizedExpandFieldNodeType(\n schema,\n fragments,\n possibleType,\n node.selectionSet\n );\n }\n }\n\n return fieldExpansion;\n}\n\nfunction expandFieldNodeType(\n schema: GraphQLSchema,\n fragments: FragmentsType,\n parentType: GraphQLCompositeType,\n selectionSet: SelectionSetNode\n): TypeExpansion {\n const typeExpansion: TypeExpansion = {};\n\n for (const selection of selectionSet.selections) {\n if (selection.kind === Kind.FIELD) {\n if (\n !isUnionType(parentType) &&\n memoizedHasField(parentType, selection.name.value)\n ) {\n typeExpansion[selection.name.value] = memoizedExpandFieldNode(\n schema,\n fragments,\n selection,\n memoizedGetReturnType(parentType, selection.name.value)\n );\n }\n } else {\n const selectionSet =\n selection.kind === Kind.INLINE_FRAGMENT\n ? selection.selectionSet\n : fragments[selection.name.value].selectionSet;\n\n const nextType =\n selection.kind === Kind.INLINE_FRAGMENT\n ? selection.typeCondition\n ? (schema.getType(\n selection.typeCondition.name.value\n ) as GraphQLCompositeType)\n : parentType\n : (schema.getType(\n fragments[selection.name.value].typeCondition.name.value\n ) as GraphQLCompositeType);\n\n /**\n * nextType (comes from query) is the type extracted from the fragment\n * parentType (comes from schema) is the possibleType for which we are filling fields\n *\n * if the type from query (nextType) is the same as the type we are filling (parentType)\n * or\n * if the type from query (nextType) is an abstract type - this case is when we jump\n * to a super type or sub type. Here we maintain the context (parentType) for which\n * we are filling the fields. The super type / sub type will be filled in its own\n * pass.\n */\n if (nextType === parentType || isAbstractType(nextType)) {\n deepMerge(\n typeExpansion,\n memoizedExpandFieldNodeType(\n schema,\n fragments,\n parentType,\n selectionSet\n )\n );\n }\n }\n }\n\n return typeExpansion;\n}\n\n/**\n * Returns a list of Possible types that one can get to from the\n * resolvedType. As an analogy, these are the same types that one\n * can use in a fragment's typeCondition.\n *\n * Note: This is different from schema.getPossibleTypes() that this\n * returns all possible types and not just the ones from the type definition.\n *\n * Example:\n * interface Node {\n * id: ID!\n * }\n * type User implements Node {\n * id: ID!\n * name: String\n * }\n * type Article implements Node {\n * id: ID!\n * title: String\n * }\n * union Card = User | Article\n *\n * - schema.getPossibleTypes(Card) would give [User, Article]\n * - This function getPossibleTypes(schema, Card) would give [User, Article, Node]\n *\n */\nfunction getPossibleTypes(\n schema: GraphQLSchema,\n compositeType: GraphQLCompositeType\n) {\n if (isObjectType(compositeType)) {\n return [compositeType];\n }\n\n const possibleTypes: GraphQLCompositeType[] = [];\n const types = schema.getTypeMap();\n for (const typeName in types) {\n if (Object.prototype.hasOwnProperty.call(types, typeName)) {\n const typ = types[typeName];\n if (isCompositeType(typ) && doTypesOverlap(schema, typ, compositeType)) {\n possibleTypes.push(typ);\n }\n }\n }\n\n return possibleTypes;\n}\n\n/**\n * Given an (Object|Interface)Type, and a fieldName, find the\n * appropriate `end` return type for the field in the Composite Type.\n *\n * Note: The `end` return type is the type by unwrapping non-null types\n * and list types. Check `resolveEndType`\n */\nfunction getReturnType(\n parentType: GraphQLObjectLike,\n fieldName: string\n): GraphQLNamedOutputType {\n const fields = parentType.getFields();\n if (!Object.prototype.hasOwnProperty.call(fields, fieldName)) {\n throw new GraphQLError(\n `Field \"${fieldName}\" does not exist in \"${parentType.name}\"`\n );\n }\n\n const outputType = fields[fieldName].type;\n return memoizedResolveEndType(outputType);\n}\n\n/**\n * Resolve to the end type of the Output type unwrapping non-null types and lists\n */\nfunction resolveEndType(typ: GraphQLOutputType): GraphQLNamedOutputType {\n if (isListType(typ) || isNonNullType(typ)) {\n return memoizedResolveEndType(typ.ofType);\n }\n return typ;\n}\n\nfunction hasField(typ: GraphQLObjectLike, fieldName: string) {\n return Object.prototype.hasOwnProperty.call(typ.getFields(), fieldName);\n}\n\n// This is because lodash does not support merging keys\n// which are symbols. We require them for leaf fields\nfunction deepMerge<TObject, TSource>(obj: TObject, src: TSource) {\n mergeWith(obj, src, (objValue, srcValue): LeafField | undefined => {\n if (isLeafField(objValue)) {\n if (isLeafField(srcValue)) {\n return {\n ...objValue,\n ...srcValue\n };\n }\n\n return objValue;\n } else if (isLeafField(srcValue)) {\n return srcValue;\n }\n\n return undefined;\n });\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ExecutionContext } from "./execution.js";
|
|
2
|
+
type Serializer = (c: ExecutionContext, v: any, onError: any, ...idx: number[]) => any;
|
|
3
|
+
export declare const jitRuntime: {
|
|
4
|
+
isPromise(value: unknown): boolean;
|
|
5
|
+
checkNonNullLeaf(ctx: ExecutionContext, value: unknown, dest: any[], nullMsg: string, locs: any, path: any, capStack: boolean, serialize: Serializer, errHandler: any, ...parentIndexes: number[]): any;
|
|
6
|
+
checkNullableLeaf(ctx: ExecutionContext, value: unknown, dest: any[], locs: any, path: any, capStack: boolean, serialize: Serializer, errHandler: any, ...parentIndexes: number[]): any;
|
|
7
|
+
callResolver(ctx: ExecutionContext, call: () => unknown, onSuccess: (result: unknown) => void, onError: (err: unknown) => void): void;
|
|
8
|
+
handleResolverResult(ctx: ExecutionContext, value: unknown, onSuccess: (result: unknown) => void, onError: (err: unknown) => void): void;
|
|
9
|
+
handleListItemResult(ctx: ExecutionContext, item: unknown, onSuccess: (result: unknown) => void, onError: (err: unknown) => void): void;
|
|
10
|
+
finalizeResult(ctx: ExecutionContext): Promise<unknown> | undefined;
|
|
11
|
+
safeMap(ctx: ExecutionContext, iterable: Iterable<unknown> | string, cb: (context: ExecutionContext, a: unknown, index: number, resultArray: unknown[], ...idx: number[]) => void, ...idx: number[]): unknown[];
|
|
12
|
+
};
|
|
13
|
+
export type JitRuntime = typeof jitRuntime;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
function resolvePromise(ctx, promise, onSuccess, onError) {
|
|
2
|
+
++ctx.promiseCounter;
|
|
3
|
+
promise.then((result) => {
|
|
4
|
+
onSuccess(result);
|
|
5
|
+
--ctx.promiseCounter;
|
|
6
|
+
if (ctx.promiseCounter === 0)
|
|
7
|
+
ctx.resolve(ctx);
|
|
8
|
+
}, (err) => {
|
|
9
|
+
onError(err);
|
|
10
|
+
--ctx.promiseCounter;
|
|
11
|
+
if (ctx.promiseCounter === 0)
|
|
12
|
+
ctx.resolve(ctx);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export const jitRuntime = {
|
|
16
|
+
isPromise(value) {
|
|
17
|
+
return (value != null &&
|
|
18
|
+
typeof value === "object" &&
|
|
19
|
+
typeof value.then === "function");
|
|
20
|
+
},
|
|
21
|
+
checkNonNullLeaf(ctx, value, dest, nullMsg, locs, path, capStack, serialize, errHandler, ...parentIndexes) {
|
|
22
|
+
const GQLError = ctx.GraphQLError;
|
|
23
|
+
if (value == null) {
|
|
24
|
+
dest.push(new GQLError(nullMsg, locs, path, undefined, capStack));
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
if (value instanceof Error) {
|
|
28
|
+
dest.push(new GQLError(value.message ?? value, locs, path, value, capStack));
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
return serialize(ctx, value, errHandler, ...parentIndexes);
|
|
32
|
+
},
|
|
33
|
+
checkNullableLeaf(ctx, value, dest, locs, path, capStack, serialize, errHandler, ...parentIndexes) {
|
|
34
|
+
if (value == null)
|
|
35
|
+
return null;
|
|
36
|
+
const GQLError = ctx.GraphQLError;
|
|
37
|
+
if (value instanceof Error) {
|
|
38
|
+
dest.push(new GQLError(value.message ?? value, locs, path, value, capStack));
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return serialize(ctx, value, errHandler, ...parentIndexes);
|
|
42
|
+
},
|
|
43
|
+
callResolver(ctx, call, onSuccess, onError) {
|
|
44
|
+
let value;
|
|
45
|
+
try {
|
|
46
|
+
value = call();
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
onError(err);
|
|
50
|
+
onSuccess(null);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
this.handleResolverResult(ctx, value, onSuccess, onError);
|
|
54
|
+
},
|
|
55
|
+
handleResolverResult(ctx, value, onSuccess, onError) {
|
|
56
|
+
if (this.isPromise(value)) {
|
|
57
|
+
resolvePromise(ctx, value, onSuccess, onError);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
onSuccess(value);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
handleListItemResult(ctx, item, onSuccess, onError) {
|
|
64
|
+
if (this.isPromise(item)) {
|
|
65
|
+
resolvePromise(ctx, item, onSuccess, onError);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
onSuccess(item);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
finalizeResult(ctx) {
|
|
72
|
+
if (ctx.promiseCounter > 0) {
|
|
73
|
+
return new Promise((resolve) => {
|
|
74
|
+
ctx.resolve = resolve;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
},
|
|
79
|
+
safeMap(ctx, iterable, cb, ...idx) {
|
|
80
|
+
let index = 0;
|
|
81
|
+
const result = [];
|
|
82
|
+
for (const a of iterable) {
|
|
83
|
+
cb(ctx, a, index, result, ...idx);
|
|
84
|
+
++index;
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=runtime.js.map
|