import { ApolloServerPlugin } from 'apollo-server-plugin-base' ; import { parse , print } from 'graphql' ; import { executePostExecRules , compileRules , addSelectionSetsToDocument , cleanupResult , getFilteredDocument , getFragmentDefinitions , completeConfig , IAuthZConfig , hasPostExecutionRules } from '@graphql-authz/core' ; export function authZApolloPlugin ( config ) { const { rules , authSchema , directiveName , authSchemaKey , processError } = completeConfig ( config ) ; return { requestDidStart ( requestContext ) { const { operationName , query } = requestContext . request ; if ( ! query ) { throw new Error ( 'Expected requestContext to have request.query' ) ; } const { variables = { } } = requestContext . request ; const filteredDocument = getFilteredDocument ( parse ( query ) , operationName ) ; const compiledRules = compileRules ( { document : filteredDocument , schema : requestContext . schema , rules , variables , directiveName , authSchemaKey , authSchema } ) ; const fullDocument = addSelectionSetsToDocument ( filteredDocument , compiledRules , requestContext . schema , variables ) ; requestContext . request . query = print ( fullDocument ) ; return Promise . resolve ( { async didResolveOperation ( requestContext ) { try { await Promise . all ( compiledRules . preExecutionRules . map ( rule => rule . execute ( requestContext . context , rule . config . fieldArgs ) ) ) ; } catch ( error ) { processError ( error ) ; } } , async willSendResponse ( requestContext ) { try { if ( requestContext . response . data && hasPostExecutionRules ( compiledRules ) ) { const fragmentDefinitions = getFragmentDefinitions ( filteredDocument ) ; const executionPromises = executePostExecRules ( { context : requestContext . context , schema : requestContext . schema , resultData : requestContext . response ?. data , document : filteredDocument , rules : compiledRules , fragmentDefinitions , variables } ) ; const cleanResult = cleanupResult ( filteredDocument , requestContext . schema , fragmentDefinitions , variables , requestContext . response . data ) ; requestContext . response . data = cleanResult ; await Promise . all ( executionPromises ) ; } } catch ( error ) { processError ( error ) ; } } } ) ; } } ; }