Haven't worked with a GraphQL server in Next.js for some time now. Can't vouch that this approach is valid anymore.
API route
pages/api/graphql.ts
import {ApolloServer} from 'apollo-server-micro';
import {getSession} from 'next-auth/client';
import {schema} from '@/backend/graphql/schema';
import prisma from '@/utils/prisma';
const apolloServer = new ApolloServer({
schema,
context: async ({req}) => {
const session = await getSession({req});
const userEmail = session?.user?.email;
// Throw if invalid
if (!userEmail) {
throw new Error('Not authenticated');
}
return {prisma, currentUserEmail: userEmail};
},
tracing: process.env.NODE_ENV === 'development',
});
export const config = {
api: {bodyParser: false},
};
export default apolloServer.createHandler({
path: '/api/graphql',
});
Schema
context.ts
import {PrismaClient} from '@prisma/client';
export type Context = {prisma: PrismaClient; currentUserEmail: string};
schema.ts
import {GraphQLDateTime} from 'graphql-iso-date';
import {
asNexusMethod,
list,
makeSchema,
nonNull,
nullable,
objectType,
queryType,
} from 'nexus';
export const DateTime = asNexusMethod(GraphQLDateTime, 'date');
const User = objectType({
name: 'User',
definition(t) {
t.nonNull.int('id');
t.string('name');
t.nonNull.string('email');
t.field('emailVerified', {type: DateTime});
t.field('createdAt', {type: nonNull(DateTime)});
t.field('updatedAt', {type: nonNull(DateTime)});
t.field('membership', {
type: Membership,
resolve: (parent, _, ctx) => {
return ctx.prisma.user
.findUnique({where: {id: parent.id}})
.membership();
},
});
},
});
const Membership = objectType({
name: 'Membership',
definition(t) {
t.nonNull.int('id');
t.nonNull.int('userId');
t.field('user', {
type: nonNull(User),
resolve: (parent, _, ctx) => {
return ctx.prisma.membership
.findUnique({where: {id: parent.id}})
.user();
},
});
t.nonNull.int('orgId');
t.field('org', {
type: nonNull(Org),
resolve: (parent, _, ctx) => {
return ctx.prisma.membership.findUnique({where: {id: parent.id}}).org();
},
});
t.nonNull.string('roleName');
t.field('role', {
type: nonNull(Role),
resolve: (parent, _, ctx) => {
return ctx.prisma.membership
.findUnique({where: {id: parent.id}})
.role();
},
});
},
});
// ... more fields
const Query = objectType({
name: 'Query',
definition(t) {
t.field('currentUser', {
type: User,
resolve: (root, args, ctx) => {
return ctx.prisma.user.findUnique({
where: {email: ctx.currentUserEmail},
});
},
});
},
});
export const schema = makeSchema({
types: [User, Membership, Query, DateTime],
});