API с Typescript + Nest + TypeORM + Postgres + Docker

API с Typescript + Nest + TypeORM + Postgres + Docker

В этой статье я покажу вам, как создать проект с использованием TypeScript, Nest, Postgres, Docker и как запустить базу данных.

TypeScript - это статически типизированный язык, который является строгим синтаксическим супермножеством JavaScript. Он предлагает улучшенную безопасность типов и поддержку инструментария, что делает его популярным выбором для крупномасштабных проектов.

Nest - это фреймворк для создания эффективных, масштабируемых серверных приложений Node.js. Он предоставляет структуру и ряд функций, облегчающих разработку и тестирование приложений.

Postgres - мощная реляционная система управления базами данных с открытым исходным кодом, которая хорошо подходит для сложных структур данных и крупномасштабной обработки данных.

TypeORM - это инструмент объектно-реляционного отображения (ORM) с открытым исходным кодом, который обеспечивает взаимодействие с реляционными базами данных, такими как MySQL, PostgreSQL и SQLite. Он помогает вам писать код, связанный с базами данных, используя объектно-ориентированное программирование на TypeScript или JavaScript, вместо того чтобы писать необработанные SQL-запросы. TypeORM предлагает множество функций, таких как управление транзакциями, миграция баз данных, пул соединений и т.д., что упрощает работу с базами данных в ваших приложениях.

Docker - это платформа контейнеризации, которая упрощает развертывание и запуск приложений в различных средах. Мы запустим базу данных Postgres и поддерживающий ее сервис в docker.

Требования

Nest:

Сначала установите nest-clinpm i -g @nestjs/cli

Затем создайте новый проект с помощью команды nest clinest new project-name

Выберите: npm для менеджера пакетов,

Далее, введите в папку проектаcd project-name

База данных PostgreSQL

Установите pgnpm install pg —save

TypeORM

Установите TypeOrmnpm install —save @nestjs/typeorm typeorm postgres

Откройте проект в вашей IDE

В app.module.ts добавьте подключение к базе данных с помощью TypeOrmModule.forRoot():

// app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'root',
      password: 'password',
      database: 'postgres',
      entities: [`${__dirname}/typeorm/entities/*{.js,.ts}`],
      synchronize: true, // do not use in prod
    }),
  ],
})
export class AppModule {}

BTW: вы можете удалить app.service и app.controller

Теперь мы должны создать наш первый модуль с помощью nest cli:

nest g resource modules/users

выберите REST API в терминалевыберите ‘yes’ для генерации точек входа CRUD

После создания модуля мы должны организовать наш проект следующим образом:

  • 1) создайте несколько папок с названиями: typeorm > database / entities / seeds
  • 2) создайте data-source.ts, main.seed.ts и user.seed.ts
  • 3) переместите пользовательскую сущность в папки с сущностями
/src/typeorm
├── database
│   └── data-source.ts
├── seeds
│   └── main.seed.ts
└── entities
    └── user.entity.ts *(generated by the script)*

вставьте в файлы приведенный ниже код:

// users.entity.ts
import { Column, CreateDateColumn, DeleteDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';

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

  @Column()
  name: string;

  @Column()
  email: string;

  @Column()
  active: boolean;

  @Column()
  birthday: Date;

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;

  @DeleteDateColumn()
  deletedAt: Date;
}
// users.service.ts
import { Injectable } from '@nestjs/common';
import { User } from 'src/typeorm/entities/user.entity';
import { DataSource } from 'typeorm';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';

@Injectable()
export class UsersService {
  constructor(private dataSource: DataSource) {}
  private userRepository = this.dataSource.getRepository(User);

  async create(createUserDto: CreateUserDto) {
    return this.userRepository.save(createUserDto);
  }

  async findAll(): Promise<User[]> {
    return this.userRepository.find();
  }

  async findOne(id: number) {
    return this.userRepository.findOneBy({ id });
  }

  async update(id: number, updateUserDto: UpdateUserDto) {
    let user = await this.findOne(id);
    user = { ...user, ...updateUserDto };
    return await this.userRepository.save(user);
  }

  async remove(id: number) {
    const user = await this.findOne(id);
    return await this.userRepository.softRemove(user);
  }
}
// data-source.ts
import { DataSource, DataSourceOptions } from 'typeorm';

export const dataSourceOptions: DataSourceOptions = {
  type: 'postgres',
  host: 'localhost',
  port: 5432,
  username: 'root',
  password: 'password',
  database: 'postgres',
  entities: ['src/**/*.entity{.js,.ts}'],
};

export default new DataSource(dataSourceOptions);
// main.seed.ts
import { DataSource } from 'typeorm';
import { dataSourceOptions } from '../database/data-source';
import { User } from '../entities/user.entity';

const dataSource = new DataSource(dataSourceOptions);
const userRepository = dataSource.getRepository(User);

async function connect() {
  try {
    if (dataSource.isInitialized) {
      await dataSource.destroy();
    }
    await dataSource.initialize();
    console.log('Data Source has been initialized!');
  } catch (err) {
    console.error('Error during Data Source connect', err);
  }
}

async function disconnect() {
  try {
    await dataSource.destroy();

    console.log('Data Source disconnected!');
  } catch (err) {
    console.error('Error during Data Source disconnect', err);
  }
}

async function seed() {
  const UserSeed = () => [
    {
      name: 'John Doe',
      email: '[email protected]',
      active: true,
      birthday: '1990-01-01',
    },
    {
      name: 'Jane Doe',
      email: '[email protected]',
      active: false,
      birthday: '1990-01-31',
    },
    {
      name: 'Josh Doe',
      email: '[email protected]',
      active: true,
      birthday: '2020-12-31',
    },
  ];

  await userRepository.save(UserSeed());
  console.log('created seeds');
}

async function runSeed() {
  await connect();
  console.log('connected');
  await seed();
  console.log('seed done');
  await disconnect();
  console.log('disconnected');
}

runSeed();

Теперь мы должны создать наш файл ‘docker-compose.yml’ в корневой папке, а затем запустить sudo docker-compose up:

version: '3.1'

services:
  db:
    image: postgres:14.2-alpine
    restart: always
    environment:
      POSTGRES_USER: "root"
      POSTGRES_PASSWORD: "password"
      POSTGRES_DB: "postgres"
    ports:
      - "5432:5432"

Несколько полезных команд docker:

  • sudo docker ps to list all containers
  • sudo docker stop my_container_name to stop a specific container

Теперь добавьте скрипт в файл package.json

// package.json
"seed":"npx ts-node src/typeorm/seeds/main.seed.ts",

в новом терминале на IDE запустите код npm start для синхронизации базы данных

Завершите приложение, а затем запустите скрипт npm run seed для заполнения базы данных.

Готово! Теперь, если вы запустите npm start и отправите GET-запрос на localhost:3000/users, вы должны получить всех пользователей из seed.