How do I execute code pre and post mutation with graphql and apollo server?

I'm just getting started with GraphQL and I've worked mostly with featherjs to build REST APIs so far. There's the concept of hooks to run code before or after interacting with a service. I wanted to know if there's a way to achieve something similar in a graphql setup.


I'm using neo4j and graphql with express and apollo server to set up an API, and I'd like to avoid having to write custom resolvers for every mutation if possible.


For a concrete example, below is a basic API server. It's put together using docker compose and has users and applications. I would like to in general be able to run arbitrary code before or after a mutation with access to the model being modified. Things like more complex validation before, or side effects after.


Those things could be here, for example, before changing the state of an application to declined, make sure that a note is added. Or after changing the state to approved, send an email to the applicant.


I'm not sure how or where to implement this kind of thing, any help is appreciated! Or also if I'm thinking about graphql wrong and there's a better way of doing what I'm trying to do.


Thanks!

import http from 'http';
import express from 'express';
import neo4j from 'neo4j-driver';
import {Neo4jGraphQL} from '@neo4j/graphql';
import {gql, ApolloServer} from 'apollo-server-express';
import {ApolloServerPluginDrainHttpServer} from 'apollo-server-core';

const typeDefs=gql`
type User {
    email: String!
    applications: [Application!] @relationship(type: "APPLICANT", direction: OUT)
}

type Application {
    user: User! @relationship(type: "APPLICANT", direction: IN)
    state: String!
    note: String
}
`;

const driver=neo4j.driver(
    'neo4j://neo4j:7687',
    neo4j.auth.basic('neo4j', 'password')
);

const {schema}=new Neo4jGraphQL({typeDefs, driver});

(async ()=>{
    const app=express();
    const server=http.createServer(app);
    const apollo=new ApolloServer({
        schema,
        plugins: [ApolloServerPluginDrainHttpServer({httpServer: server})]
    });
    await apollo.start();
    apollo.applyMiddleware({app});
    await new Promise(r=>server.listen({port: 4000}, r));
    console.log('GraphQL server listening at '+apollo.graphqlPath);
})();