@hoangvvo/graphql-jit
Advanced tools
Comparing version 0.6.4 to 0.7.2
@@ -36,2 +36,16 @@ import { ArgumentNode, ASTNode, DirectiveNode, FieldNode, GraphQLArgument, GraphQLDirective, GraphQLField, GraphQLInputType, GraphQLObjectType, SelectionSetNode, SourceLocation, ValueNode, VariableNode } from "graphql"; | ||
}; | ||
declare type ResponsePathType = "variable" | "literal" | "meta"; | ||
export interface ObjectPath { | ||
prev: ObjectPath | undefined; | ||
key: string; | ||
type: ResponsePathType; | ||
} | ||
interface MissingVariablePath { | ||
valueNode: VariableNode; | ||
path?: ObjectPath; | ||
argument?: { | ||
definition: GraphQLArgument; | ||
node: ArgumentNode; | ||
}; | ||
} | ||
export interface Arguments { | ||
@@ -52,10 +66,2 @@ values: { | ||
export declare function getArgumentDefs(def: GraphQLField<any, any> | GraphQLDirective, node: FieldNode | DirectiveNode): Arguments; | ||
interface MissingVariablePath { | ||
valueNode: VariableNode; | ||
path?: ObjectPath; | ||
argument?: { | ||
definition: GraphQLArgument; | ||
node: ArgumentNode; | ||
}; | ||
} | ||
interface ASTValueWithVariables { | ||
@@ -70,8 +76,2 @@ value: object | string | boolean | symbol | number | null | any[]; | ||
export declare function computeLocations(nodes: ASTNode[]): SourceLocation[]; | ||
export interface ObjectPath { | ||
prev: ObjectPath | undefined; | ||
key: string; | ||
type: ResponsePathType; | ||
} | ||
declare type ResponsePathType = "variable" | "literal" | "meta"; | ||
export declare function addPath(responsePath: ObjectPath | undefined, key: string, type?: ResponsePathType): ObjectPath; | ||
@@ -78,0 +78,0 @@ export declare function flattenPath(path: ObjectPath): Array<{ |
@@ -7,2 +7,3 @@ "use strict"; | ||
exports.flattenPath = exports.addPath = exports.computeLocations = exports.valueFromAST = exports.getArgumentDefs = exports.collectSubfields = exports.resolveFieldDef = exports.collectFields = void 0; | ||
const generate_function_1 = __importDefault(require("generate-function")); | ||
const graphql_1 = require("graphql"); | ||
@@ -13,5 +14,4 @@ const execute_1 = require("graphql/execution/execute"); | ||
const execution_1 = require("./execution"); | ||
const generate_function_1 = __importDefault(require("./generate-function")); | ||
const inspect_1 = __importDefault(require("./inspect")); | ||
const inspect = inspect_1.default(); | ||
const inspect = (0, inspect_1.default)(); | ||
/** | ||
@@ -71,3 +71,3 @@ * Given a selectionSet, adds all of the fields in that selection to | ||
} | ||
case language_1.Kind.INLINE_FRAGMENT: { | ||
case language_1.Kind.INLINE_FRAGMENT: | ||
if (!doesFragmentConditionMatch(compilationContext, selection, runtimeType)) { | ||
@@ -82,3 +82,2 @@ continue; | ||
break; | ||
} | ||
case language_1.Kind.FRAGMENT_SPREAD: { | ||
@@ -240,3 +239,3 @@ const fragName = selection.name.value; | ||
function compileSkipInclude(compilationContext, node) { | ||
const gen = generate_function_1.default(); | ||
const gen = (0, generate_function_1.default)(); | ||
const { skipValue, includeValue } = compileSkipIncludeDirectiveValues(compilationContext, node); | ||
@@ -311,3 +310,3 @@ /** | ||
default: | ||
throw new graphql_1.GraphQLError(`Argument 'if' on Directive '${directive.name.value}' has an invalid value (${graphql_1.valueFromASTUntyped(ifNode.value)}). Expected type 'Boolean!'`, [ifNode]); | ||
throw new graphql_1.GraphQLError(`Argument 'if' on Directive '${directive.name.value}' has an invalid value (${(0, graphql_1.valueFromASTUntyped)(ifNode.value)}). Expected type 'Boolean!'`, [ifNode]); | ||
} | ||
@@ -329,3 +328,3 @@ } | ||
throw new graphql_1.GraphQLError(`Variable '${variable.name.value}' is not defined`, [ | ||
variable, | ||
variable | ||
]); | ||
@@ -362,3 +361,3 @@ } | ||
} | ||
const conditionalType = graphql_1.typeFromAST(compilationContext.schema, typeConditionNode); | ||
const conditionalType = (0, graphql_1.typeFromAST)(compilationContext.schema, typeConditionNode); | ||
if (conditionalType === type) { | ||
@@ -370,4 +369,4 @@ return true; | ||
} | ||
if (type_1.isAbstractType(conditionalType)) { | ||
return compilationContext.schema.isPossibleType(conditionalType, type); | ||
if ((0, type_1.isAbstractType)(conditionalType)) { | ||
return compilationContext.schema.isSubType(conditionalType, type); | ||
} | ||
@@ -390,4 +389,7 @@ return false; | ||
const fieldNode = fieldNodes[0]; | ||
const fieldName = fieldNode.name.value; | ||
return execute_1.getFieldDef(compilationContext.schema, parentType, fieldName); | ||
if (graphql_1.versionInfo.major < 16) { | ||
const fieldName = fieldNode.name.value; | ||
return (0, execute_1.getFieldDef)(compilationContext.schema, parentType, fieldName); | ||
} | ||
return (0, execute_1.getFieldDef)(compilationContext.schema, parentType, fieldNode); | ||
} | ||
@@ -414,12 +416,12 @@ exports.resolveFieldDef = resolveFieldDef; | ||
let cache0; | ||
function memoized(...args) { | ||
function memoized(a1, a2, a3) { | ||
if (!cache0) { | ||
cache0 = new WeakMap(); | ||
} | ||
let cache1 = cache0.get(args[0]); | ||
let cache1 = cache0.get(a1); | ||
let cache2; | ||
if (cache1) { | ||
cache2 = cache1.get(args[1]); | ||
cache2 = cache1.get(a2); | ||
if (cache2) { | ||
const cachedValue = cache2.get(args[2]); | ||
const cachedValue = cache2.get(a3); | ||
if (cachedValue !== undefined) { | ||
@@ -432,10 +434,11 @@ return cachedValue; | ||
cache1 = new WeakMap(); | ||
cache0.set(args[0], cache1); | ||
cache0.set(a1, cache1); | ||
} | ||
if (!cache2) { | ||
cache2 = new WeakMap(); | ||
cache1.set(args[1], cache2); | ||
cache1.set(a2, cache2); | ||
} | ||
const newValue = fn(...args); | ||
cache2.set(args[2], newValue); | ||
// eslint-disable-next-line prefer-rest-params | ||
const newValue = fn(...arguments); | ||
cache2.set(a3, newValue); | ||
return newValue; | ||
@@ -473,3 +476,3 @@ } | ||
path: addPath(undefined, name, "literal"), | ||
argument: { definition: argDef, node: argumentNode }, | ||
argument: { definition: argDef, node: argumentNode } | ||
}); | ||
@@ -483,3 +486,3 @@ } | ||
// continue with an invalid argument value. | ||
throw new graphql_1.GraphQLError(`Argument "${name}" of type "${argType}" has invalid value ${graphql_1.print(argumentNode.value)}.`, argumentNode.value); | ||
throw new graphql_1.GraphQLError(`Argument "${name}" of type "${argType}" has invalid value ${(0, graphql_1.print)(argumentNode.value)}.`, argumentNode.value); | ||
} | ||
@@ -489,3 +492,3 @@ if (isASTValueWithVariables(coercedValue)) { | ||
valueNode, | ||
path: addPath(path, name, "literal"), | ||
path: addPath(path, name, "literal") | ||
}))); | ||
@@ -495,3 +498,3 @@ } | ||
} | ||
if (graphql_1.isNonNullType(argType) && values[name] === undefined && !hasVariables) { | ||
if ((0, graphql_1.isNonNullType)(argType) && values[name] === undefined && !hasVariables) { | ||
// If no value or a nullish value was provided to a variable with a | ||
@@ -513,3 +516,3 @@ // non-null type (required), produce an error. | ||
function valueFromAST(valueNode, type) { | ||
if (graphql_1.isNonNullType(type)) { | ||
if ((0, graphql_1.isNonNullType)(type)) { | ||
if (valueNode.kind === language_1.Kind.NULL) { | ||
@@ -523,3 +526,3 @@ return; // Invalid: intentionally return no value. | ||
return { | ||
value: null, | ||
value: null | ||
}; | ||
@@ -530,3 +533,3 @@ } | ||
} | ||
if (graphql_1.isListType(type)) { | ||
if ((0, graphql_1.isListType)(type)) { | ||
const itemType = type.ofType; | ||
@@ -543,3 +546,3 @@ if (valueNode.kind === language_1.Kind.LIST) { | ||
valueNode: itemNode, | ||
path: addPath(undefined, i.toString(), "literal"), | ||
path: addPath(undefined, i.toString(), "literal") | ||
}); | ||
@@ -556,3 +559,3 @@ } | ||
valueNode, | ||
path: addPath(path, i.toString(), "literal"), | ||
path: addPath(path, i.toString(), "literal") | ||
}))); | ||
@@ -574,4 +577,4 @@ } | ||
valueNode, | ||
path: addPath(path, "0", "literal"), | ||
})), | ||
path: addPath(path, "0", "literal") | ||
})) | ||
}; | ||
@@ -581,3 +584,3 @@ } | ||
} | ||
if (graphql_1.isInputObjectType(type)) { | ||
if ((0, graphql_1.isInputObjectType)(type)) { | ||
if (valueNode.kind !== language_1.Kind.OBJECT) { | ||
@@ -605,3 +608,3 @@ return; // Invalid: intentionally return no value. | ||
valueNode, | ||
path: addPath(path, field.name, "literal"), | ||
path: addPath(path, field.name, "literal") | ||
}))); | ||
@@ -613,3 +616,3 @@ } | ||
} | ||
if (graphql_1.isEnumType(type)) { | ||
if ((0, graphql_1.isEnumType)(type)) { | ||
if (valueNode.kind !== language_1.Kind.ENUM) { | ||
@@ -624,3 +627,3 @@ return; // Invalid: intentionally return no value. | ||
} | ||
if (graphql_1.isScalarType(type)) { | ||
if ((0, graphql_1.isScalarType)(type)) { | ||
// Scalars fulfill parsing a literal value via parseLiteral(). | ||
@@ -632,2 +635,3 @@ // Invalid values represent a failure to parse correctly, in which case | ||
if (type.parseLiteral.length > 1) { | ||
// eslint-disable-next-line | ||
console.error("Scalar with variable inputs detected for parsing AST literals. This is not supported."); | ||
@@ -674,3 +678,5 @@ } | ||
function keyMap(list, keyFn) { | ||
return list.reduce((map, item) => ((map[keyFn(item)] = item), map), Object.create(null)); | ||
return list.reduce( | ||
// eslint-disable-next-line no-sequences | ||
(map, item) => ((map[keyFn(item)] = item), map), Object.create(null)); | ||
} | ||
@@ -680,3 +686,3 @@ function computeLocations(nodes) { | ||
if (node.loc) { | ||
list.push(graphql_1.getLocation(node.loc.source, node.loc.start)); | ||
list.push((0, graphql_1.getLocation)(node.loc.source, node.loc.start)); | ||
} | ||
@@ -702,4 +708,5 @@ return list; | ||
function isInvalid(value) { | ||
// eslint-disable-next-line no-self-compare | ||
return value === undefined || value !== value; | ||
} | ||
//# sourceMappingURL=ast.js.map |
@@ -13,14 +13,14 @@ "use strict"; | ||
value: message, | ||
enumerable: true, | ||
enumerable: true | ||
}, | ||
locations: { | ||
value: locations || undefined, | ||
enumerable: locations && locations.length > 0, | ||
enumerable: locations && locations.length > 0 | ||
}, | ||
path: { | ||
value: path || undefined, | ||
enumerable: Boolean(path), | ||
enumerable: Boolean(path) | ||
}, | ||
originalError: { | ||
value: originalError, | ||
value: originalError | ||
}, | ||
@@ -31,4 +31,4 @@ extensions: { | ||
value: extensions || undefined, | ||
enumerable: Boolean(extensions), | ||
}, | ||
enumerable: Boolean(extensions) | ||
} | ||
}); | ||
@@ -40,3 +40,3 @@ // Include (non-enumerable) stack trace. | ||
writable: true, | ||
configurable: true, | ||
configurable: true | ||
}); | ||
@@ -52,3 +52,3 @@ } | ||
writable: true, | ||
configurable: true, | ||
configurable: true | ||
}); | ||
@@ -61,9 +61,4 @@ } | ||
constructor: { value: GraphQLError }, | ||
name: { value: "GraphQLError" }, | ||
toString: { | ||
value: function toString() { | ||
return graphql_1.printError(this); | ||
}, | ||
}, | ||
name: { value: "GraphQLError" } | ||
}); | ||
//# sourceMappingURL=error.js.map |
@@ -0,1 +1,2 @@ | ||
import { TypedDocumentNode } from "@graphql-typed-document-node/core"; | ||
import { DocumentNode, ExecutionResult, GraphQLError, GraphQLFieldResolver, GraphQLIsTypeOfFn, GraphQLObjectType, GraphQLOutputType, GraphQLSchema } from "graphql"; | ||
@@ -21,30 +22,2 @@ import { ExecutionContext as GraphQLContext } from "graphql/execution/execute"; | ||
} | ||
/** | ||
* The context used during compilation. | ||
* | ||
* It stores deferred nodes to be processed later as well as the function arguments to be bounded at top level | ||
*/ | ||
export interface CompilationContext extends GraphQLContext { | ||
resolvers: { | ||
[key: string]: GraphQLFieldResolver<any, any, any>; | ||
}; | ||
serializers: { | ||
[key: string]: (c: ExecutionContext, v: any, onError: (c: ExecutionContext, msg: string) => void) => any; | ||
}; | ||
hoistedFunctions: string[]; | ||
hoistedFunctionNames: Map<string, number>; | ||
typeResolvers: { | ||
[key: string]: GraphQLTypeResolver<any, any>; | ||
}; | ||
isTypeOfs: { | ||
[key: string]: GraphQLIsTypeOfFn<any, any>; | ||
}; | ||
resolveInfos: { | ||
[key: string]: any; | ||
}; | ||
deferred: DeferredField[]; | ||
options: CompilerOptions; | ||
depth: number; | ||
} | ||
export declare const GLOBAL_VARIABLES_NAME = "__context.variables"; | ||
interface ExecutionContext { | ||
@@ -93,10 +66,38 @@ promiseCounter: number; | ||
} | ||
export interface CompiledQuery { | ||
/** | ||
* The context used during compilation. | ||
* | ||
* It stores deferred nodes to be processed later as well as the function arguments to be bounded at top level | ||
*/ | ||
export interface CompilationContext extends GraphQLContext { | ||
resolvers: { | ||
[key: string]: GraphQLFieldResolver<any, any, any>; | ||
}; | ||
serializers: { | ||
[key: string]: (c: ExecutionContext, v: any, onError: (c: ExecutionContext, msg: string) => void) => any; | ||
}; | ||
hoistedFunctions: string[]; | ||
hoistedFunctionNames: Map<string, number>; | ||
typeResolvers: { | ||
[key: string]: GraphQLTypeResolver<any, any>; | ||
}; | ||
isTypeOfs: { | ||
[key: string]: GraphQLIsTypeOfFn<any, any>; | ||
}; | ||
resolveInfos: { | ||
[key: string]: any; | ||
}; | ||
deferred: DeferredField[]; | ||
options: CompilerOptions; | ||
depth: number; | ||
} | ||
export declare const GLOBAL_VARIABLES_NAME = "__context.variables"; | ||
export interface CompiledQuery<TResult = { | ||
[key: string]: any; | ||
}, TVariables = { | ||
[key: string]: any; | ||
}> { | ||
operationName?: string; | ||
query: (root: any, context: any, variables: Maybe<{ | ||
[key: string]: any; | ||
}>) => Promise<ExecutionResult> | ExecutionResult; | ||
subscribe?: (root: any, context: any, variables: Maybe<{ | ||
[key: string]: any; | ||
}>) => Promise<AsyncIterableIterator<ExecutionResult> | ExecutionResult>; | ||
query: (root: any, context: any, variables: Maybe<TVariables>) => Promise<ExecutionResult<TResult>> | ExecutionResult<TResult>; | ||
subscribe?: (root: any, context: any, variables: Maybe<TVariables>) => Promise<AsyncIterableIterator<ExecutionResult<TResult>> | ExecutionResult<TResult>>; | ||
stringify: (v: any) => string; | ||
@@ -112,3 +113,7 @@ } | ||
*/ | ||
export declare function compileQuery(schema: GraphQLSchema, document: DocumentNode, operationName?: string, partialOptions?: Partial<CompilerOptions>): CompiledQuery | ExecutionResult; | ||
export declare function compileQuery<TResult = { | ||
[key: string]: any; | ||
}, TVariables = { | ||
[key: string]: any; | ||
}>(schema: GraphQLSchema, document: TypedDocumentNode<TResult, TVariables>, operationName?: string, partialOptions?: Partial<CompilerOptions>): CompiledQuery<TResult, TVariables> | ExecutionResult<TResult>; | ||
export declare function isCompiledQuery<C extends CompiledQuery, E extends ExecutionResult>(query: C | E): query is C; | ||
@@ -115,0 +120,0 @@ export declare function createBoundQuery(compilationContext: CompilationContext, document: DocumentNode, func: (context: ExecutionContext) => Promise<any> | undefined, getVariableValues: (inputs: { |
@@ -7,2 +7,3 @@ "use strict"; | ||
exports.isAsyncIterable = exports.isPromiseInliner = exports.isPromise = exports.createBoundQuery = exports.isCompiledQuery = exports.compileQuery = exports.GLOBAL_VARIABLES_NAME = void 0; | ||
const generate_function_1 = __importDefault(require("generate-function")); | ||
const graphql_1 = require("graphql"); | ||
@@ -12,3 +13,2 @@ const Path_1 = require("graphql/jsutils/Path"); | ||
const error_1 = require("./error"); | ||
const generate_function_1 = __importDefault(require("./generate-function")); | ||
const inspect_1 = __importDefault(require("./inspect")); | ||
@@ -18,3 +18,3 @@ const non_null_1 = require("./non-null"); | ||
const variables_1 = require("./variables"); | ||
const inspect = inspect_1.default(); | ||
const inspect = (0, inspect_1.default)(); | ||
// prefix for the variable used ot cache validation results | ||
@@ -68,11 +68,13 @@ const SAFETY_CHECK_PREFIX = "__validNode"; | ||
} | ||
const getVariables = variables_1.compileVariableParsing(schema, context.operation.variableDefinitions || []); | ||
const type = graphql_1.getOperationRootType(context.schema, context.operation); | ||
const fieldMap = ast_1.collectFields(context, type, context.operation.selectionSet, Object.create(null), Object.create(null)); | ||
const getVariables = (0, variables_1.compileVariableParsing)(schema, context.operation.variableDefinitions || []); | ||
const type = (0, graphql_1.getOperationRootType)(context.schema, context.operation); | ||
const fieldMap = (0, ast_1.collectFields)(context, type, context.operation.selectionSet, Object.create(null), Object.create(null)); | ||
const functionBody = compileOperation(context, type, fieldMap); | ||
const compiledQuery = { | ||
query: createBoundQuery(context, document, new Function("return " + functionBody)(), getVariables, context.operation.name != null | ||
query: createBoundQuery(context, document, | ||
// eslint-disable-next-line no-new-func | ||
new Function("return " + functionBody)(), getVariables, context.operation.name != null | ||
? context.operation.name.value | ||
: undefined), | ||
stringify, | ||
stringify | ||
}; | ||
@@ -87,5 +89,5 @@ if (context.operation.operation === "subscription") { | ||
// and visualization tools like try-jit. | ||
compiledQuery.__DO_NOT_USE_THIS_OR_YOU_WILL_BE_FIRED_compilation = functionBody; | ||
compiledQuery.__DO_NOT_USE_THIS_OR_YOU_WILL_BE_FIRED_compilation = | ||
functionBody; | ||
} | ||
/* istanbul ignore stop */ | ||
return compiledQuery; | ||
@@ -95,3 +97,3 @@ } | ||
return { | ||
errors: normalizeErrors(err), | ||
errors: normalizeErrors(err) | ||
}; | ||
@@ -107,5 +109,6 @@ } | ||
function createBoundQuery(compilationContext, document, func, getVariableValues, operationName) { | ||
const { resolvers, typeResolvers, isTypeOfs, serializers, resolveInfos, } = compilationContext; | ||
const trimmer = non_null_1.createNullTrimmer(compilationContext); | ||
const fnName = operationName ? operationName : "query"; | ||
const { resolvers, typeResolvers, isTypeOfs, serializers, resolveInfos } = compilationContext; | ||
const trimmer = (0, non_null_1.createNullTrimmer)(compilationContext); | ||
const fnName = operationName || "query"; | ||
/* eslint-disable */ | ||
/** | ||
@@ -121,2 +124,3 @@ * In-order to assign a debuggable name to the bound query function, | ||
*/ | ||
/* eslint-enable */ | ||
const ret = { | ||
@@ -127,3 +131,3 @@ [fnName](rootValue, context, variables) { | ||
// Return early errors if variable coercing failed. | ||
if (variables_1.failToParseVariables(parsedVariables)) { | ||
if ((0, variables_1.failToParseVariables)(parsedVariables)) { | ||
return { errors: parsedVariables.errors }; | ||
@@ -147,4 +151,5 @@ } | ||
nullErrors: [], | ||
errors: [], | ||
errors: [] | ||
}; | ||
// eslint-disable-next-line no-useless-call | ||
const result = func.call(null, executionContext); | ||
@@ -155,3 +160,3 @@ if (isPromise(result)) { | ||
return postProcessResult(executionContext); | ||
}, | ||
} | ||
}; | ||
@@ -161,3 +166,3 @@ return ret[fnName]; | ||
exports.createBoundQuery = createBoundQuery; | ||
function postProcessResult({ data, nullErrors, errors, trimmer, }) { | ||
function postProcessResult({ data, nullErrors, errors, trimmer }) { | ||
if (nullErrors.length > 0) { | ||
@@ -167,3 +172,3 @@ const trimmed = trimmer(data, nullErrors); | ||
data: trimmed.data, | ||
errors: errors.concat(trimmed.errors), | ||
errors: errors.concat(trimmed.errors) | ||
}; | ||
@@ -174,3 +179,3 @@ } | ||
data, | ||
errors, | ||
errors | ||
}; | ||
@@ -261,3 +266,3 @@ } | ||
function compileDeferredField(context, deferredField, appendix) { | ||
const { name, originPaths, destinationPaths, fieldNodes, fieldType, fieldName, jsFieldName, responsePath, parentType, args, } = deferredField; | ||
const { name, originPaths, destinationPaths, fieldNodes, fieldType, fieldName, jsFieldName, responsePath, parentType, args } = deferredField; | ||
const subContext = createSubCompilationContext(context); | ||
@@ -309,3 +314,3 @@ const nodeBody = compileType(subContext, parentType, fieldType, fieldNodes, [jsFieldName], [`${GLOBAL_PARENT_NAME}.${name}`], responsePath); | ||
${compileDeferredFields(subContext)} | ||
${appendix ? appendix : ""} | ||
${appendix || ""} | ||
} | ||
@@ -352,3 +357,3 @@ `); | ||
let errorDestination; | ||
if (graphql_1.isNonNullType(type)) { | ||
if ((0, graphql_1.isNonNullType)(type)) { | ||
type = type.ofType; | ||
@@ -367,13 +372,13 @@ const nullErrorStr = `"Cannot return null for non-nullable field ${parentType.name}.${getFieldNodesName(fieldNodes)}."`; | ||
body += `${sourcePath} instanceof Error ? (${errorDestination}.push(${createErrorObject(context, fieldNodes, previousPath, errorPath, sourcePath)}), null) : `; | ||
if (graphql_1.isLeafType(type)) { | ||
if ((0, graphql_1.isLeafType)(type)) { | ||
body += compileLeafType(context, type, originPaths, fieldNodes, previousPath, errorDestination); | ||
} | ||
else if (graphql_1.isObjectType(type)) { | ||
const fieldMap = ast_1.collectSubfields(context, type, fieldNodes); | ||
else if ((0, graphql_1.isObjectType)(type)) { | ||
const fieldMap = (0, ast_1.collectSubfields)(context, type, fieldNodes); | ||
body += compileObjectType(context, type, fieldNodes, originPaths, destinationPaths, previousPath, errorDestination, fieldMap, false); | ||
} | ||
else if (graphql_1.isAbstractType(type)) { | ||
else if ((0, graphql_1.isAbstractType)(type)) { | ||
body += compileAbstractType(context, parentType, type, fieldNodes, originPaths, previousPath, errorDestination); | ||
} | ||
else if (graphql_1.isListType(type)) { | ||
else if ((0, graphql_1.isListType)(type)) { | ||
body += compileListType(context, parentType, type, fieldNodes, originPaths, previousPath, errorDestination); | ||
@@ -391,3 +396,3 @@ } | ||
if (context.options.disableLeafSerialization && | ||
(type instanceof graphql_1.GraphQLEnumType || graphql_1.isSpecifiedScalarType(type))) { | ||
(type instanceof graphql_1.GraphQLEnumType || (0, graphql_1.isSpecifiedScalarType)(type))) { | ||
body += `${originPaths.join(".")}`; | ||
@@ -422,3 +427,3 @@ } | ||
function compileObjectType(context, type, fieldNodes, originPaths, destinationPaths, responsePath, errorDestination, fieldMap, alwaysDefer) { | ||
const body = generate_function_1.default(); | ||
const body = (0, generate_function_1.default)(); | ||
// Begin object compilation paren | ||
@@ -434,3 +439,3 @@ body("("); | ||
const fieldNodes = fieldMap[name]; | ||
const field = ast_1.resolveFieldDef(context, type, fieldNodes); | ||
const field = (0, ast_1.resolveFieldDef)(context, type, fieldNodes); | ||
if (!field) { | ||
@@ -491,3 +496,3 @@ // Field is invalid, should have been caught in validation | ||
name, | ||
responsePath: ast_1.addPath(responsePath, name), | ||
responsePath: (0, ast_1.addPath)(responsePath, name), | ||
originPaths, | ||
@@ -500,3 +505,3 @@ destinationPaths, | ||
fieldNodes, | ||
args: ast_1.getArgumentDefs(field, fieldNodes[0]), | ||
args: (0, ast_1.getArgumentDefs)(field, fieldNodes[0]) | ||
}); | ||
@@ -518,3 +523,3 @@ context.resolvers[getResolverName(type.name, field.name)] = resolver; | ||
body("?"); | ||
body(compileType(context, type, field.type, fieldNodes, originPaths.concat(field.name), destinationPaths.concat(name), ast_1.addPath(responsePath, name))); | ||
body(compileType(context, type, field.type, fieldNodes, originPaths.concat(field.name), destinationPaths.concat(name), (0, ast_1.addPath)(responsePath, name))); | ||
// if not included | ||
@@ -546,3 +551,3 @@ body(": undefined"); | ||
const subContext = createSubCompilationContext(context); | ||
const object = compileType(subContext, parentType, objectType, fieldNodes, originPaths, ["__concrete"], ast_1.addPath(previousPath, objectType.name, "meta")); | ||
const object = compileType(subContext, parentType, objectType, fieldNodes, originPaths, ["__concrete"], (0, ast_1.addPath)(previousPath, objectType.name, "meta")); | ||
return `case "${objectType.name}": { | ||
@@ -558,6 +563,10 @@ ${generateUniqueDeclarations(subContext)} | ||
const nullTypeError = `"Runtime Object type is not a possible type for \\"${type.name}\\"."`; | ||
const notPossibleTypeError = '`Runtime Object type "${nodeType}" is not a possible type for "' + | ||
/* eslint-disable max-len */ | ||
const notPossibleTypeError = | ||
// eslint-disable-next-line no-template-curly-in-string | ||
'`Runtime Object type "${nodeType}" is not a possible type for "' + | ||
type.name + | ||
'".`'; | ||
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."`; | ||
/* eslint-enable max-len */ | ||
return `((nodeType, err) => | ||
@@ -603,6 +612,6 @@ { | ||
const fieldType = type.ofType; | ||
const dataBody = compileType(listContext, parentType, fieldType, fieldNodes, ["__currentItem"], [`${GLOBAL_PARENT_NAME}[idx${newDepth}]`], ast_1.addPath(responsePath, "idx" + newDepth, "variable")); | ||
const dataBody = compileType(listContext, parentType, fieldType, fieldNodes, ["__currentItem"], [`${GLOBAL_PARENT_NAME}[idx${newDepth}]`], (0, ast_1.addPath)(responsePath, "idx" + newDepth, "variable")); | ||
const errorMessage = `"Expected Iterable, but did not find one for field ${parentType.name}.${getFieldNodesName(fieldNodes)}."`; | ||
const errorCase = `(${errorDestination}.push(${createErrorObject(context, fieldNodes, responsePath, errorMessage)}), null)`; | ||
const executionError = createErrorObject(context, fieldNodes, ast_1.addPath(responsePath, "idx" + newDepth, "variable"), "err.message != null ? err.message : err", "err"); | ||
const executionError = createErrorObject(context, fieldNodes, (0, ast_1.addPath)(responsePath, "idx" + newDepth, "variable"), "err.message != null ? err.message : err", "err"); | ||
const emptyError = createErrorObject(context, fieldNodes, responsePath, '""'); | ||
@@ -701,3 +710,3 @@ const uniqueDeclarations = generateUniqueDeclarations(listContext); | ||
const { schema, fragments, operation } = context; | ||
context.resolveInfos[resolveInfoName] = resolve_info_1.createResolveInfoThunk({ | ||
context.resolveInfos[resolveInfoName] = (0, resolve_info_1.createResolveInfoThunk)({ | ||
schema, | ||
@@ -709,3 +718,3 @@ fragments, | ||
fieldType, | ||
fieldNodes, | ||
fieldNodes | ||
}, context.options.resolverInfoEnricher); | ||
@@ -725,3 +734,3 @@ return `${GLOBAL_EXECUTION_CONTEXT}.resolveInfos.${resolveInfoName}(${GLOBAL_ROOT_NAME}, ${exports.GLOBAL_VARIABLES_NAME}, ${serializeResponsePath(responsePath)})`; | ||
let objectPath = topLevel; | ||
const flattened = ast_1.flattenPath(path); | ||
const flattened = (0, ast_1.flattenPath)(path); | ||
for (const section of flattened) { | ||
@@ -758,4 +767,4 @@ if (section.type === "literal") { | ||
body += `if (Object.prototype.hasOwnProperty.call(${exports.GLOBAL_VARIABLES_NAME}, "${varName}")) {`; | ||
if (variable.argument && graphql_1.isNonNullType(variable.argument.definition.type)) { | ||
const message = `'Argument "${variable.argument.definition.name}" of non-null type "${inspect(variable.argument.definition.type)}" must not be null.'`; | ||
if (variable.argument && (0, graphql_1.isNonNullType)(variable.argument.definition.type)) { | ||
const message = `'Argument "${variable.argument.definition.name}" of non-null type "${variable.argument.definition.type.toString()}" must not be null.'`; | ||
body += `if (${exports.GLOBAL_VARIABLES_NAME}['${variable.valueNode.name.value}'] == null) { | ||
@@ -772,5 +781,5 @@ ${errorDestination}.push(${createErrorObject(context, [variable.argument.node.value], path, message)}); | ||
if (variable.argument && | ||
graphql_1.isNonNullType(variable.argument.definition.type) && | ||
(0, graphql_1.isNonNullType)(variable.argument.definition.type) && | ||
variable.argument.definition.defaultValue === undefined) { | ||
const message = `'Argument "${variable.argument.definition.name}" of required type "${inspect(variable.argument.definition.type)}" was provided the variable "$${varName}" which was not provided a runtime value.'`; | ||
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.'`; | ||
body += ` else { | ||
@@ -821,3 +830,3 @@ ${errorDestination}.push(${createErrorObject(context, [variable.argument.node.value], path, message)}); | ||
function serializeResponsePathAsArray(path) { | ||
const flattened = ast_1.flattenPath(path); | ||
const flattened = (0, ast_1.flattenPath)(path); | ||
let src = "["; | ||
@@ -837,6 +846,6 @@ for (let i = flattened.length - 1; i >= 0; i--) { | ||
function getErrorDestination(type) { | ||
return graphql_1.isNonNullType(type) ? GLOBAL_NULL_ERRORS_NAME : GLOBAL_ERRORS_NAME; | ||
return (0, graphql_1.isNonNullType)(type) ? GLOBAL_NULL_ERRORS_NAME : GLOBAL_ERRORS_NAME; | ||
} | ||
function createResolveInfoName(path) { | ||
return (ast_1.flattenPath(path) | ||
return ((0, ast_1.flattenPath)(path) | ||
.map((p) => p.key) | ||
@@ -872,5 +881,3 @@ .join("_") + "Info"); | ||
const { name } = scalar; | ||
const serialize = customSerializer | ||
? customSerializer | ||
: (val) => scalar.serialize(val); | ||
const serialize = customSerializer || ((val) => scalar.serialize(val)); | ||
return function leafSerializer(context, v, onError, ...idx) { | ||
@@ -900,3 +907,3 @@ try { | ||
* @param {GraphQLAbstractType} abstractType | ||
* @returns {string | GraphQLObjectType} | ||
* @returns {string} | ||
*/ | ||
@@ -919,3 +926,3 @@ function defaultResolveTypeFn(value, contextValue, info, abstractType) { | ||
else if (isTypeOfResult) { | ||
return type; | ||
return type.name; | ||
} | ||
@@ -981,4 +988,3 @@ } | ||
variableValues: {}, | ||
fieldResolver: undefined, | ||
errors: errors, | ||
errors | ||
}; | ||
@@ -1002,5 +1008,5 @@ } | ||
return `new ${GRAPHQL_ERROR}(${message}, | ||
${JSON.stringify(ast_1.computeLocations(nodes))}, | ||
${JSON.stringify((0, ast_1.computeLocations)(nodes))}, | ||
${serializeResponsePathAsArray(path)}, | ||
${originalError ? originalError : "undefined"}, | ||
${originalError || "undefined"}, | ||
${context.options.disablingCapturingStackErrors ? "true" : "false"})`; | ||
@@ -1046,2 +1052,3 @@ } | ||
function isInvalid(value) { | ||
// eslint-disable-next-line no-self-compare | ||
return value === undefined || value !== value; | ||
@@ -1070,7 +1077,7 @@ } | ||
const fieldName = fieldNode.name.value; | ||
const field = ast_1.resolveFieldDef(context, type, fieldNodes); | ||
const field = (0, ast_1.resolveFieldDef)(context, type, fieldNodes); | ||
if (!field) { | ||
throw new graphql_1.GraphQLError(`The subscription field "${fieldName}" is not defined.`, fieldNodes); | ||
} | ||
const responsePath = ast_1.addPath(undefined, fieldName); | ||
const responsePath = (0, ast_1.addPath)(undefined, fieldName); | ||
const resolveInfoName = createResolveInfoName(responsePath); | ||
@@ -1081,3 +1088,3 @@ const subscriber = field.subscribe; | ||
try { | ||
const eventStream = await subscriber(executionContext.rootValue, executionContext.variables, executionContext.context, resolveInfo); | ||
const eventStream = await (subscriber === null || subscriber === void 0 ? void 0 : subscriber(executionContext.rootValue, executionContext.variables, executionContext.context, resolveInfo)); | ||
if (eventStream instanceof Error) { | ||
@@ -1089,3 +1096,3 @@ throw eventStream; | ||
catch (error) { | ||
throw graphql_1.locatedError(error, resolveInfo.fieldNodes, Path_1.pathToArray(resolveInfo.path)); | ||
throw (0, graphql_1.locatedError)(error, resolveInfo.fieldNodes, (0, Path_1.pathToArray)(resolveInfo.path)); | ||
} | ||
@@ -1129,5 +1136,5 @@ } | ||
function createBoundSubscribe(compilationContext, document, func, getVariableValues, operationName) { | ||
const { resolvers, typeResolvers, isTypeOfs, serializers, resolveInfos, } = compilationContext; | ||
const trimmer = non_null_1.createNullTrimmer(compilationContext); | ||
const fnName = operationName ? operationName : "subscribe"; | ||
const { resolvers, typeResolvers, isTypeOfs, serializers, resolveInfos } = compilationContext; | ||
const trimmer = (0, non_null_1.createNullTrimmer)(compilationContext); | ||
const fnName = operationName || "subscribe"; | ||
const ret = { | ||
@@ -1138,3 +1145,3 @@ async [fnName](rootValue, context, variables) { | ||
// Return early errors if variable coercing failed. | ||
if (variables_1.failToParseVariables(parsedVariables)) { | ||
if ((0, variables_1.failToParseVariables)(parsedVariables)) { | ||
return { errors: parsedVariables.errors }; | ||
@@ -1158,6 +1165,7 @@ } | ||
errors: [], | ||
data: {}, | ||
data: {} | ||
}; | ||
// eslint-disable-next-line no-useless-call | ||
return func.call(null, executionContext); | ||
}, | ||
} | ||
}; | ||
@@ -1207,5 +1215,5 @@ return ret[fnName]; | ||
return this; | ||
}, | ||
} | ||
}; | ||
} | ||
//# sourceMappingURL=execution.js.map |
@@ -1,2 +0,2 @@ | ||
export { compileQuery, isCompiledQuery, CompilerOptions, CompiledQuery, } from "./execution"; | ||
export { GraphQLJitResolveInfo, FieldExpansion, LeafField, TypeExpansion, fieldExpansionEnricher, isLeafField, } from "./resolve-info"; | ||
export { compileQuery, isCompiledQuery, CompilerOptions, CompiledQuery } from "./execution"; | ||
export { GraphQLJitResolveInfo, FieldExpansion, LeafField, TypeExpansion, fieldExpansionEnricher, isLeafField } from "./resolve-info"; |
@@ -18,13 +18,13 @@ "use strict"; | ||
function memoize2(fn) { | ||
return uncurry2(lodash_memoize_1.default((a) => lodash_memoize_1.default((b) => fn(a, b)))); | ||
return uncurry2((0, lodash_memoize_1.default)((a) => (0, lodash_memoize_1.default)((b) => fn(a, b)))); | ||
} | ||
exports.memoize2 = memoize2; | ||
function memoize3(fn) { | ||
return uncurry3(lodash_memoize_1.default((a) => lodash_memoize_1.default((b) => lodash_memoize_1.default((c) => fn(a, b, c))))); | ||
return uncurry3((0, lodash_memoize_1.default)((a) => (0, lodash_memoize_1.default)((b) => (0, lodash_memoize_1.default)((c) => fn(a, b, c))))); | ||
} | ||
exports.memoize3 = memoize3; | ||
function memoize4(fn) { | ||
return uncurry4(lodash_memoize_1.default((a) => lodash_memoize_1.default((b) => lodash_memoize_1.default((c) => lodash_memoize_1.default((d) => fn(a, b, c, d)))))); | ||
return uncurry4((0, lodash_memoize_1.default)((a) => (0, lodash_memoize_1.default)((b) => (0, lodash_memoize_1.default)((c) => (0, lodash_memoize_1.default)((d) => fn(a, b, c, d)))))); | ||
} | ||
exports.memoize4 = memoize4; | ||
//# sourceMappingURL=memoize.js.map |
@@ -9,5 +9,4 @@ "use strict"; | ||
const type_1 = require("graphql/type"); | ||
const lodash_merge_1 = __importDefault(require("lodash.merge")); | ||
const ast_1 = require("./ast"); | ||
// @ts-ignore | ||
const deepmerge5_1 = __importDefault(require("./deepmerge5")); | ||
/** | ||
@@ -116,7 +115,7 @@ * | ||
function parseQueryNullables(compilationContext) { | ||
const type = graphql_1.getOperationRootType(compilationContext.schema, compilationContext.operation); | ||
const fields = ast_1.collectFields(compilationContext, type, compilationContext.operation.selectionSet, Object.create(null), Object.create(null)); | ||
const type = (0, graphql_1.getOperationRootType)(compilationContext.schema, compilationContext.operation); | ||
const fields = (0, ast_1.collectFields)(compilationContext, type, compilationContext.operation.selectionSet, Object.create(null), Object.create(null)); | ||
const properties = Object.create(null); | ||
for (const responseName of Object.keys(fields)) { | ||
const fieldType = ast_1.resolveFieldDef(compilationContext, type, fields[responseName]); | ||
const fieldType = (0, ast_1.resolveFieldDef)(compilationContext, type, fields[responseName]); | ||
if (!fieldType) { | ||
@@ -134,3 +133,3 @@ // if field does not exist, it should be ignored for compatibility concerns. | ||
isNullable: true, | ||
children: properties, | ||
children: properties | ||
}; | ||
@@ -148,3 +147,3 @@ } | ||
function transformNode(compilationContext, fieldNodes, type) { | ||
if (graphql_1.isNonNullType(type)) { | ||
if ((0, graphql_1.isNonNullType)(type)) { | ||
const nullable = transformNode(compilationContext, fieldNodes, type.ofType); | ||
@@ -157,7 +156,7 @@ if (nullable != null) { | ||
} | ||
if (graphql_1.isObjectType(type)) { | ||
const subfields = ast_1.collectSubfields(compilationContext, type, fieldNodes); | ||
if ((0, graphql_1.isObjectType)(type)) { | ||
const subfields = (0, ast_1.collectSubfields)(compilationContext, type, fieldNodes); | ||
const properties = Object.create(null); | ||
for (const responseName of Object.keys(subfields)) { | ||
const fieldType = ast_1.resolveFieldDef(compilationContext, type, subfields[responseName]); | ||
const fieldType = (0, ast_1.resolveFieldDef)(compilationContext, type, subfields[responseName]); | ||
if (!fieldType) { | ||
@@ -175,6 +174,6 @@ // if field does not exist, it should be ignored for compatibility concerns. | ||
isNullable: true, | ||
children: properties, | ||
children: properties | ||
}; | ||
} | ||
if (graphql_1.isListType(type)) { | ||
if ((0, graphql_1.isListType)(type)) { | ||
const child = transformNode(compilationContext, fieldNodes, type.ofType); | ||
@@ -184,3 +183,3 @@ if (child != null) { | ||
isNullable: true, | ||
children: { [ARRAY_CHILD_NAME]: child }, | ||
children: { [ARRAY_CHILD_NAME]: child } | ||
}; | ||
@@ -190,6 +189,6 @@ } | ||
isNullable: true, | ||
children: {}, | ||
children: {} | ||
}; | ||
} | ||
if (type_1.isAbstractType(type)) { | ||
if ((0, type_1.isAbstractType)(type)) { | ||
return compilationContext.schema.getPossibleTypes(type).reduce((res, t) => { | ||
@@ -200,3 +199,3 @@ const property = transformNode(compilationContext, fieldNodes, t); | ||
// TODO: Possible bug: two object with different nullability on objects. | ||
res.children = deepmerge5_1.default(res.children, property.children); | ||
res.children = (0, lodash_merge_1.default)(res.children, property.children); | ||
} | ||
@@ -206,3 +205,3 @@ return res; | ||
isNullable: true, | ||
children: {}, | ||
children: {} | ||
}); | ||
@@ -209,0 +208,0 @@ } |
@@ -15,5 +15,2 @@ import { FieldNode, GraphQLObjectType, GraphQLOutputType, GraphQLResolveInfo } from "graphql"; | ||
} | ||
export interface TypeExpansion { | ||
[fieldName: string]: FieldExpansion | LeafField; | ||
} | ||
declare const LeafFieldSymbol: unique symbol; | ||
@@ -23,2 +20,5 @@ export interface LeafField { | ||
} | ||
export interface TypeExpansion { | ||
[fieldName: string]: FieldExpansion | LeafField; | ||
} | ||
export declare function isLeafField(obj: LeafField | FieldExpansion): obj is LeafField; | ||
@@ -30,3 +30,3 @@ /** | ||
*/ | ||
export declare function createResolveInfoThunk<T>({ schema, fragments, operation, parentType, fieldName, fieldType, fieldNodes, }: { | ||
export declare function createResolveInfoThunk<T>({ schema, fragments, operation, parentType, fieldName, fieldType, fieldNodes }: { | ||
schema: GraphQLResolveInfo["schema"]; | ||
@@ -33,0 +33,0 @@ fragments: GraphQLResolveInfo["fragments"]; |
@@ -7,7 +7,6 @@ "use strict"; | ||
exports.fieldExpansionEnricher = exports.createResolveInfoThunk = exports.isLeafField = void 0; | ||
const generate_function_1 = __importDefault(require("generate-function")); | ||
const graphql_1 = require("graphql"); | ||
const lodash_memoize_1 = __importDefault(require("lodash.memoize")); | ||
// @ts-ignore | ||
const deepmerge5_1 = __importDefault(require("./deepmerge5")); | ||
const generate_function_1 = __importDefault(require("./generate-function")); | ||
const lodash_mergewith_1 = __importDefault(require("lodash.mergewith")); | ||
const memoize_1 = require("./memoize"); | ||
@@ -27,3 +26,3 @@ const LeafFieldSymbol = Symbol("LeafFieldSymbol"); | ||
*/ | ||
function createResolveInfoThunk({ schema, fragments, operation, parentType, fieldName, fieldType, fieldNodes, }, enricher) { | ||
function createResolveInfoThunk({ schema, fragments, operation, parentType, fieldName, fieldType, fieldNodes }, enricher) { | ||
let enrichedInfo = {}; | ||
@@ -39,3 +38,3 @@ if (typeof enricher === "function") { | ||
fragments, | ||
operation, | ||
operation | ||
}) || {}; | ||
@@ -46,3 +45,3 @@ if (typeof enrichedInfo !== "object" || Array.isArray(enrichedInfo)) { | ||
} | ||
const gen = generate_function_1.default(); | ||
const gen = (0, generate_function_1.default)(); | ||
gen(`return function getGraphQLResolveInfo(rootValue, variableValues, path) { | ||
@@ -64,2 +63,3 @@ return { | ||
gen(`};};`); | ||
// eslint-disable-next-line | ||
return new Function("fieldName", "fieldNodes", "fieldType", "parentType", "schema", "fragments", "operation", "enrichedInfo", gen.toString()).call(null, fieldName, fieldNodes, fieldType, parentType, schema, fragments, operation, enrichedInfo); | ||
@@ -75,12 +75,12 @@ } | ||
return { | ||
fieldExpansion, | ||
fieldExpansion | ||
}; | ||
} | ||
exports.fieldExpansionEnricher = fieldExpansionEnricher; | ||
const memoizedGetReturnType = memoize_1.memoize2(getReturnType); | ||
const memoizedHasField = memoize_1.memoize2(hasField); | ||
const memoizedResolveEndType = lodash_memoize_1.default(resolveEndType); | ||
const memoizedGetPossibleTypes = memoize_1.memoize2(getPossibleTypes); | ||
const memoizedExpandFieldNodeType = memoize_1.memoize4(expandFieldNodeType); | ||
const memoizedExpandFieldNode = memoize_1.memoize4(expandFieldNode); | ||
const memoizedGetReturnType = (0, memoize_1.memoize2)(getReturnType); | ||
const memoizedHasField = (0, memoize_1.memoize2)(hasField); | ||
const memoizedResolveEndType = (0, lodash_memoize_1.default)(resolveEndType); | ||
const memoizedGetPossibleTypes = (0, memoize_1.memoize2)(getPossibleTypes); | ||
const memoizedExpandFieldNodeType = (0, memoize_1.memoize4)(expandFieldNodeType); | ||
const memoizedExpandFieldNode = (0, memoize_1.memoize4)(expandFieldNode); | ||
function expandFieldNode(schema, fragments, node, fieldType) { | ||
@@ -95,3 +95,3 @@ if (node.selectionSet == null) { | ||
for (const possibleType of possibleTypes) { | ||
if (!graphql_1.isUnionType(possibleType)) { | ||
if (!(0, graphql_1.isUnionType)(possibleType)) { | ||
fieldExpansion[possibleType.name] = memoizedExpandFieldNodeType(schema, fragments, possibleType, node.selectionSet); | ||
@@ -106,3 +106,3 @@ } | ||
if (selection.kind === "Field") { | ||
if (!graphql_1.isUnionType(parentType) && | ||
if (!(0, graphql_1.isUnionType)(parentType) && | ||
memoizedHasField(parentType, selection.name.value)) { | ||
@@ -148,3 +148,3 @@ typeExpansion[selection.name.value] = memoizedExpandFieldNode(schema, fragments, selection, memoizedGetReturnType(parentType, selection.name.value)); | ||
function getPossibleTypes(schema, compositeType) { | ||
if (graphql_1.isObjectType(compositeType)) { | ||
if ((0, graphql_1.isObjectType)(compositeType)) { | ||
return [compositeType]; | ||
@@ -157,3 +157,3 @@ } | ||
const typ = types[typeName]; | ||
if (graphql_1.isCompositeType(typ) && graphql_1.doTypesOverlap(schema, typ, compositeType)) { | ||
if ((0, graphql_1.isCompositeType)(typ) && (0, graphql_1.doTypesOverlap)(schema, typ, compositeType)) { | ||
possibleTypes.push(typ); | ||
@@ -184,3 +184,3 @@ } | ||
function resolveEndType(typ) { | ||
if (graphql_1.isListType(typ) || graphql_1.isNonNullType(typ)) { | ||
if ((0, graphql_1.isListType)(typ) || (0, graphql_1.isNonNullType)(typ)) { | ||
return memoizedResolveEndType(typ.ofType); | ||
@@ -196,7 +196,15 @@ } | ||
function deepMerge(obj, src) { | ||
return deepmerge5_1.default(obj, src, { | ||
isMergeableObject: isLeafField, | ||
clone: false, | ||
(0, lodash_mergewith_1.default)(obj, src, (objValue, srcValue) => { | ||
if (isLeafField(objValue)) { | ||
if (isLeafField(srcValue)) { | ||
return Object.assign(Object.assign({}, objValue), srcValue); | ||
} | ||
return objValue; | ||
} | ||
else if (isLeafField(srcValue)) { | ||
return srcValue; | ||
} | ||
return undefined; | ||
}); | ||
} | ||
//# sourceMappingURL=resolve-info.js.map |
import { GraphQLError, GraphQLSchema, VariableDefinitionNode } from "graphql"; | ||
export declare type CoercedVariableValues = FailedVariableCoercion | VariableValues; | ||
interface FailedVariableCoercion { | ||
@@ -11,2 +10,3 @@ errors: ReadonlyArray<GraphQLError>; | ||
} | ||
export declare type CoercedVariableValues = FailedVariableCoercion | VariableValues; | ||
export declare function failToParseVariables(x: any): x is FailedVariableCoercion; | ||
@@ -13,0 +13,0 @@ export declare function compileVariableParsing(schema: GraphQLSchema, varDefNodes: ReadonlyArray<VariableDefinitionNode>): (inputs: { |
@@ -7,8 +7,8 @@ "use strict"; | ||
exports.compileVariableParsing = exports.failToParseVariables = void 0; | ||
const generate_function_1 = __importDefault(require("generate-function")); | ||
const graphql_1 = require("graphql"); | ||
const ast_1 = require("./ast"); | ||
const error_1 = require("./error"); | ||
const generate_function_1 = __importDefault(require("./generate-function")); | ||
const inspect_1 = __importDefault(require("./inspect")); | ||
const inspect = inspect_1.default(); | ||
const inspect = (0, inspect_1.default)(); | ||
function failToParseVariables(x) { | ||
@@ -30,25 +30,22 @@ return x.errors; | ||
depth: 0, | ||
inputPath: ast_1.addPath(undefined, "input"), | ||
responsePath: ast_1.addPath(undefined, "coerced"), | ||
dependencies, | ||
inputPath: (0, ast_1.addPath)(undefined, "input"), | ||
responsePath: (0, ast_1.addPath)(undefined, "coerced"), | ||
dependencies | ||
}; | ||
const varName = varDefNode.variable.name.value; | ||
const varType = graphql_1.typeFromAST(schema, varDefNode.type); | ||
if (!varType || !graphql_1.isInputType(varType)) { | ||
const varType = (0, graphql_1.typeFromAST)(schema, varDefNode.type); | ||
if (!varType || !(0, graphql_1.isInputType)(varType)) { | ||
// Must use input types for variables. This should be caught during | ||
// validation, however is checked again here for safety. | ||
errors.push(new error_1.GraphQLError(`Variable "$${varName}" expected value of type ` + | ||
`"${varType ? varType : graphql_1.print(varDefNode.type)}" which cannot be used as an input type.`, ast_1.computeLocations([varDefNode.type]))); | ||
`"${varType || (0, graphql_1.print)(varDefNode.type)}" which cannot be used as an input type.`, (0, ast_1.computeLocations)([varDefNode.type]))); | ||
continue; | ||
} | ||
if (varDefNode.defaultValue) { | ||
// If no value was provided to a variable with a default value, | ||
// use the default value. | ||
coercedValues[varName] = graphql_1.valueFromAST(varDefNode.defaultValue, varType); | ||
} | ||
const hasValueName = hasValue(ast_1.addPath(context.inputPath, varName)); | ||
// Ensure a constant shape of the input map | ||
coercedValues[varName] = undefined; | ||
const hasValueName = hasValue((0, ast_1.addPath)(context.inputPath, varName)); | ||
mainBody += `const ${hasValueName} = Object.prototype.hasOwnProperty.call(${getObjectPath(context.inputPath)}, "${varName}");\n`; | ||
context.inputPath = ast_1.addPath(context.inputPath, varName); | ||
context.responsePath = ast_1.addPath(context.responsePath, varName); | ||
mainBody += generateInput(context, varType, varName, hasValueName, false); | ||
context.inputPath = (0, ast_1.addPath)(context.inputPath, varName); | ||
context.responsePath = (0, ast_1.addPath)(context.responsePath, varName); | ||
mainBody += generateInput(context, varType, varName, hasValueName, (0, graphql_1.valueFromAST)(varDefNode.defaultValue, varType), false); | ||
} | ||
@@ -58,3 +55,3 @@ if (errors.length > 0) { | ||
} | ||
const gen = generate_function_1.default(); | ||
const gen = (0, generate_function_1.default)(); | ||
gen(` | ||
@@ -71,3 +68,6 @@ return function getVariables(input) { | ||
`); | ||
return Function("GraphQLJITError", "inspect", ...Array.from(dependencies.keys()), gen.toString())(error_1.GraphQLError, inspect, ...Array.from(dependencies.values())); | ||
// eslint-disable-next-line | ||
return Function.apply(null, ["GraphQLJITError", "inspect"] | ||
.concat(Array.from(dependencies.keys())) | ||
.concat(gen.toString())).apply(null, [error_1.GraphQLError, inspect].concat(Array.from(dependencies.values()))); | ||
} | ||
@@ -79,9 +79,9 @@ exports.compileVariableParsing = compileVariableParsing; | ||
const MIN_32BIT_INT = -2147483648; | ||
function generateInput(context, varType, varName, hasValueName, wrapInList) { | ||
function generateInput(context, varType, varName, hasValueName, defaultValue, wrapInList) { | ||
const currentOutput = getObjectPath(context.responsePath); | ||
const currentInput = getObjectPath(context.inputPath); | ||
const errorLocation = printErrorLocation(ast_1.computeLocations([context.varDefNode])); | ||
const gen = generate_function_1.default(); | ||
const errorLocation = printErrorLocation((0, ast_1.computeLocations)([context.varDefNode])); | ||
const gen = (0, generate_function_1.default)(); | ||
gen(`if (${currentInput} == null) {`); | ||
if (graphql_1.isNonNullType(varType)) { | ||
if ((0, graphql_1.isNonNullType)(varType)) { | ||
let nonNullMessage; | ||
@@ -109,5 +109,8 @@ let omittedMessage; | ||
`); | ||
if (defaultValue !== undefined) { | ||
gen(`else { ${currentOutput} = ${JSON.stringify(defaultValue)} }`); | ||
} | ||
} | ||
gen(`} else {`); | ||
if (graphql_1.isScalarType(varType)) { | ||
if ((0, graphql_1.isScalarType)(varType)) { | ||
switch (varType.name) { | ||
@@ -213,3 +216,3 @@ case graphql_1.GraphQLID.name: | ||
} | ||
else if (graphql_1.isEnumType(varType)) { | ||
else if ((0, graphql_1.isEnumType)(varType)) { | ||
context.dependencies.set(`${varType.name}getValue`, varType.getValue.bind(varType)); | ||
@@ -237,3 +240,3 @@ gen(` | ||
} | ||
else if (graphql_1.isListType(varType)) { | ||
else if ((0, graphql_1.isListType)(varType)) { | ||
context.errorMessage = `'Variable "$${varName}" got invalid value ' + inspect(${currentInput}) + '; '`; | ||
@@ -243,4 +246,4 @@ const hasValueName = hasValue(context.inputPath); | ||
const subContext = createSubCompilationContext(context); | ||
subContext.responsePath = ast_1.addPath(subContext.responsePath, index, "variable"); | ||
subContext.inputPath = ast_1.addPath(subContext.inputPath, index, "variable"); | ||
subContext.responsePath = (0, ast_1.addPath)(subContext.responsePath, index, "variable"); | ||
subContext.inputPath = (0, ast_1.addPath)(subContext.inputPath, index, "variable"); | ||
subContext.depth++; | ||
@@ -253,10 +256,10 @@ gen(` | ||
${getObjectPath(subContext.inputPath)} !== undefined; | ||
${generateInput(subContext, varType.ofType, varName, hasValueName, false)} | ||
${generateInput(subContext, varType.ofType, varName, hasValueName, undefined, false)} | ||
} | ||
} else { | ||
${generateInput(context, varType.ofType, varName, hasValueName, true)} | ||
${generateInput(context, varType.ofType, varName, hasValueName, undefined, true)} | ||
} | ||
`); | ||
} | ||
else if (graphql_1.isInputType(varType)) { | ||
else if ((0, graphql_1.isInputType)(varType)) { | ||
gen(` | ||
@@ -275,3 +278,3 @@ if (typeof ${currentInput} !== 'object') { | ||
allowedFields.push(field.name); | ||
const hasValueName = hasValue(ast_1.addPath(subContext.inputPath, field.name)); | ||
const hasValueName = hasValue((0, ast_1.addPath)(subContext.inputPath, field.name)); | ||
gen(` | ||
@@ -282,7 +285,7 @@ const ${hasValueName} = Object.prototype.hasOwnProperty.call( | ||
`); | ||
subContext.inputPath = ast_1.addPath(subContext.inputPath, field.name); | ||
subContext.responsePath = ast_1.addPath(subContext.responsePath, field.name); | ||
subContext.inputPath = (0, ast_1.addPath)(subContext.inputPath, field.name); | ||
subContext.responsePath = (0, ast_1.addPath)(subContext.responsePath, field.name); | ||
subContext.errorMessage = `'Variable "$${varName}" got invalid value ' + inspect(${currentInput}) + '; '`; | ||
gen(` | ||
${generateInput(subContext, field.type, field.name, hasValueName, false)} | ||
${generateInput(subContext, field.type, field.name, hasValueName, field.defaultValue, false)} | ||
`); | ||
@@ -289,0 +292,0 @@ } |
108
package.json
{ | ||
"name": "@hoangvvo/graphql-jit", | ||
"version": "0.6.4", | ||
"version": "0.7.2", | ||
"description": "GraphQL JIT Compiler to JS", | ||
"main": "dist/index.js", | ||
"types": "./dist/index.d.ts", | ||
"author": "Hoang Vo (https://hoangvvo.com)", | ||
"keywords": [ | ||
"graphql", | ||
"graphql-js", | ||
"jit", | ||
"performance" | ||
], | ||
"author": "Hoang Vo", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/hoangvvo/graphql-jit.git" | ||
"url": "git@github.com:hoangvvo/graphql-jit.git" | ||
}, | ||
"scripts": { | ||
"precommit": "lint-staged", | ||
"prepublishOnly": "yarn && yarn build", | ||
"lint": "eslint .", | ||
"build": "tsc", | ||
"format": "prettier --write 'src/**/*.ts' '*.js'", | ||
"check-format": "prettier -l 'src/**/*.ts' '*.js'", | ||
"lint": "eslint --ext .ts .", | ||
"lint-fix": "eslint --ext .ts . --fix", | ||
"build": "tsc --project tsconfig.build.json", | ||
"test": "jest", | ||
"test:ci": "jest --ci --coverage", | ||
"mutation-test": "stryker run", | ||
"codecov": "codecov", | ||
"benchmark": "NODE_ENV=production ts-node -T ./src/__benchmarks__/benchmarks.ts" | ||
@@ -30,2 +29,22 @@ }, | ||
], | ||
"jest": { | ||
"moduleFileExtensions": [ | ||
"ts", | ||
"js", | ||
"json" | ||
], | ||
"testEnvironment": "node", | ||
"testRegex": "(/tests/.*|(\\.|/)test)\\.ts$", | ||
"transform": { | ||
"^.+\\.ts$": "ts-jest" | ||
}, | ||
"coverageThreshold": { | ||
"global": { | ||
"branches": 92, | ||
"functions": 96, | ||
"lines": 96, | ||
"statements": 96 | ||
} | ||
} | ||
}, | ||
"peerDependencies": { | ||
@@ -35,28 +54,51 @@ "graphql": ">=15" | ||
"devDependencies": { | ||
"@babel/core": "^7.13.8", | ||
"@babel/preset-env": "^7.13.9", | ||
"@babel/preset-typescript": "^7.13.0", | ||
"@graphql-tools/schema": "^7.1.3", | ||
"@types/benchmark": "^2.1.0", | ||
"@types/jest": "^26.0.20", | ||
"@graphql-tools/schema": "^8.3.1", | ||
"@stryker-mutator/core": "^2.0.0", | ||
"@stryker-mutator/jest-runner": "^2.0.0", | ||
"@stryker-mutator/typescript": "^2.0.0", | ||
"@types/benchmark": "^1.0.31", | ||
"@types/jest": "^27.0.3", | ||
"@types/lodash.memoize": "^4.1.6", | ||
"@types/node": "^14.14.31", | ||
"@typescript-eslint/eslint-plugin": "^4.16.1", | ||
"@typescript-eslint/parser": "^4.16.1", | ||
"babel-jest": "^26.6.3", | ||
"@types/lodash.merge": "^4.6.6", | ||
"@types/lodash.mergewith": "^4.6.6", | ||
"@types/node": "^10.17.26", | ||
"@typescript-eslint/eslint-plugin": "5.2.0", | ||
"@typescript-eslint/parser": "5.2.0", | ||
"benchmark": "^2.1.4", | ||
"codecov": "^3.8.1", | ||
"eslint": "^7.21.0", | ||
"eslint-config-prettier": "^8.1.0", | ||
"eslint-plugin-prettier": "^3.3.1", | ||
"fast-json-stringify": "^2.4.2", | ||
"graphql": "^15.1.0", | ||
"jest": "^26.6.3", | ||
"prettier": "^2.2.1", | ||
"ts-node": "^9.1.1", | ||
"typescript": "^4.2.3" | ||
"codecov": "^3.3.0", | ||
"eslint": "^8.1.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"eslint-config-standard": "^16.0.3", | ||
"eslint-plugin-import": "^2.25.2", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-promise": "^5.1.1", | ||
"eslint-plugin-standard": "^5.0.0", | ||
"graphql": "^16.0.0", | ||
"jest": "^27.4.3", | ||
"lint-staged": "^8.1.5", | ||
"prettier": "^2.4.1", | ||
"ts-jest": "^27.0.7", | ||
"ts-node": "^8.0.3", | ||
"typescript": "^4.4.4" | ||
}, | ||
"dependencies": { | ||
"lodash.memoize": "^4.1.2" | ||
"@graphql-typed-document-node/core": "3.1.0", | ||
"generate-function": "^2.3.1", | ||
"lodash.memoize": "^4.1.2", | ||
"lodash.merge": "4.6.2", | ||
"lodash.mergewith": "4.6.2" | ||
}, | ||
"lint-staged": { | ||
"linters": { | ||
"*.ts": [ | ||
"eslint --fix", | ||
"prettier --no-config --write", | ||
"git add" | ||
], | ||
"*.{graphql,js,md,json,yaml,yml}": [ | ||
"prettier --no-config --write", | ||
"git add" | ||
] | ||
} | ||
} | ||
} |
# GraphQL JIT | ||
[![Build](https://github.com/hoangvvo/graphql-jit/actions/workflows/build.yml/badge.svg)](https://github.com/hoangvvo/graphql-jit/actions/workflows/build.yml) | ||
[![codecov](https://codecov.io/gh/hoangvvo/graphql-jit/branch/dev/graph/badge.svg?token=WUU4718LQH)](https://codecov.io/gh/hoangvvo/graphql-jit) | ||
![npm](https://img.shields.io/npm/dw/graphql-jit) | ||
[![codecov](https://codecov.io/gh/zalando-incubator/graphql-jit/branch/main/graph/badge.svg)](https://codecov.io/gh/zalando-incubator/graphql-jit) | ||
This is a fork of [zalando-incubator/graphql-jit](https://github.com/zalando-incubator/graphql-jit) that features the following improvements: | ||
This is a fork of zalando-incubator/graphql-jit that features the following improvements: | ||
- Support for GraphQL Subscription | ||
- ~~Support for GraphQL Subscription~~ (merged in upstream) | ||
- Custom JSON Stringify factory function | ||
- Minimal dependencies for lightweight bundle | ||
If you do not have the above use cases, it is better to stick with the [original repo](https://github.com/zalando-incubator/graphql-jit). Check out the [their README](https://github.com/zalando-incubator/graphql-jit/blob/master/README.md) to learn more about `graphql-jit`. | ||
### Why? | ||
GraphQL-JS is a very well written runtime implementation of the latest GraphQL spec. However, by compiling to JS, V8 is able to create optimized | ||
code which yields much better performance. `graphql-jit` leverages this behaviour of V8 optimization by compiling the queries into functions to significantly improve performance (See [benchmarks](#benchmarks) below) | ||
#### Benchmarks | ||
GraphQL-JS 16 on Node 16.13.0 | ||
```bash | ||
$ yarn benchmark skip-json | ||
Starting introspection | ||
graphql-js x 1,941 ops/sec ±2.50% (225 runs sampled) | ||
graphql-jit x 6,158 ops/sec ±2.38% (222 runs sampled) | ||
Starting fewResolvers | ||
graphql-js x 26,620 ops/sec ±2.41% (225 runs sampled) | ||
graphql-jit x 339,223 ops/sec ±2.94% (215 runs sampled) | ||
Starting manyResolvers | ||
graphql-js x 16,415 ops/sec ±2.36% (220 runs sampled) | ||
graphql-jit x 178,331 ops/sec ±2.73% (221 runs sampled) | ||
Starting nestedArrays | ||
graphql-js x 127 ops/sec ±1.43% (220 runs sampled) | ||
graphql-jit x 1,316 ops/sec ±2.58% (219 runs sampled) | ||
Done in 141.25s. | ||
``` | ||
### Support for GraphQL spec | ||
The goal is to support the [June 2018 version of the GraphQL spec](https://facebook.github.io/graphql/June2018/). | ||
#### Differences to `graphql-js` | ||
In order to achieve better performance, the `graphql-jit` compiler introduces some limitations. | ||
The primary limitation is that all computed properties must have a resolver and only these can return a `Promise`. | ||
## Install | ||
```sh | ||
yarn add @hoangvvo/graphql-jit | ||
// or | ||
npm i @hoangvvo/graphql-jit | ||
yarn add graphql-jit | ||
``` | ||
## Usage | ||
## Example | ||
For complete working examples, check the [examples/](examples) directory | ||
#### Create a schema | ||
```js | ||
import { compileQuery, isCompiledQuery } from "graphql-jit"; | ||
const typeDefs = ` | ||
type Query { | ||
hello: String | ||
} | ||
`; | ||
const resolvers = { | ||
Query: { | ||
hello() { | ||
return new Promise((resolve) => setTimeout(() => resolve("World!"), 200)); | ||
} | ||
} | ||
}; | ||
const query = `{ hello }`; | ||
const { makeExecutableSchema } = require("@graphql-tools/schema"); | ||
const schema = makeExecutableSchema({ typeDefs, resolvers }); | ||
``` | ||
#### Compile a Query | ||
```js | ||
const query = ` | ||
{ | ||
hello | ||
} | ||
`; | ||
const { parse } = require("graphql"); | ||
const document = parse(query); | ||
const { compileQuery, isCompiledQuery } = require("graphql-jit"); | ||
const compiledQuery = compileQuery(schema, document); | ||
// check if the compilation is successful | ||
@@ -37,2 +96,3 @@ if (!isCompiledQuery(compiledQuery)) { | ||
} | ||
``` | ||
@@ -70,3 +130,3 @@ #### Execute the Query | ||
for overly expensive serializers | ||
- `customJSONSerializer` {function, default: undefined} - A function to be called with [`CompilationContext`](https://github.com/zalando-incubator/graphql-jit/blob/master/src/execution.ts#L87) to produce also a JSON serializer function. The default stringifier function is `JSON.stringify` | ||
- `customJSONSerializer` {function, default: undefined} - A function to be called with [`CompilationContext`](https://github.com/zalando-incubator/graphql-jit/blob/main/src/execution.ts#L130) to produce also a JSON serializer function. The default stringifier function is `JSON.stringify` | ||
@@ -73,0 +133,0 @@ #### compiledQuery.query(root: any, context: any, variables: Maybe<{ [key: string]: any }>) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
147
2
209292
6
28
33
3104
+ Addedgenerate-function@^2.3.1
+ Addedlodash.merge@4.6.2
+ Addedlodash.mergewith@4.6.2
+ Added@graphql-typed-document-node/core@3.1.0(transitive)
+ Addedgenerate-function@2.3.1(transitive)
+ Addedgraphql@15.9.0(transitive)
+ Addedis-property@1.0.2(transitive)
+ Addedlodash.merge@4.6.2(transitive)
+ Addedlodash.mergewith@4.6.2(transitive)