import { GraphQLSchemaValidationError , GraphQLSchemaModule , GraphQLResolverMap , } from '../schema-helper' ; import { GraphQLRequest , GraphQLExecutionResult , Logger } from 'apollo-server-types' ; import { buildSubgraphSchema } from '@apollo/subgraph' ; import { executeQueryPlan , buildOperationContext , } from '@apollo/gateway' ; import { QueryPlan , QueryPlanner } from '@apollo/query-planner' ; import { LocalGraphQLDataSource } from '../datasources/LocalGraphQLDataSource' ; import { mergeDeep } from 'apollo-utilities' ; import { queryPlanSerializer , astSerializer } from 'apollo-federation-integration-testsuite' ; import gql from 'graphql-tag' ; import { fixtures } from 'apollo-federation-integration-testsuite' ; import { composeServices } from '@apollo/composition' ; import { buildSchema , operationFromDocument , ServiceDefinition } from '@apollo/federation-internals' ; const prettyFormat = require ( 'pretty-format' ) ; export type ServiceDefinitionModule = ServiceDefinition & GraphQLSchemaModule ; export function overrideResolversInService ( module , resolvers ) { return { name : module . name , typeDefs : module . typeDefs , resolvers : mergeDeep ( module . resolvers , resolvers ) , } ; } export async function execute ( request , services = fixtures , logger = console ) { const serviceMap = Object . fromEntries ( services . map ( ( { name , typeDefs , resolvers } ) => { return [ name , new LocalGraphQLDataSource ( buildSubgraphSchema ( [ { typeDefs , resolvers } ] ) ) , ] as [ string , LocalGraphQLDataSource ] ; } ) ) ; const { schema , queryPlanner } = getFederatedTestingSchema ( services ) ; const operationDocument = gql `${ request . query }` ; const operation = operationFromDocument ( schema , operationDocument ) ; const queryPlan = queryPlanner . buildQueryPlan ( operation ) ; const operationContext = buildOperationContext ( { schema : schema . toAPISchema ( ) . toGraphQLJSSchema ( ) , operationDocument , } ) ; const result = await executeQueryPlan ( queryPlan , serviceMap , { cache : undefined as any , context : { } , request , logger } , operationContext ) ; return { ... result , queryPlan } ; } export function buildLocalService ( modules ) { const schema = buildSubgraphSchema ( modules ) ; return new LocalGraphQLDataSource ( schema ) ; } export function getFederatedTestingSchema ( services = fixtures ) { const compositionResult = composeServices ( services ) ; if ( compositionResult . errors ) { throw new GraphQLSchemaValidationError ( compositionResult . errors ) ; } const queryPlanner = new QueryPlanner ( compositionResult . schema ) ; const schema = buildSchema ( compositionResult . supergraphSdl ) ; const serviceMap = Object . fromEntries ( services . map ( ( service ) => [ service . name , buildLocalService ( [ service ] ) , ] ) ) ; return { serviceMap , schema , queryPlanner } ; } export function getTestingSupergraphSdl ( services = fixtures ) { const compositionResult = composeServices ( services ) ; if ( ! compositionResult . errors ) { return compositionResult . supergraphSdl ; } throw new Error ( `Testing fixtures don't compose properly!\nCauses:\n${ compositionResult . errors . join ( '\n\n' ) }` ) ; } export function wait ( ms , toResolveTo ? ) { return new Promise ( ( r ) => setTimeout ( ( ) => r ( toResolveTo ) , ms ) ) ; } export function printPlan ( queryPlan ) { return prettyFormat ( queryPlan , { plugins : [ queryPlanSerializer , astSerializer ] , } ) ; }