@apollo/server
Version:
Core engine for Apollo GraphQL server
119 lines (107 loc) • 3.38 kB
text/typescript
import {
execute,
type ExecutionArgs,
type ExecutionResult,
type GraphQLError,
} from 'graphql';
// This file "polyfills" graphql@17's experimentalExecuteIncrementally (by
// returning a function that does not understand incremental directives if
// you're using graphql@16). The types defined in this file are largely copied
// from graphql-js.
interface ObjMap<T> {
[key: string]: T;
}
export interface GraphQLExperimentalInitialIncrementalExecutionResult<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> extends ExecutionResult<TData, TExtensions> {
hasNext: boolean;
incremental?: ReadonlyArray<
GraphQLExperimentalIncrementalResult<TData, TExtensions>
>;
extensions?: TExtensions;
}
export interface GraphQLExperimentalSubsequentIncrementalExecutionResult<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> {
hasNext: boolean;
incremental?: ReadonlyArray<
GraphQLExperimentalIncrementalResult<TData, TExtensions>
>;
extensions?: TExtensions;
}
type GraphQLExperimentalIncrementalResult<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> =
| GraphQLExperimentalIncrementalDeferResult<TData, TExtensions>
| GraphQLExperimentalIncrementalStreamResult<TData, TExtensions>;
interface GraphQLExperimentalIncrementalDeferResult<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> extends ExecutionResult<TData, TExtensions> {
path?: ReadonlyArray<string | number>;
label?: string;
}
interface GraphQLExperimentalIncrementalStreamResult<
TData = Array<unknown>,
TExtensions = ObjMap<unknown>,
> {
errors?: ReadonlyArray<GraphQLError>;
items?: TData | null;
path?: ReadonlyArray<string | number>;
label?: string;
extensions?: TExtensions;
}
export interface GraphQLExperimentalIncrementalExecutionResults<
TData = ObjMap<unknown>,
TExtensions = ObjMap<unknown>,
> {
initialResult: GraphQLExperimentalInitialIncrementalExecutionResult<
TData,
TExtensions
>;
subsequentResults: AsyncGenerator<
GraphQLExperimentalSubsequentIncrementalExecutionResult<TData, TExtensions>,
void,
void
>;
}
type PromiseOrValue<T> = Promise<T> | T;
// This starts as undefined and is set to a function or null by running
// tryToLoadGraphQL17(). If graphql-js 17 is installed, it is set to the
// experimentalExecuteIncrementally function from that package; otherwise it is
// set to null.
let graphqlExperimentalExecuteIncrementally:
| ((
args: ExecutionArgs,
) => PromiseOrValue<
ExecutionResult | GraphQLExperimentalIncrementalExecutionResults
>)
| null
| undefined = undefined;
async function tryToLoadGraphQL17() {
if (graphqlExperimentalExecuteIncrementally !== undefined) {
return;
}
const graphql = await import('graphql');
if (
graphql.version === '17.0.0-alpha.2' &&
'experimentalExecuteIncrementally' in graphql
) {
graphqlExperimentalExecuteIncrementally = (graphql as any)
.experimentalExecuteIncrementally;
} else {
graphqlExperimentalExecuteIncrementally = null;
}
}
export async function executeIncrementally(
args: ExecutionArgs,
): Promise<ExecutionResult | GraphQLExperimentalIncrementalExecutionResults> {
await tryToLoadGraphQL17();
if (graphqlExperimentalExecuteIncrementally) {
return graphqlExperimentalExecuteIncrementally(args);
}
return execute(args);
}