DEV Community

Nadim Chowdhury
Nadim Chowdhury

Posted on • Edited 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.

Support My Work ❤️

If you enjoy my content and find it valuable, consider supporting me by buying me a coffee. Your support helps me continue creating and sharing useful resources. Thank you!

Connect with Me 🌍

Let’s stay connected! You can follow me or reach out on these platforms:

🔹 YouTube – Tutorials, insights & tech content

🔹 LinkedIn – Professional updates & networking

🔹 GitHub – My open-source projects & contributions

🔹 Instagram – Behind-the-scenes & personal updates

🔹 X (formerly Twitter) – Quick thoughts & tech discussions

I’d love to hear from you—whether it’s feedback, collaboration ideas, or just a friendly hello!

Disclaimer

This content has been generated with the assistance of AI. While I strive for accuracy and quality, please verify critical information independently.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Jetbrains image

Build Secure, Ship Fast

Discover best practices to secure CI/CD without slowing down your pipeline.

Read more