How to connect Nest.js backend with PostgreSQL for GraphQL API?
Published: 2024-05-17 13:33:07

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:

```bash
npm install @nestjs/typeorm typeorm pg
```

### 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.

```typescript
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 {}
```

### 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`:

```typescript
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;
}
```

### 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:

```bash
nest generate service recipe
```

Now, implement the service:

```typescript
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);
  }
}
```

### 5. Update Resolver to Use Service

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

```typescript
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);
  }
}
```

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.