Podobnie jak inne frameworki oparte na Node.js, Nest.js oferuje rozbudowany zestaw narzędzi do tworzenia solidnych i skalowalnych usług backendowych. Kluczowe jest zrozumienie, jak efektywnie zaimplementować operacje tworzenia, odczytu, aktualizacji i usuwania (CRUD), które są podstawowymi funkcjami w procesie budowy interfejsów API.
W tym artykule omówimy, jak skonstruować API REST oparte na CRUD w Nest.js, wykorzystując TypeORM i bazę danych PostgreSQL.
Pierwsze kroki z Nest.js
Aby rozpocząć, zainstaluj narzędzie wiersza poleceń Nest.js za pomocą poniższej komendy:
npm i -g @nestjs/cli
Następnie, utwórz nowy projekt, używając:
nest new crud-app
Narzędzie CLI poprosi Cię o wybranie menedżera pakietów. Wybierz preferowaną opcję. W naszym przypadku użyjemy npm, domyślnego menedżera pakietów dla Node.js.
CLI wygeneruje podstawową strukturę projektu Nest.js, zawierającą wszystkie wymagane pliki konfiguracyjne i początkowe zależności, niezbędne do uruchomienia aplikacji.
Na koniec, przejdź do katalogu projektu i uruchom serwer deweloperski:
cd crud-app
npm run start
Kod źródłowy tego projektu można znaleźć w repozytorium GitHub.
Utwórz bazę danych PostgreSQL
W tym poradniku wykorzystana zostanie instancja PostgreSQL w chmurze. Możesz również skonfigurować lokalną bazę danych PostgreSQL, instalując ją na systemie Windows, macOS lub Linux.
Aby skonfigurować instancję PostgreSQL w chmurze:


Konfiguracja połączenia z bazą danych
W katalogu głównym projektu utwórz plik `.env` i wklej adres URL połączenia z bazą danych w następujący sposób:
DATABASE_URL="<twój adres URL połączenia>"
Następnie zainstaluj wymagane pakiety:
npm install pg typeorm @nestjs/typeorm @nestjs/config
Stwórz moduł bazy danych za pomocą narzędzia CLI:
nest g module database
Otwórz plik `database/database.module.ts` i dodaj poniższy kod, który skonfiguruje połączenie z bazą danych:
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from '../users/models/user.entity';@Module({
imports: [
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],useFactory: async (configService: ConfigService) => ({
type: 'postgres',
url: configService.get('DATABASE_URL'),
entities: [User],
synchronize: true
}),
}),
],
})export class DatabaseModule {}
Moduł bazy danych zarządza połączeniem, konfigurując moduł TypeORM z niezbędnymi danymi, w tym adresem URL bazy danych.
Dodatkowo, definiuje on encję `User` w ramach konfiguracji, co opisuje strukturę danych i atrybuty przechowywane w tabeli bazy danych PostgreSQL.
Na tym etapie, Twój kod może generować błędy, ponieważ encja użytkownika nie została jeszcze utworzona. Zrobimy to w kolejnych krokach.
Aktualizacja pliku app.module.ts
Na koniec, zaktualizuj główny moduł aplikacji, aby włączyć konfigurację modułu bazy danych:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DatabaseModule } from './database/database.module';@Module({
imports: [
ConfigModule.forRoot({
envFilePath: '.env',
}),
DatabaseModule,
],controllers: [AppController],
providers: [AppService],
})export class AppModule {}
Zdefiniowanie modułu użytkowników
Moduł użytkowników służy jako centralny element, odpowiadający za zarządzanie logiką implementacji funkcjonalności API CRUD.
Uruchom poniższe polecenie w terminalu, aby utworzyć moduł użytkowników API:
nest g module users
Narzędzie CLI automatycznie zaktualizuje plik `app.module.ts`, aby odzwierciedlić wprowadzone zmiany, a także utworzy nowy moduł `users`. Zapewnia to prawidłową integrację nowego modułu z konfiguracją modułu aplikacji.
Utworzenie encji użytkownika
TypeORM jest biblioteką mapowania obiektowo-relacyjnego (ORM), która upraszcza interakcję z bazą danych w aplikacjach TypeScript, mapując obiekty JavaScript na tabele baz danych.
Tworząc encję użytkownika z TypeORM, definiujesz strukturę i atrybuty danych użytkownika w bazie danych PostgreSQL.
W katalogu `users` utwórz nowy plik `models/user.entity.ts` i dodaj następujący kod:
import { Entity, PrimaryGeneratedColumn, Column, } from "typeorm";@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;@Column()
name: string;@Column()
email: string;
}
Encja `User` opisuje strukturę danych użytkownika przechowywanych w bazie danych. Zawiera ona identyfikator jako kolumnę klucza podstawowego oraz kolumny `name` i `email` z odpowiadającymi im typami danych.
Utworzenie usługi API CRUD
Teraz, utwórz usługę API, która będzie zarządzać logiką operacji CRUD, używając następującego polecenia:
nest g service users
Otwórz plik `user-auth.service.ts` i dodaj ten kod:
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import {User} from './models/user.entity';@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private userRepository: Repository<User>,
) {}async findAll(): Promise<User[]> {
return this.userRepository.find();
}async findOne(id: number): Promise<User> {
return this.userRepository.findOne({ where: { id } });
}async create(user: Partial<User>): Promise<User> {
const newuser = this.userRepository.create(user);
return this.userRepository.save(newuser);
}async update(id: number, user: Partial<User>): Promise<User> {
await this.userRepository.update(id, user);
return this.userRepository.findOne({ where: { id } });
}async delete(id: number): Promise<void> {
await this.userRepository.delete(id);
}
}
Klasa `UsersService` definiuje różne metody API dedykowane obsłudze operacji CRUD. Metody te obejmują pobieranie wszystkich użytkowników, wyszukiwanie użytkownika po identyfikatorze, tworzenie nowego użytkownika, aktualizację istniejącego użytkownika oraz usuwanie użytkownika z bazy danych.
Zdefiniowanie kontrolera dla API
Utwórz kontroler, który będzie zarządzał punktami końcowymi API dla operacji związanych z użytkownikami:
nest g controller users
Dodaj poniższy kod do pliku `users.controller.ts`:
import { Controller, Get, Post, Body, Put, Param, Delete, NotFoundException, HttpCode } from '@nestjs/common';
import { UsersService } from './users.service';
import { User } from './models/user.entity';@Controller('api/users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}@Get()
async findAll(): Promise<User[]> {
return this.usersService.findAll();
}@Post()
@HttpCode(201)
async create(@Body() user: User): Promise<User> {
const createdUser = await this.usersService.create(user);
return createdUser;
}@Put(':id')
async update (@Param('id') id: number, @Body() user: User): Promise<any> {
await this.usersService.update(id, user);
return { message: 'User updated successfully' };
}@Delete(':id')
async delete(@Param('id') id: number): Promise<any> {
const user = await this.usersService.findOne(id);if (!user) {
throw new NotFoundException('User does not exist!');
}await this.usersService.delete(id);
return { message: 'User deleted successfully' };
}
}
Kontroler zarządza punktami końcowymi API dla operacji użytkownika. Obsługuje żądania GET do pobierania wszystkich użytkowników, żądania POST do tworzenia nowych użytkowników, PUT do aktualizacji istniejących i DELETE do usuwania użytkowników.
Wykorzystując `UsersService` i interakcję z encją `User`, kontroler ten zapewnia kompletne API do zarządzania operacjami użytkownika na danych przechowywanych w bazie danych.
Aktualizacja pliku users.module.ts
Na koniec, zaktualizuj plik `users.module.ts`, jak pokazano poniżej, aby upewnić się, że zawiera encję `User` i moduł TypeORM, który ustanawia połączenie z bazą danych.
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './models/user.entity';@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService]
})export class UsersModule {}
Uruchom serwer deweloperski, aby przetestować operacje CRUD za pomocą Postmana:
npm run start
Serwer powinien być dostępny na porcie 3000, a Ty możesz wysyłać zapytania API na adres http://localhost:3000/api/users.
Tworzenie aplikacji backendowych z Nest.js
Niezależnie od tego, czy tworzysz proste API REST, czy złożoną aplikację internetową, Nest.js oferuje szeroki zakres funkcji i możliwości do budowania niezawodnego backendu.
Nest.js oferuje bardziej ustrukturyzowane podejście do tworzenia projektów w porównaniu do Express.js. Gwarantuje to, że możesz efektywnie tworzyć, skalować i utrzymywać skomplikowane aplikacje dzięki zorganizowanemu i modułowemu podejściu projektowemu.
newsblog.pl