import { GraphQLSchema , graphql , ExecutionResult , GraphQLResolveInfo , defaultFieldResolver , OperationDefinitionNode } from 'graphql' ; import { StrongObjectType } from './object' ; /**
 * Creates a strong, type-safe, GraphQL schema that forces correctness on
 * execution.
 */ export function createSchema < TValue > ( config ) ; export function createSchema < TValue , TContext > ( config ) ; export function createSchema < TValue , TContext > ( config ) { return new StrongSchema ( config ) ; } /**
 * The configuration for a strong GraphQL schema.
 */ export interface StrongSchemaConfig < TValue , TContext > { readonly query : StrongObjectType < TValue , TContext > ; readonly mutation ? : StrongObjectType < TValue , TContext > ; /**
     * Runs only once at the beginning of an execution for this schema.
     */ onExecute ? ( value , context , info ) : void | Promise < void > ; } /**
 * The strong GraphQL schema represents a type-safe GraphQL schema that forces
 * type correctness on execution with the `execute` method.
 */ export class StrongSchema < TValue , TContext > extends GraphQLSchema { constructor ( config ) { super ( { query : config . query . ofType . clone ( ) , mutation : config . mutation && config . mutation . ofType . clone ( ) , } ) ; const { onExecute } = config ; if ( onExecute ) { const executedOperations = new WeakMap < OperationDefinitionNode , Promise < void > > ( ) ; const rootTypes = [ this . getQueryType ( ) , this . getMutationType ( ) , ] . filter ( Boolean ) ; rootTypes . forEach ( rootType => { const fields = rootType . getFields ( ) ; for ( const fieldName of Object . keys ( fields ) ) { const resolver = fields [ fieldName ] . resolve || defaultFieldResolver ; fields [ fieldName ] . resolve = async ( source , args , context , info ) => { if ( ! executedOperations . has ( info . operation ) ) { executedOperations . set ( info . operation , Promise . resolve ( onExecute ( source , context , info ) ) ) ; } await executedOperations . get ( info . operation ) ; return await resolver ( source , args , context , info ) ; } ; } } ) ; } } /**
     * A type-safe execution function for our strong GraphQL schema. With this
     * function you will be forced to provide values and contexts of the correct
     * types.
     */ public execute ( query , value , context , variables = { } , operation ? ) { return graphql ( this , query , value , context , variables , operation ) ; } }