UNPKG

grafast

Version:

Cutting edge GraphQL planning and execution engine

179 lines 7.07 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GraphQLResolveTypeStep = exports.GraphQLResolverStep = void 0; exports.graphqlResolveType = graphqlResolveType; exports.graphqlResolver = graphqlResolver; const tslib_1 = require("tslib"); const graphql = tslib_1.__importStar(require("graphql")); const index_js_1 = require("../index.js"); const step_js_1 = require("../step.js"); const utils_js_1 = require("../utils.js"); const { defaultTypeResolver } = graphql; /** * Calls the given GraphQL resolver for each input - emulates GraphQL * resolution. * * @internal */ class GraphQLResolverStep extends step_js_1.UnbatchedStep { static { this.$$export = { moduleName: "grafast", exportName: "GraphQLResolverStep", }; } constructor(resolver, subscriber, $plan, $args, resolveInfoBase) { super(); this.resolver = resolver; this.subscriber = subscriber; this.resolveInfoBase = resolveInfoBase; this.isSyncAndSafe = false; this.allowMultipleOptimizations = false; this.addDependency($plan); this.addDependency($args); this.addDependency((0, index_js_1.context)()); this.addDependency(this.operationPlan.variableValuesStep); this.addDependency(this.operationPlan.rootValueStep); this.isNotRoot = ![ this.operationPlan.queryType, this.operationPlan.mutationType, this.operationPlan.subscriptionType, ].includes(resolveInfoBase.parentType); } toStringMeta() { const resolverName = this.resolver?.displayName || this.resolver?.name || this.subscriber?.displayName || this.subscriber?.name || null; return `${this.resolveInfoBase.parentType.name}.${this.resolveInfoBase.fieldName}${resolverName && resolverName !== "resolve" ? `:${resolverName}` : ""}`; } unbatchedExecute(extra, source, args, context, variableValues, rootValue) { if (!extra.stream) { if (this.isNotRoot && source == null) { return source; } const resolveInfo = Object.assign(Object.create(this.resolveInfoBase), { variableValues, rootValue, path: { typename: this.resolveInfoBase.parentType.name, key: this.resolveInfoBase.fieldName, // ENHANCE: add full support for path (requires runtime indexes) prev: undefined, }, }); const data = this.resolver?.(source, args, context, resolveInfo); return flagErrorIfErrorAsync(data); } else { if (this.isNotRoot) { return Promise.reject(new Error(`Invalid non-root subscribe`)); } if (this.subscriber == null) { return Promise.reject(new Error(`Cannot subscribe to field`)); } const resolveInfo = Object.assign(Object.create(this.resolveInfoBase), { // ENHANCE: add support for path variableValues, rootValue, }); // TODO: we also need to call the resolver on each result? const data = this.subscriber(source, args, context, resolveInfo); // TODO: should apply flagErrorIfError to each value data yields return flagErrorIfErrorAsync(data); } } } exports.GraphQLResolverStep = GraphQLResolverStep; /** @internal */ class GraphQLResolveTypeStep extends step_js_1.Step { static { this.$$export = { moduleName: "grafast", exportName: "GraphQLResolveTypeStep", }; } constructor($stepOrSpecifier, info) { super(); // Could be promises this.isSyncAndSafe = false; const { abstractType } = info; this.abstractType = abstractType; this.resolveInfoBase = { ...this.operationPlan.resolveInfoOperationBase, // TODO: this resolveInfo is seriously hacked, we don't know a number of // things that _shouldn't_ be necessary for figuring out the type, so // we'll run in this crippled state. // Really we should inherit the resolveInfo from the field itself, but // currently that doesn't get passed through. Maybe it should have its // own step which we pass through as a dependency? fieldName: null, parentType: null, path: null, fieldNodes: null, // Even this is a lie returnType: abstractType, }; this.addDataDependency($stepOrSpecifier); this.addUnaryDependency((0, index_js_1.context)()); this.addUnaryDependency(this.operationPlan.variableValuesStep); this.addUnaryDependency(this.operationPlan.rootValueStep); } /** * Akin to graphql-js' completeAbstractValue... but just the typeName * resolution part. */ figureOutTheTypeOf(data, context, resolveInfo) { const abstractType = this.abstractType; if (abstractType.resolveType != null) { return abstractType.resolveType(data, context, resolveInfo, abstractType); } else { return defaultTypeResolver(data, context, resolveInfo, abstractType); } } execute({ indexMap, values: [values0, contextVal, variableValuesVal, rootValueVal], }) { const context = contextVal.unaryValue(); const variableValues = variableValuesVal.unaryValue(); const rootValue = rootValueVal.unaryValue(); const resolveInfo = { ...this.resolveInfoBase, rootValue, variableValues, }; return indexMap((i) => { const data = values0.at(i); if (data == null) { return data; } else if ((0, utils_js_1.isPromiseLike)(data)) { return data.then((resolvedData) => this.figureOutTheTypeOf(resolvedData, context, resolveInfo)); } else { return this.figureOutTheTypeOf(data, context, resolveInfo); } }); } } exports.GraphQLResolveTypeStep = GraphQLResolveTypeStep; function graphqlResolveType($stepOrSpecifier, info) { return new GraphQLResolveTypeStep($stepOrSpecifier, info); } /** * Emulates what GraphQL does when calling a resolver, including handling of * polymorphism. * * @internal */ function graphqlResolver(resolver, subscriber, $step, $args, resolveInfoBase) { return new GraphQLResolverStep(resolver, subscriber, $step, $args, resolveInfoBase); } function flagErrorIfError(data) { return data instanceof Error ? (0, index_js_1.flagError)(data) : data; } function flagErrorIfErrorAsync(data) { if ((0, utils_js_1.isPromiseLike)(data)) { return data.then(flagErrorIfError); } else { return flagErrorIfError(data); } } //# sourceMappingURL=graphqlResolver.js.map