implementing-graphql-apis-with-nestjs-and-prisma-orm.html

Implementing GraphQL APIs with NestJS and Prisma ORM

In the modern era of web development, the demand for efficient and flexible APIs is at an all-time high. GraphQL has emerged as a powerful alternative to REST APIs, offering developers the ability to request only the data they need. When combined with NestJS—a progressive Node.js framework—and Prisma ORM—a robust database toolkit—creating GraphQL APIs becomes a streamlined and efficient process. This article will guide you through the implementation of GraphQL APIs using NestJS and Prisma ORM, providing code snippets and actionable insights along the way.

Understanding the Basics

What is GraphQL?

GraphQL is a query language for APIs and a runtime for executing those queries with existing data. It allows clients to request specific data structures, leading to improved performance and reduced data over-fetching.

Why NestJS?

NestJS is a framework for building efficient and scalable server-side applications. It leverages TypeScript's capabilities and is built around the modular architecture that can be easily tested, maintained, and extended.

What is Prisma ORM?

Prisma is an open-source database toolkit that simplifies database access and management. It provides a type-safe query builder and migrations, making database interactions easier and more reliable.

Setting Up Your Development Environment

To get started, ensure you have Node.js and npm installed on your machine. You can check your installation by running:

node -v
npm -v

Step 1: Initialize a New NestJS Project

Start by creating a new NestJS project. Open your terminal and run:

npm i -g @nestjs/cli
nest new graphql-nestjs-prisma
cd graphql-nestjs-prisma

Step 2: Install Required Packages

Next, you need to install the necessary packages for GraphQL and Prisma:

npm install @nestjs/graphql @nestjs/apollo apollo-server-express prisma --save
npm install @prisma/client

Step 3: Initialize Prisma

To set up Prisma ORM, initialize it in your project:

npx prisma init

This command creates a new prisma folder containing a schema.prisma file. Update the datasource block to configure your database connection. For example, for a PostgreSQL database:

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

Step 4: Define Your Database Models

In the schema.prisma file, you can define your models. Here’s an example of a User model:

model User {
  id    Int    @id @default(autoincrement())
  name  String
  email String @unique
}

After defining your models, run the following command to generate the Prisma Client:

npx prisma migrate dev --name init

This command creates a new migration and applies it to your database.

Building the GraphQL API

Step 5: Configure GraphQL Module

Open the app.module.ts file and set up the GraphQL module:

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { UserModule } from './user/user.module';

@Module({
  imports: [
    GraphQLModule.forRoot({
      autoSchemaFile: 'schema.gql',
    }),
    UserModule,
  ],
})
export class AppModule {}

Step 6: Create User Module

Generate a user module:

nest g module user
nest g resolver user
nest g service user

Step 7: Implement User Resolver

In the user.resolver.ts file, implement the resolver methods to handle GraphQL queries and mutations:

import { Resolver, Query, Mutation, Args } from '@nestjs/graphql';
import { UserService } from './user.service';
import { User } from './user.model';
import { CreateUserInput } from './create-user.input';

@Resolver(of => User)
export class UserResolver {
  constructor(private userService: UserService) {}

  @Query(returns => [User])
  async users() {
    return this.userService.findAll();
  }

  @Mutation(returns => User)
  async createUser(@Args('input') input: CreateUserInput) {
    return this.userService.create(input);
  }
}

Step 8: Implement User Service

In the user.service.ts file, implement the service methods:

import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma.service';
import { CreateUserInput } from './create-user.input';
import { User } from './user.model';

@Injectable()
export class UserService {
  constructor(private prisma: PrismaService) {}

  async findAll(): Promise<User[]> {
    return this.prisma.user.findMany();
  }

  async create(data: CreateUserInput): Promise<User> {
    return this.prisma.user.create({ data });
  }
}

Step 9: Create User Model and Input Types

Define the User model and CreateUserInput type in user.model.ts and create-user.input.ts respectively:

import { ObjectType, Field, Int } from '@nestjs/graphql';

@ObjectType()
export class User {
  @Field(type => Int)
  id: number;

  @Field()
  name: string;

  @Field()
  email: string;
}

And for the input:

import { InputType, Field } from '@nestjs/graphql';

@InputType()
export class CreateUserInput {
  @Field()
  name: string;

  @Field()
  email: string;
}

Running Your Application

Step 10: Start the NestJS Server

Now that everything is set up, start your application:

npm run start:dev

Visit http://localhost:3000/graphql to access the GraphQL playground. You can test your queries and mutations here. For example, to create a user:

mutation {
  createUser(input: { name: "John Doe", email: "john@example.com" }) {
    id
    name
    email
  }
}

Conclusion

Implementing GraphQL APIs with NestJS and Prisma ORM offers a modern approach to building scalable and efficient web applications. By following the steps outlined in this guide, you can set up a robust system that leverages the strengths of each technology. Whether you’re building a new project or enhancing an existing one, integrating these tools will provide you with the flexibility and performance needed in today’s development landscape.

With this foundational knowledge, you’re now equipped to dive deeper into advanced features, such as authentication, pagination, and subscriptions, to further enhance your GraphQL API. Happy coding!

SR
Syed
Rizwan

About the Author

Syed Rizwan is a Machine Learning Engineer with 5 years of experience in AI, IoT, and Industrial Automation.