DEV Community

Cover image for How to do CRUD in GraphQL Nest.js API?
Nadim Chowdhury
Nadim Chowdhury

Posted on

How to do CRUD in GraphQL Nest.js API?

Implementing CRUD operations in a GraphQL API using Nest.js involves setting up mutations and queries that correspond to create, read, update, and delete actions. Below, I'll outline how to implement these CRUD operations using a simplified example with a Recipe entity.

1. Setup the GraphQL Module

Assuming you have already set up your Nest.js project with GraphQL as outlined in the previous response, ensure your GraphQL module is configured correctly in app.module.ts.

2. Define the GraphQL Types

Using the code-first approach, define your entity as a GraphQL type. Here’s the Recipe class:

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

@ObjectType()
export class Recipe {
  @Field(() => ID)
  id: string;

  @Field()
  title: string;

  @Field({ nullable: true })
  description?: string;
}
Enter fullscreen mode Exit fullscreen mode

3. Create Input Types

For mutations, you will need input types. Here's how you can define them for creating and updating recipes:

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

@InputType()
export class CreateRecipeInput {
  @Field()
  title: string;

  @Field({ nullable: true })
  description?: string;
}

@InputType()
export class UpdateRecipeInput {
  @Field(() => ID)
  id: string;

  @Field({ nullable: true })
  title?: string;

  @Field({ nullable: true })
  description?: string;
}
Enter fullscreen mode Exit fullscreen mode

4. Define Resolvers

Create a resolver for handling queries and mutations:

import { Resolver, Query, Mutation, Args } from '@nestjs/graphql';
import { Recipe } from './entities/recipe.entity';
import { CreateRecipeInput, UpdateRecipeInput } from './dto/recipe.input';

@Resolver(of => Recipe)
export class RecipeResolver {
  private recipes: Recipe[] = []; // This will act as our in-memory database

  @Query(returns => Recipe, { nullable: true })
  async recipe(@Args('id', { type: () => ID }) id: string): Promise<Recipe> {
    return this.recipes.find(recipe => recipe.id === id);
  }

  @Query(returns => [Recipe])
  async recipes(): Promise<Recipe[]> {
    return this.recipes;
  }

  @Mutation(returns => Recipe)
  async createRecipe(@Args('createRecipeData') createRecipeData: CreateRecipeInput): Promise<Recipe> {
    const recipe = {
      id: Math.random().toString(), // generate a random ID for example purposes
      ...createRecipeData,
    };
    this.recipes.push(recipe);
    return recipe;
  }

  @Mutation(returns => Recipe)
  async updateRecipe(@Args('updateRecipeData') updateRecipeData: UpdateRecipeInput): Promise<Recipe> {
    const recipe = this.recipes.find(r => r.id === updateRecipeData.id);
    if (!recipe) {
      throw new Error('Recipe not found');
    }
    Object.assign(recipe, updateRecipeData);
    return recipe;
  }

  @Mutation(returns => Boolean)
  async deleteRecipe(@Args('id', { type: () => ID }) id: string): Promise<boolean> {
    const index = this.recipes.findIndex(recipe => recipe.id === id);
    if (index === -1) {
      throw new Error('Recipe not found');
    }
    this.recipes.splice(index, 1);
    return true;
  }
}
Enter fullscreen mode Exit fullscreen mode

5. Connect to a Real Database

In a real application, you should replace the in-memory array with a database. You can integrate with a database like PostgreSQL using TypeORM or any other database module. Use repositories or custom services to handle data operations.

6. Considerations for Production

  • Validation: Add DTO validation using class-validator to ensure data integrity.
  • Authorization: Secure your API using guards and decorators to manage who can perform CRUD operations.
  • Error Handling: Implement proper error handling to manage and respond to errors gracefully.
  • Testing: Write unit and integration tests for your resolvers and services to ensure they work as expected.

This example demonstrates basic CRUD operations using Nest.js and GraphQL. The code-first approach allows you to maintain your GraphQL schema in TypeScript, making it easy to refactor and understand.

Disclaimer: This content is generated by AI.

Top comments (0)