Gazar Avatar

GAZAR

EngineerEntrepreneurStoryteller

Building a GraphQL Server with Apollo Server, Prisma, and TypeScript

In recent years, GraphQL has gained immense popularity as a query language for APIs due to its flexibility and efficiency. Apollo Server is a GraphQL server implementation that simplifies the process of building GraphQL APIs, while Prisma offers a powerful ORM (Object-Relational Mapping) for database interactions. When combined with TypeScript, these tools provide a robust foundation for building scalable and type-safe GraphQL servers. In this article, we'll explore how to integrate Apollo Server with Prisma using TypeScript to create a GraphQL API.

mkdir apollo-prisma-server
cd apollo-prisma-server
npm init -y
npm install apollo-server graphql prisma @prisma/client typescript ts-node @types/node

Next, initialize TypeScript in the project:

npx tsc --init

Prisma simplifies database access by generating type-safe database client libraries based on your data model. Let's define our data model in Prisma. Create a new file called schema.prisma in the project root:

// schema.prisma
model User {
  id        Int      @id @default(autoincrement())
  name      String
  email     String   @unique
  posts     Post[]
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String
  author    User     @relation(fields: [authorId], references: [id])
  authorId  Int
}

Now, generate the Prisma client:

npx prisma generate

Setting Up Apollo Server:

Create a new file called index.ts in the project root to define our Apollo Server:

import * as yup from 'yup';
const createUserSchema = yup.object().shape({
  name: yup.string().required(),
  email: yup.string().email().required(),
});

const updateUserSchema = yup.object().shape({
  id: yup.number().required(),
  name: yup.string(),
  email: yup.string().email(),
});

const createPostSchema = yup.object().shape({
  title: yup.string().required(),
  content: yup.string().required(),
  authorId: yup.number().required(),
});

const updatePostSchema = yup.object().shape({
  id: yup.number().required(),
  title: yup.string(),
  content: yup.string(),
});

Next, let's update our resolver functions to perform input validation before executing mutations:

import { ValidationError } from 'yup';
const resolvers = {
  Mutation: {
    createUser: async (_, { data }) => {
      try {
        await createUserSchema.validate(data, { abortEarly: false });
        return prisma.user.create({ data });
      } catch (error) {
        if (error instanceof ValidationError) {
          throw new Error(error.errors.join(', '));
        }
        throw error;
      }
    },
    updateUser: async (_, { data }) => {
      try {
        await updateUserSchema.validate(data, { abortEarly: false });
        const { id, ...rest } = data;
        return prisma.user.update({
          where: { id },
          data: rest,
        });
      } catch (error) {
        if (error instanceof ValidationError) {
          throw new Error(error.errors.join(', '));
        }
        throw error;
      }
    },
    createPost: async (_, { data }) => {
      try {
        await createPostSchema.validate(data, { abortEarly: false });
        return prisma.post.create({ data });
      } catch (error) {
        if (error instanceof ValidationError) {
          throw new Error(error.errors.join(', '));
        }
        throw error;
      }
    },
    updatePost: async (_, { data }) => {
      try {
        await updatePostSchema.validate(data, { abortEarly: false });
        const { id, ...rest } = data;
        return prisma.post.update({
          where: { id },
          data: rest,
        });
      } catch (error) {
        if (error instanceof ValidationError) {
          throw new Error(error.errors.join(', '));
        }
        throw error;
      }
    },
  },
};

Then you can have the server

const server = new ApolloServer({
  typeDefs,
  resolvers,
});

server.listen().then(({ url }) => {
  console.log(`Server running at ${url}`);
});

This code defines our GraphQL schema, resolvers, and sets up an Apollo Server instance. We're using the Prisma client to interact with the database.

Now, let's start our Apollo Server:

npx ts-node index.ts

Your GraphQL server should now be running at the specified URL (typically http://localhost:4000). You can access the GraphQL Playground to interact with your API and execute queries.

Conclusion:

In this article, we've seen how to build a GraphQL server with Apollo Server, Prisma, and TypeScript. By leveraging the power of GraphQL for API queries, Prisma for database interactions, and TypeScript for type safety, we've created a robust and scalable backend for our applications. This setup allows for efficient development and maintenance of GraphQL APIs with confidence in type safety and data integrity.

prismagraphqlserveryupapollo

Comments

Please log in to post a comment.

No comments yet.

Be the first to comment!