DEV Community

Nadim Chowdhury
Nadim Chowdhury

Posted on

How to connect Nest.js backend with PostgreSQL for GraphQL API?

To connect a Nest.js backend with PostgreSQL for a GraphQL API, you'll generally use TypeORM, which is an ORM that can handle various SQL database interactions in a structured and scalable way. Here’s a step-by-step guide to setting up this connection and integrating it into your GraphQL API.

1. Install Necessary Packages

First, you need to install TypeORM along with pg, the PostgreSQL driver:

npm install @nestjs/typeorm typeorm pg
Enter fullscreen mode Exit fullscreen mode

2. Configure TypeORM Module

Configure TypeORM in your Nest.js application by modifying the app.module.ts file to include TypeORM module settings. You need to specify connection settings for your PostgreSQL database.

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'your_username',
      password: 'your_password',
      database: 'your_database',
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true,  // Use only in development, remove in production!
    }),
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      autoSchemaFile: true,
    }),
    // Your other modules
  ],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

3. Create Entity Definitions

Entities in TypeORM are equivalent to tables in your PostgreSQL database. Here’s how you could define an entity for a Recipe:

import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
import { Field, ObjectType, ID } from '@nestjs/graphql';

@ObjectType()
@Entity()
export class Recipe {
  @Field(() => ID)
  @PrimaryGeneratedColumn()
  id: number;

  @Field()
  @Column()
  title: string;

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

4. Integrate Entity with GraphQL

To integrate this entity with GraphQL, you need to update the resolver to use a service that interacts with the database. First, create a service:

nest generate service recipe
Enter fullscreen mode Exit fullscreen mode

Now, implement the service:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Recipe } from './recipe.entity';
import { CreateRecipeInput, UpdateRecipeInput } from './dto/recipe.input';

@Injectable()
export class RecipeService {
  constructor(
    @InjectRepository(Recipe)
    private recipeRepository: Repository<Recipe>,
  ) {}

  findAll(): Promise<Recipe[]> {
    return this.recipeRepository.find();
  }

  findOne(id: number): Promise<Recipe> {
    return this.recipeRepository.findOneBy({ id });
  }

  create(createRecipeInput: CreateRecipeInput): Promise<Recipe> {
    const newRecipe = this.recipeRepository.create(createRecipeInput);
    return this.recipeRepository.save(newRecipe);
  }

  async update(id: number, updateRecipeInput: UpdateRecipeInput): Promise<Recipe> {
    const recipe = await this.recipeRepository.preload({
      id: id,
      ...updateRecipeInput,
    });
    if (!recipe) {
      throw new Error('Recipe not found');
    }
    return this.recipeRepository.save(recipe);
  }

  async remove(id: number): Promise<void> {
    await this.recipeRepository.delete(id);
  }
}
Enter fullscreen mode Exit fullscreen mode

5. Update Resolver to Use Service

Finally, modify your resolver to use the service for handling database operations:

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

@Resolver(() => Recipe)
export class RecipeResolver {
  constructor(private readonly recipeService: RecipeService) {}

  @Query(() => [Recipe])
  recipes() {
    return this.recipeService.findAll();
  }

  @Query(() => Recipe, { nullable: true })
  recipe(@Args('id', { type: () => ID }) id: number) {
    return this.recipeService.findOne(id);
  }

  @Mutation(() => Recipe)
  createRecipe(@Args('createRecipeData') createRecipeData: CreateRecipeInput) {
    return this.recipeService.create(createRecipeData);
  }

  @Mutation(() => Recipe)
  updateRecipe(@Args('id') id: number, @Args('updateRecipeData') updateRecipeData: UpdateRecipeInput) {
    return this.recipeService.update(id, updateRecipeData);
  }

  @Mutation(() => Boolean)
  deleteRecipe

(@Args('id', { type: () => ID }) id: number) {
    return this.recipeService.remove(id).then(() => true);
  }
}
Enter fullscreen mode Exit fullscreen mode

This setup provides a robust structure for handling CRUD operations in your GraphQL API, leveraging the power of TypeORM for database interactions with PostgreSQL.

Disclaimer: This content is generated by AI.

Top comments (0)