grafast
Version:
Cutting edge GraphQL planning and execution engine
182 lines • 6.95 kB
TypeScript
import LRU from "@graphile/lru";
import type { FieldNode, GraphQLEnumType, GraphQLObjectType, GraphQLScalarType } from "graphql";
import * as graphql from "graphql";
import type { Bucket } from "../bucket.js";
import type { ExecutionEntryFlags, JSONValue, LocationDetails } from "../interfaces.js";
import type { Step } from "../step.js";
import type { PayloadRoot } from "./executeOutputPlan.js";
import type { LayerPlan } from "./LayerPlan.js";
export type OutputPlanTypeIntrospection = {
mode: "introspection";
/**
* The GraphQL introspection field selection (may include arguments/etc). We
* can build a GraphQL document from this and issue it to graphql-js rather
* than replicating that effort.
*/
field: FieldNode;
/**
* The names of the variables used in this document.
*/
variableNames: string[];
/**
* No need to re-run the introspection each time, may as well cache it,
* right?
*
* Key: canonical JSON stringify of the variables used.
* Value: the GraphQL result (`{data, errors}`) for this.
*/
introspectionCacheByVariableValues: LRU<string, JSONValue>;
};
export type OutputPlanTypeRoot = {
/**
* Always return `{}`
*/
mode: "root";
typeName: string;
};
export type OutputPlanTypeObject = {
/**
* Return `{}` if non-null
*/
mode: "object";
typeName: string;
deferLabel: string | undefined;
};
export type OutputPlanTypePolymorphicObject = {
/**
* Return `{}` if non-null
*/
mode: "polymorphic";
typeNames: string[];
deferLabel: string | undefined;
};
export type OutputPlanTypeArray = {
/**
* Return a list of the same length if an array
*/
mode: "array";
};
export type OutputPlanTypeLeaf = {
/**
* Return the value.
*/
mode: "leaf";
graphqlType: GraphQLScalarType | GraphQLEnumType;
};
export type OutputPlanTypeNull = {
mode: "null";
};
/**
* Thanks to `@stream`, output plans must handle their own nullability concerns
* and we might need an output plan for any of these:
*
* - A concrete object
* - A polymorphic object
* - A leaf (enum/scalar)
* - Something we know will always be null
* - A list of any of the above
* - A list of lists
*
* In addition to the above, we also need to cover
*
* - The root object (which is like a concrete object, except it's never null)
* - Introspection
*/
export type OutputPlanType = OutputPlanTypeRoot | OutputPlanTypeObject | OutputPlanTypePolymorphicObject | OutputPlanTypeLeaf | OutputPlanTypeNull | OutputPlanTypeArray | OutputPlanTypeIntrospection;
export type OutputPlanKeyValueOutputPlan = {
type: "outputPlan";
outputPlan: OutputPlan;
isNonNull: boolean;
locationDetails: LocationDetails;
};
export type OutputPlanKeyValueTypeName = {
type: "__typename";
locationDetails: LocationDetails;
};
export type OutputPlanKeyValue = OutputPlanKeyValueOutputPlan | OutputPlanKeyValueTypeName;
export type OutputPlanKeyValueOutputPlanWithCachedBits = OutputPlanKeyValueOutputPlan & {
layerPlanId: number;
};
/**
* Defines a way of taking a layerPlan and converting it into an output value.
*
* The result of executing an output plan will be the following:
*
* - data?: the data for this layer, could be object, array or leaf (see OutputPlanMode)
* - errors: a list of errors that occurred (if any), including path details _within the output plan_
* - streams: a list of streams that were created
*/
export declare class OutputPlan<TType extends OutputPlanType = OutputPlanType> {
layerPlan: LayerPlan;
readonly type: TType;
/** For errors */
readonly locationDetails: LocationDetails;
/**
* The step that represents the root value. How this is used depends on the
* OutputPlanMode.
*/
readonly rootStep: Step;
/**
* If this output plan should resolve to an error if a side effect step
* raises an error, this is that side effect.
*/
readonly sideEffectStep: Step | null;
/**
* For root/object output plans, the keys to set on the resulting object
* grouped by the concrete object type name.
*
* IMPORTANT: the order of these keys is significant, they MUST match the
* order in the request otherwise we break GraphQL spec compliance!
*/
keys: {
[key: string]: OutputPlanKeyValueTypeName | OutputPlanKeyValueOutputPlanWithCachedBits;
};
/**
* For list output plans, the output plan that describes the list children.
*/
child: OutputPlan | null;
childIsNonNull: boolean;
/**
* For polymorphic output plans, the Object output plan for each specific type.
*/
childByTypeName: {
[typeName: string]: OutputPlan<OutputPlanTypeObject>;
} | undefined;
/**
* For object output plan types only.
*/
deferredOutputPlans: OutputPlan<OutputPlanTypeObject | OutputPlanTypePolymorphicObject>[];
constructor(layerPlan: LayerPlan,
/**
* For root, this should always be an object.
*
* For object this could represent an object or null.
*
* For polymorphic this could represent a polymorphic object or null.
*
* For array it's the list itself (or null) and dictates the length of the result.
*
* For leaf, it's the leaf plan itself.
*
* For `introspection`, `null` it's irrelevant. Use `constant(null)` or whatever.
*/
rootStep: Step, type: TType, locationDetails: LocationDetails);
print(): string;
toString(): string;
expectChild(type: GraphQLObjectType | null, key: string | null): void;
addChild(type: GraphQLObjectType | null, key: string | null, child: OutputPlanKeyValue): void;
getLayerPlans(layerPlans?: Set<LayerPlan<import("./LayerPlan.js").LayerPlanReason>>): Set<LayerPlan>;
makeNextStepByLayerPlan(): Record<number, any[]>;
execute(this: OutputPlan, _root: PayloadRoot, _mutablePath: ReadonlyArray<string | number>, _bucket: Bucket, _bucketIndex: number, _rawBucketRootValue?: any, _bucketRootFlags?: ExecutionEntryFlags): JSONValue;
executeString(this: OutputPlan, _root: PayloadRoot, _mutablePath: ReadonlyArray<string | number>, _bucket: Bucket, _bucketIndex: number, _rawBucketRootValue?: any, _bucketRootFlags?: ExecutionEntryFlags): string;
optimize(): void;
finalize(): void;
}
export declare function coerceError(error: Error, locationDetails: LocationDetails, path: ReadonlyArray<string | number>): graphql.GraphQLError;
export declare function nonNullError(locationDetails: LocationDetails, path: readonly (string | number)[]): graphql.GraphQLError;
/**
* Finds the child of `targetParent` that has a path towards `descendent` (by
* walking backwards from descendent to targetParent).
*/
export declare function getDirectLayerPlanChild(targetParent: LayerPlan, descendent: LayerPlan): LayerPlan;
//# sourceMappingURL=OutputPlan.d.ts.map