Come creare un’API REST CRUD Nest.js utilizzando TypeORM e PostgreSQL

Come altri framework Node.js, Nest.js fornisce un toolkit completo per la creazione di servizi di backend robusti e scalabili. Tuttavia, è importante capire come implementare in modo efficiente le operazioni di creazione, lettura, aggiornamento ed eliminazione (CRUD) in Nest.js: queste sono le operazioni più fondamentali nello sviluppo delle API.

Scopri come creare un’API REST CRUD Nest.js utilizzando TypeORM e un database PostgreSQL.

Guida introduttiva a Nest.js

Per iniziare, installa lo strumento a riga di comando Nest.js:

 npm i -g @nestjs/cli 

Successivamente, crea un nuovo progetto eseguendo:

 nest new crud-app 

Lo strumento CLI ti chiederà di scegliere un gestore di pacchetti, scegli l’opzione che ritieni più preferibile. Useremo npm, il gestore di pacchetti Node.

L’interfaccia a riga di comando eseguirà l’impalcatura di un progetto Nest.js di base con tutti i file di configurazione richiesti e le dipendenze iniziali necessarie per eseguire l’applicazione.

Infine, vai alla directory del progetto e avvia il server di sviluppo.

 cd crud-app
npm run start

Puoi trovare il codice di questo progetto nel suo file Git Hub deposito.

Crea un database PostgreSQL

Questo tutorial utilizza un’istanza PostgreSQL cloud, ma puoi invece configurare un database PostgreSQL locale. Puoi installare PostgreSQL su Windows, su macOS o su Linux.

Per configurare un’istanza PostgreSQL cloud:

  • Vai a ElephantSQLregistrati e accedi alla pagina di panoramica del tuo account.
  • Fai clic sul pulsante Crea nuova istanza nella sezione in alto a sinistra della pagina per creare una nuova istanza per la tua applicazione.
  • Inserisci il nome della tua istanza, scegli il piano gratuito e infine seleziona la regione per completare il processo di configurazione.
  • Dopo aver creato l’istanza del database, vai alla pagina delle impostazioni e copia l’URL del database fornito.
  • Configurare la connessione al database

    Nella directory principale del tuo progetto, crea un file .env e incolla l’URL di connessione al database come segue:

     DATABASE_URL="<your connection url here>" 

    Ora installa questi pacchetti:

     npm install pg typeorm @nestjs/typeorm @nestjs/config 

    Successivamente, vai avanti e crea un modulo di database utilizzando lo strumento CLI.

     nest g module database 

    Apri il file database/database.module.ts e aggiungi il seguente codice di configurazione del database:

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

    Questo modulo database gestisce la connessione configurando il modulo TypeORM con il parametro di connessione richiesto, l’URL del database.

    Inoltre, definisce l’entità Utente come parte della configurazione che specifica la struttura e le proprietà dei dati archiviati nella tabella del database PostgreSQL.

    In questa fase, il tuo codice genererà probabilmente un errore perché non hai ancora creato l’entità utenti. Lo farai nei seguenti passaggi.

    Aggiorna il file app.module.ts

    Infine, aggiorna il modulo principale dell’applicazione per includere la configurazione per il modulo database.

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

    Definire un modulo utenti

    Il modulo utenti funge da componente centralizzato, responsabile dell’incapsulamento e della gestione della logica richiesta per implementare la funzionalità CRUD dell’API.

    Esegui questo comando da terminale per creare il modulo utenti dell’API.

     nest g module users 

    Lo strumento CLI aggiorna automaticamente il file app.module.ts per riflettere le modifiche apportate, oltre a creare il modulo utente. Ciò garantisce che il modulo appena creato, users, sia correttamente integrato nella configurazione del modulo dell’applicazione.

    Crea un’entità utente

    TypeORM è una libreria ORM (Object-Relational Mapping) che semplifica le interazioni del database nelle applicazioni che utilizzano TypeScript mappando gli oggetti JavaScript alle tabelle del database.

    Creando un’entità utente utilizzando TypeORM, definisci la struttura e le proprietà dei dati utente nel database PostgreSQL.

    Nella directory degli utenti, crea un nuovo models/user.entity.ts e aggiungi il seguente codice.

     import { Entity, PrimaryGeneratedColumn, Column, } from "typeorm";

    @Entity()
    export class User {
        @PrimaryGeneratedColumn()
        id: number;

        @Column()
        name: string;

        @Column()
        email: string;
    }

    L’entità Utente definisce la struttura dei dati utente archiviati nel database. In questo caso, si tratta dell’id come colonna della chiave primaria, delle colonne name e email e delle proprietà corrispondenti.

    Crea il servizio API CRUD

    Ora, crea il servizio API che gestirà la logica per le operazioni CRUD eseguendo il comando seguente:

     nest g service users 

    Apri il file user-auth.service.ts e aggiungi questo codice:

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

    Questa classe UsersService definisce vari metodi API dedicati alla gestione delle operazioni CRUD. Questi metodi includono il recupero dei dati di tutti gli utenti, la ricerca di un utente specifico utilizzando il proprio numero ID, la creazione di un nuovo utente, l’aggiornamento di un utente esistente e un metodo per eliminare i dati di un utente specifico nel database.

    Definire un controller per l’API

    Crea un controller che gestirà gli endpoint API per le operazioni relative agli utenti.

     nest g controller users 

    Successivamente, aggiungi il codice seguente al file 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' };
      }
    }

    Il controller gestisce gli endpoint API per le operazioni degli utenti. Gestisce le richieste GET per recuperare tutti gli utenti, le richieste POST per creare nuovi utenti, le richieste PUT per aggiornare gli utenti esistenti e le richieste DELETE per eliminare gli utenti.

    Utilizzando UsersService e interagendo con l’entità Utente, questo controller fornisce un’API completa per la gestione delle operazioni relative all’utente sui dati archiviati nel database.

    Aggiorna il file users.module.ts

    Infine, aggiorna il file users.module.ts come mostrato di seguito per assicurarti di incorporare l’entità Utente e il modulo TypeORM, che stabilisce la connessione al database.

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

    Infine, vai avanti e avvia il server di sviluppo per testare le operazioni CRUD utilizzando Postman.

     npm run start 

    Il server verrà avviato sulla porta 3000 e puoi inviargli richieste API a http://localhost:3000/api/users.

    Creazione di applicazioni back-end con Nest.js

    Che tu stia sviluppando una semplice API REST o un’app Web complessa, Nest.js offre un set completo di funzionalità e capacità per costruire un sistema di back-end affidabile e robusto.

    Nest.js offre un approccio più strutturato allo sviluppo del progetto rispetto a Express.js. Ciò garantisce la possibilità di creare, ridimensionare e gestire con sicurezza applicazioni complesse, grazie al modello di progettazione organizzato e modulare.