БыстроС созданиС CRUD с nest, @nestjsx/crud ΠΈ TestMace

БыстроС созданиС CRUD с nest, @nestjsx/crud ΠΈ TestMace

Π’ настоящСС врСмя REST API стал стандартом Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ web-ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ, позволяя Ρ€Π°Π·Π±ΠΈΡ‚ΡŒ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ Π½Π° нСзависимыС части. Для UI Π½Π° Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ популярныС Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠΈ Ρ‚ΠΈΠΏΠ° Angular, React, Vue ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅. Π Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΆΠ΅ backend ΠΌΠΎΠ³ΡƒΡ‚ Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ ΠΈΠ· большого разнообразия языков ΠΈ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠΎΠ². БСгодня я Π±Ρ‹ Ρ…ΠΎΡ‚Π΅Π» ΠΏΠΎΠ³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ΡŒ ΠΎ Ρ‚Π°ΠΊΠΎΠΌ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠ΅ ΠΊΠ°ΠΊ NestJS. ΠœΡ‹ Π² TestMace Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Π΅Π³ΠΎ для Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΡ… ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠ². Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ nest ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ @nestjsx/crud, ΠΌΡ‹ создадим простоС CRUD ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅.

ΠŸΠΎΡ‡Π΅ΠΌΡƒ NestJS

Π’ послСднСС врСмя Π² JavaScript сообщСствС появилось достаточно ΠΌΠ½ΠΎΠ³ΠΎ backend Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠΎΠ². И Ссли Π² ΠΏΠ»Π°Π½Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»Π° ΠΎΠ½ΠΈ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ схоТиС с Nest возмоТности, Ρ‚ΠΎ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΎΠ½ Ρ‚ΠΎΡ‡Π½ΠΎ Π²Ρ‹ΠΈΠ³Ρ€Ρ‹Π²Π°Π΅Ρ‚ β€” это Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°. Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ возмоТности NestJS ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠΌΡ‹ΡˆΠ»Π΅Π½Π½Ρ‹Π΅ прилоТСния ΠΈ ΠΌΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ Π½Π° большиС ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹:

  • использованиС TypeScript Π² качСствС основного языка Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ. Π₯отя NestJS ΠΈ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ JavaScript, Ρ‡Π°ΡΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»Π° ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ, особСнно Ссли Ρ€Π΅Ρ‡ΡŒ ΠΈΠ΄Π΅Ρ‚ ΠΎ сторонних ΠΏΠ°ΠΊΠ΅Ρ‚Π°Ρ…;
  • Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ DI ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°, Ρ‡Ρ‚ΠΎ позволяСт ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ слабосвязанныС ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹;
  • Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π» самого Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠ° Ρ€Π°Π·Π±ΠΈΡ‚ Π½Π° нСзависимыС взаимозамСняСмыС ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹. НапримСр, ΠΏΠΎΠ΄ ΠΊΠ°ΠΏΠΎΡ‚ΠΎΠΌ Π² качСствС Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠ° ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΊΠ°ΠΊ express, Ρ‚Π°ΠΊ ΠΈ fastify, для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π‘Π” nest ΠΈΠ· ΠΊΠΎΡ€ΠΎΠ±ΠΊΠΈ прСдоставляСт Π±ΠΈΠ½Π΄ΠΈΠ½Π³ΠΈ ΠΊ typeorm, mongoose, sequelize;
  • NestJS Π½Π΅ зависит ΠΎΡ‚ ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΡ‹ ΠΈ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ REST, GraphQL, Websockets, gRPC ΠΈ Ρ‚.Π΄.

Π‘Π°ΠΌ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ Π²Π΄ΠΎΡ…Π½ΠΎΠ²Π»Π΅Π½ frontend Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠΎΠΌ Angular ΠΈ ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ‚ΡƒΠ°Π»ΡŒΠ½ΠΎ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΌΠ½ΠΎΠ³ΠΎ ΠΎΠ±Ρ‰Π΅Π³ΠΎ с Π½ΠΈΠΌ.

Установка NestJS ΠΈ Ρ€Π°Π·Π²Π΅Ρ€Ρ‚Ρ‹Π²Π°Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°

Nest содСрТит ΠΏΠ°ΠΊΠ΅Ρ‚ nest/cli, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ позволяСт быстро Ρ€Π°Π·Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ каркас прилоТСния. Установим глобально Π΄Π°Π½Π½Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚:

npm install --global @nest/cli

ПослС установки сгСнСрируСм Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ каркас нашСго прилоТСния с ΠΈΠΌΠ΅Π½Π΅ΠΌ nest-rest. ДСлаСтся это с использованиС ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ nest new nest-rest.

nest new nest-rest

dmitrii@dmitrii-HP-ZBook-17-G3:~/projects $ nest new nest-rest
  We will scaffold your app in a few seconds..

CREATE /nest-rest/.prettierrc (51 bytes)
CREATE /nest-rest/README.md (3370 bytes)
CREATE /nest-rest/nest-cli.json (84 bytes)
CREATE /nest-rest/nodemon-debug.json (163 bytes)
CREATE /nest-rest/nodemon.json (67 bytes)
CREATE /nest-rest/package.json (1805 bytes)
CREATE /nest-rest/tsconfig.build.json (97 bytes)
CREATE /nest-rest/tsconfig.json (325 bytes)
CREATE /nest-rest/tslint.json (426 bytes)
CREATE /nest-rest/src/app.controller.spec.ts (617 bytes)
CREATE /nest-rest/src/app.controller.ts (274 bytes)
CREATE /nest-rest/src/app.module.ts (249 bytes)
CREATE /nest-rest/src/app.service.ts (142 bytes)
CREATE /nest-rest/src/main.ts (208 bytes)
CREATE /nest-rest/test/app.e2e-spec.ts (561 bytes)
CREATE /nest-rest/test/jest-e2e.json (183 bytes)

? Which package manager would you ️ to use? yarn
 Installation in progress... 

  Successfully created project nest-rest
  Get started with the following commands:

$ cd nest-rest
$ yarn run start

                          Thanks for installing Nest 
                 Please consider donating to our open collective
                        to help us maintain this package.

                 Donate: https://opencollective.com/nest

Π’ качСствС ΠΏΠ°ΠΊΠ΅Ρ‚Π½ΠΎΠ³ΠΎ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π° ΠΌΡ‹ Π²Ρ‹Π±Π΅Ρ€Π΅ΠΌ yarn.
На Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ сСрвСр ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ npm start ΠΈ пройдя ΠΏΠΎ адрСсу http://localhost:3000 ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π»ΠΈΡ†Π΅Π·Ρ€Π΅Ρ‚ΡŒ Π³Π»Π°Π²Π½ΡƒΡŽ страницу. Однако ΠΌΡ‹ Π½Π΅ для этого здСсь ΡΠΎΠ±Ρ€Π°Π»ΠΈΡΡŒ ΠΈ двигаСмся дальшС.

НастраиваСм Ρ€Π°Π±ΠΎΡ‚Ρƒ с Π±Π°Π·ΠΎΠΉ

Π’ качСствС Π‘Π£Π‘Π” для Π΄Π°Π½Π½ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠΈ я Π²Ρ‹Π±Ρ€Π°Π» PostrgreSQL. О вкусах Π½Π΅ спорят, ΠΏΠΎ ΠΌΠΎΠ΅ΠΌΡƒ мнСнию, это Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ зрСлая Π‘Π£Π‘Π”, ΠΎΠ±Π»Π°Π΄Π°ΡŽΡ‰Π°Ρ всСми Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹ΠΌΠΈ возмоТностями. Как ΡƒΠΆΠ΅ Π±Ρ‹Π»ΠΎ сказано, для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π±Π°Π·Π°ΠΌΠΈ Π΄Π°Π½Π½Ρ‹Ρ… Nest прСдоставляСт ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡŽ с Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚Π°ΠΌΠΈ. Π’.ΠΊ. ΠΌΠΎΠΉ Π²Ρ‹Π±ΠΎΡ€ ΠΏΠ°Π» Π½Π° PostgreSQL, Ρ‚ΠΎ Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ TypeORM Π² качСствС ORM. Установим Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ для ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ с Π±Π°Π·ΠΎΠΉ Π΄Π°Π½Π½Ρ‹Ρ…:

yarn add typeorm @nestjs/typeorm pg

По порядку, для Ρ‡Π΅Π³ΠΎ Π½ΡƒΠΆΠ΅Π½ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚:

  1. typeorm β€” ΠΏΠ°ΠΊΠ΅Ρ‚ нСпосрСдствСнно с самой ORM;
  2. @nestjs/typeorm β€” TypeORM ΠΏΠ°ΠΊΠ΅Ρ‚ для NestJS. ДобавляСт ΠΌΠΎΠ΄ΡƒΠ»ΠΈ для импортирования Π² ΠΌΠΎΠ΄ΡƒΠ»ΠΈ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°, Π° Ρ‚Π°ΠΊΠΆΠ΅ Π½Π°Π±ΠΎΡ€ Π΄Π΅ΠΊΠΎΡ€Π°Ρ‚ΠΎΡ€ΠΎΠ²-Ρ…Π΅Π»ΠΏΠ΅Ρ€ΠΎΠ²;
  3. pg β€” Π΄Ρ€Π°ΠΉΠ²Π΅Ρ€ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с PostgreSQL.

ОкСй, ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ установлСны, Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ саму Π±Π°Π·Ρƒ. Для развСртывания Π±Π°Π·Ρ‹ я Π±ΡƒΠ΄Ρƒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ docker-compose.yml ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ содСрТания:

docker-compose.yml

version: '3.1'

services:
  db:
    image: postgres:11.2
    restart: always
    environment:
      POSTGRES_PASSWORD: example
    volumes:
      - ../db:/var/lib/postgresql/data
      - ./postgresql.conf:/etc/postgresql/postgresql.conf
    ports:
      - 5432:5432
  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080

Как ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΈΠ΄Π΅Ρ‚ΡŒ, Π΄Π°Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΡƒΠ΅Ρ‚ запуск 2 ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠ²:

  1. db β€” это ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ нСпосрСдствСнно с Π±Π°Π·ΠΎΠΉ Π΄Π°Π½Π½Ρ‹Ρ…. Π’ нашСм случаС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ postgresql вСрсии 11.2;
  2. adminer β€” ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€ Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π±Π°Π·ΠΎΠΉ Π΄Π°Π½Π½Ρ‹Ρ…. ΠŸΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΠ΅Ρ‚ web-интСрфСйс для просмотра ΠΈ управлСния Π±Π°Π·ΠΎΠΉ.

Для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡΠΌ ΠΏΠΎ tcp я Π΄ΠΎΠ±Π°Π²ΠΈΠ» ΠΊΠΎΠ½Ρ„ΠΈΠ³ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ содСрТания.

postgresql.conf

# -----------------------------
# PostgreSQL configuration file
# -----------------------------
#
# This file consists of lines of the form:
#
#   name = value
#
# (The "=" is optional.)  Whitespace may be used.  Comments are introduced with
# "#" anywhere on a line.  The complete list of parameter names and allowed
# values can be found in the PostgreSQL documentation.
#
# The commented-out settings shown in this file represent the default values.
# Re-commenting a setting is NOT sufficient to revert it to the default value;
# you need to reload the server.
#
# This file is read on server startup and when the server receives a SIGHUP
# signal.  If you edit the file on a running system, you have to SIGHUP the
# server for the changes to take effect, run "pg_ctl reload", or execute
# "SELECT pg_reload_conf()".  Some parameters, which are marked below,
# require a server shutdown and restart to take effect.
#
# Any parameter can also be given as a command-line option to the server, e.g.,
# "postgres -c log_connections=on".  Some parameters can be changed at run time
# with the "SET" SQL command.
#
# Memory units:  kB = kilobytes        Time units:  ms  = milliseconds
#                MB = megabytes                     s   = seconds
#                GB = gigabytes                     min = minutes
#                TB = terabytes                     h   = hours
#                                                   d   = days
#------------------------------------------------------------------------------
# FILE LOCATIONS
#------------------------------------------------------------------------------
# The default values of these variables are driven from the -D command-line
# option or PGDATA environment variable, represented here as ConfigDir.
#data_directory = 'ConfigDir'       # use data in another directory
# (change requires restart)
#hba_file = 'ConfigDir/pg_hba.conf' # host-based authentication file
# (change requires restart)
#ident_file = 'ConfigDir/pg_ident.conf' # ident configuration file
# (change requires restart)
# If external_pid_file is not explicitly set, no extra PID file is written.
#external_pid_file = ''         # write an extra PID file
# (change requires restart)
#------------------------------------------------------------------------------
# CONNECTIONS AND AUTHENTICATION
#------------------------------------------------------------------------------
# - Connection Settings -
listen_addresses = '*'
#listen_addresses = 'localhost'     # what IP address(es) to listen on;
# comma-separated list of addresses;
# defaults to 'localhost'; use '*' for all
# (change requires restart)
#port = 5432                # (change requires restart)
#max_connections = 100          # (change requires restart)
#superuser_reserved_connections = 3 # (change requires restart)
#unix_socket_directories = '/tmp'   # comma-separated list of directories
# (change requires restart)
#unix_socket_group = ''         # (change requires restart)
#unix_socket_permissions = 0777     # begin with 0 to use octal notation
# (change requires restart)
#bonjour = off              # advertise server via Bonjour
# (change requires restart)
#bonjour_name = ''          # defaults to the computer name
# (change requires restart)
# - TCP Keepalives -
# see "man 7 tcp" for details
#tcp_keepalives_idle = 0        # TCP_KEEPIDLE, in seconds;
# 0 selects the system default
#tcp_keepalives_interval = 0        # TCP_KEEPINTVL, in seconds;
# 0 selects the system default
#tcp_keepalives_count = 0       # TCP_KEEPCNT;
# 0 selects the system default
# - Authentication -
#authentication_timeout = 1min      # 1s-600s
#password_encryption = md5      # md5 or scram-sha-256
#db_user_namespace = off
# GSSAPI using Kerberos
#krb_server_keyfile = ''
#krb_caseins_users = off
# - SSL -
#ssl = off
#ssl_ca_file = ''
#ssl_cert_file = 'server.crt'
#ssl_crl_file = ''
#ssl_key_file = 'server.key'
#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers
#ssl_prefer_server_ciphers = on
#ssl_ecdh_curve = 'prime256v1'
#ssl_min_protocol_version = 'TLSv1'
#ssl_max_protocol_version = ''
#ssl_dh_params_file = ''
#ssl_passphrase_command = ''
#ssl_passphrase_command_supports_reload = off
#------------------------------------------------------------------------------
# RESOURCE USAGE (except WAL)
#------------------------------------------------------------------------------
# - Memory -
#shared_buffers = 32MB          # min 128kB
# (change requires restart)
#huge_pages = try           # on, off, or try
# (change requires restart)
#temp_buffers = 8MB         # min 800kB
#max_prepared_transactions = 0      # zero disables the feature
# (change requires restart)
# Caution: it is not advisable to set max_prepared_transactions nonzero unless
# you actively intend to use prepared transactions.
#work_mem = 4MB             # min 64kB
#maintenance_work_mem = 64MB        # min 1MB
#autovacuum_work_mem = -1       # min 1MB, or -1 to use maintenance_work_mem
#max_stack_depth = 2MB          # min 100kB
#shared_memory_type = mmap      # the default is the first option
# supported by the operating system:
#   mmap
#   sysv
#   windows
# (change requires restart)
#dynamic_shared_memory_type = posix # the default is the first option
# supported by the operating system:
#   posix
#   sysv
#   windows
#   mmap
# (change requires restart)
# - Disk -
#temp_file_limit = -1           # limits per-process temp file space
# in kB, or -1 for no limit
# - Kernel Resources -
#max_files_per_process = 1000       # min 25
# (change requires restart)
# - Cost-Based Vacuum Delay -
#vacuum_cost_delay = 0          # 0-100 milliseconds (0 disables)
#vacuum_cost_page_hit = 1       # 0-10000 credits
#vacuum_cost_page_miss = 10     # 0-10000 credits
#vacuum_cost_page_dirty = 20        # 0-10000 credits
#vacuum_cost_limit = 200        # 1-10000 credits
# - Background Writer -
#bgwriter_delay = 200ms         # 10-10000ms between rounds
#bgwriter_lru_maxpages = 100        # max buffers written/round, 0 disables
#bgwriter_lru_multiplier = 2.0      # 0-10.0 multiplier on buffers scanned/round
#bgwriter_flush_after = 0       # measured in pages, 0 disables
# - Asynchronous Behavior -
#effective_io_concurrency = 1       # 1-1000; 0 disables prefetching
#max_worker_processes = 8       # (change requires restart)
#max_parallel_maintenance_workers = 2   # taken from max_parallel_workers
#max_parallel_workers_per_gather = 2    # taken from max_parallel_workers
#parallel_leader_participation = on
#max_parallel_workers = 8       # maximum number of max_worker_processes that
# can be used in parallel operations
#old_snapshot_threshold = -1        # 1min-60d; -1 disables; 0 is immediate
# (change requires restart)
#backend_flush_after = 0        # measured in pages, 0 disables
#------------------------------------------------------------------------------
# WRITE-AHEAD LOG
#------------------------------------------------------------------------------
# - Settings -
#wal_level = replica            # minimal, replica, or logical
# (change requires restart)
#fsync = on             # flush data to disk for crash safety
# (turning this off can cause
# unrecoverable data corruption)
#synchronous_commit = on        # synchronization level;
# off, local, remote_write, remote_apply, or on
#wal_sync_method = fsync        # the default is the first option
# supported by the operating system:
#   open_datasync
#   fdatasync (default on Linux)
#   fsync
#   fsync_writethrough
#   open_sync
#full_page_writes = on          # recover from partial page writes
#wal_compression = off          # enable compression of full-page writes
#wal_log_hints = off            # also do full page writes of non-critical updates
# (change requires restart)
#wal_buffers = -1           # min 32kB, -1 sets based on shared_buffers
# (change requires restart)
#wal_writer_delay = 200ms       # 1-10000 milliseconds
#wal_writer_flush_after = 1MB       # measured in pages, 0 disables
#commit_delay = 0           # range 0-100000, in microseconds
#commit_siblings = 5            # range 1-1000
# - Checkpoints -
#checkpoint_timeout = 5min      # range 30s-1d
#max_wal_size = 1GB
#min_wal_size = 80MB
#checkpoint_completion_target = 0.5 # checkpoint target duration, 0.0 - 1.0
#checkpoint_flush_after = 0     # measured in pages, 0 disables
#checkpoint_warning = 30s       # 0 disables
# - Archiving -
#archive_mode = off     # enables archiving; off, on, or always
# (change requires restart)
#archive_command = ''       # command to use to archive a logfile segment
# placeholders: %p = path of file to archive
#               %f = file name only
# e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
#archive_timeout = 0        # force a logfile segment switch after this
# number of seconds; 0 disables
# - Archive Recovery -
# These are only used in recovery mode.
#restore_command = ''       # command to use to restore an archived logfile segment
# placeholders: %p = path of file to restore
#               %f = file name only
# e.g. 'cp /mnt/server/archivedir/%f %p'
# (change requires restart)
#archive_cleanup_command = ''   # command to execute at every restartpoint
#recovery_end_command = ''  # command to execute at completion of recovery
# - Recovery Target -
# Set these only when performing a targeted recovery.
#recovery_target = ''       # 'immediate' to end recovery as soon as a
# consistent state is reached
# (change requires restart)
#recovery_target_name = ''  # the named restore point to which recovery will proceed
# (change requires restart)
#recovery_target_time = ''  # the time stamp up to which recovery will proceed
# (change requires restart)
#recovery_target_xid = ''   # the transaction ID up to which recovery will proceed
# (change requires restart)
#recovery_target_lsn = ''   # the WAL LSN up to which recovery will proceed
# (change requires restart)
#recovery_target_inclusive = on # Specifies whether to stop:
# just after the specified recovery target (on)
# just before the recovery target (off)
# (change requires restart)
#recovery_target_timeline = 'latest'    # 'current', 'latest', or timeline ID
# (change requires restart)
#recovery_target_action = 'pause'   # 'pause', 'promote', 'shutdown'
# (change requires restart)
#------------------------------------------------------------------------------
# REPLICATION
#------------------------------------------------------------------------------
# - Sending Servers -
# Set these on the master and on any standby that will send replication data.
#max_wal_senders = 10       # max number of walsender processes
# (change requires restart)
#wal_keep_segments = 0      # in logfile segments; 0 disables
#wal_sender_timeout = 60s   # in milliseconds; 0 disables
#max_replication_slots = 10 # max number of replication slots
# (change requires restart)
#track_commit_timestamp = off   # collect timestamp of transaction commit
# (change requires restart)
# - Master Server -
# These settings are ignored on a standby server.
#synchronous_standby_names = '' # standby servers that provide sync rep
# method to choose sync standbys, number of sync standbys,
# and comma-separated list of application_name
# from standby(s); '*' = all
#vacuum_defer_cleanup_age = 0   # number of xacts by which cleanup is delayed
# - Standby Servers -
# These settings are ignored on a master server.
#primary_conninfo = ''          # connection string to sending server
# (change requires restart)
#primary_slot_name = ''         # replication slot on sending server
# (change requires restart)
#promote_trigger_file = ''      # file name whose presence ends recovery
#hot_standby = on           # "off" disallows queries during recovery
# (change requires restart)
#max_standby_archive_delay = 30s    # max delay before canceling queries
# when reading WAL from archive;
# -1 allows indefinite delay
#max_standby_streaming_delay = 30s  # max delay before canceling queries
# when reading streaming WAL;
# -1 allows indefinite delay
#wal_receiver_status_interval = 10s # send replies at least this often
# 0 disables
#hot_standby_feedback = off     # send info from standby to prevent
# query conflicts
#wal_receiver_timeout = 60s     # time that receiver waits for
# communication from master
# in milliseconds; 0 disables
#wal_retrieve_retry_interval = 5s   # time to wait before retrying to
# retrieve WAL after a failed attempt
#recovery_min_apply_delay = 0       # minimum delay for applying changes during recovery
# - Subscribers -
# These settings are ignored on a publisher.
#max_logical_replication_workers = 4    # taken from max_worker_processes
# (change requires restart)
#max_sync_workers_per_subscription = 2  # taken from max_logical_replication_workers
#------------------------------------------------------------------------------
# QUERY TUNING
#------------------------------------------------------------------------------
# - Planner Method Configuration -
#enable_bitmapscan = on
#enable_hashagg = on
#enable_hashjoin = on
#enable_indexscan = on
#enable_indexonlyscan = on
#enable_material = on
#enable_mergejoin = on
#enable_nestloop = on
#enable_parallel_append = on
#enable_seqscan = on
#enable_sort = on
#enable_tidscan = on
#enable_partitionwise_join = off
#enable_partitionwise_aggregate = off
#enable_parallel_hash = on
#enable_partition_pruning = on
# - Planner Cost Constants -
#seq_page_cost = 1.0            # measured on an arbitrary scale
#random_page_cost = 4.0         # same scale as above
#cpu_tuple_cost = 0.01          # same scale as above
#cpu_index_tuple_cost = 0.005       # same scale as above
#cpu_operator_cost = 0.0025     # same scale as above
#parallel_tuple_cost = 0.1      # same scale as above
#parallel_setup_cost = 1000.0   # same scale as above
#jit_above_cost = 100000        # perform JIT compilation if available
# and query more expensive than this;
# -1 disables
#jit_inline_above_cost = 500000     # inline small functions if query is
# more expensive than this; -1 disables
#jit_optimize_above_cost = 500000   # use expensive JIT optimizations if
# query is more expensive than this;
# -1 disables
#min_parallel_table_scan_size = 8MB
#min_parallel_index_scan_size = 512kB
#effective_cache_size = 4GB
# - Genetic Query Optimizer -
#geqo = on
#geqo_threshold = 12
#geqo_effort = 5            # range 1-10
#geqo_pool_size = 0         # selects default based on effort
#geqo_generations = 0           # selects default based on effort
#geqo_selection_bias = 2.0      # range 1.5-2.0
#geqo_seed = 0.0            # range 0.0-1.0
# - Other Planner Options -
#default_statistics_target = 100    # range 1-10000
#constraint_exclusion = partition   # on, off, or partition
#cursor_tuple_fraction = 0.1        # range 0.0-1.0
#from_collapse_limit = 8
#join_collapse_limit = 8        # 1 disables collapsing of explicit
# JOIN clauses
#force_parallel_mode = off
#jit = on               # allow JIT compilation
#plan_cache_mode = auto         # auto, force_generic_plan or
# force_custom_plan
#------------------------------------------------------------------------------
# REPORTING AND LOGGING
#------------------------------------------------------------------------------
# - Where to Log -
#log_destination = 'stderr'     # Valid values are combinations of
# stderr, csvlog, syslog, and eventlog,
# depending on platform.  csvlog
# requires logging_collector to be on.
# This is used when logging to stderr:
#logging_collector = off        # Enable capturing of stderr and csvlog
# into log files. Required to be on for
# csvlogs.
# (change requires restart)
# These are only used if logging_collector is on:
#log_directory = 'log'          # directory where log files are written,
# can be absolute or relative to PGDATA
#log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'    # log file name pattern,
# can include strftime() escapes
#log_file_mode = 0600           # creation mode for log files,
# begin with 0 to use octal notation
#log_truncate_on_rotation = off     # If on, an existing log file with the
# same name as the new log file will be
# truncated rather than appended to.
# But such truncation only occurs on
# time-driven rotation, not on restarts
# or size-driven rotation.  Default is
# off, meaning append to existing files
# in all cases.
#log_rotation_age = 1d          # Automatic rotation of logfiles will
# happen after that time.  0 disables.
#log_rotation_size = 10MB       # Automatic rotation of logfiles will
# happen after that much log output.
# 0 disables.
# These are relevant when logging to syslog:
#syslog_facility = 'LOCAL0'
#syslog_ident = 'postgres'
#syslog_sequence_numbers = on
#syslog_split_messages = on
# This is only relevant when logging to eventlog (win32):
# (change requires restart)
#event_source = 'PostgreSQL'
# - When to Log -
#log_min_messages = warning     # values in order of decreasing detail:
#   debug5
#   debug4
#   debug3
#   debug2
#   debug1
#   info
#   notice
#   warning
#   error
#   log
#   fatal
#   panic
#log_min_error_statement = error    # values in order of decreasing detail:
#   debug5
#   debug4
#   debug3
#   debug2
#   debug1
#   info
#   notice
#   warning
#   error
#   log
#   fatal
#   panic (effectively off)
#log_min_duration_statement = -1    # logs statements and their durations
# according to log_statement_sample_rate. -1 is disabled,
# 0 logs all statement, > 0 logs only statements running at
# least this number of milliseconds.
#log_statement_sample_rate = 1  # Fraction of logged statements over
# log_min_duration_statement. 1.0 logs all statements,
# 0 never logs.
# - What to Log -
#debug_print_parse = off
#debug_print_rewritten = off
#debug_print_plan = off
#debug_pretty_print = on
#log_checkpoints = off
#log_connections = off
#log_disconnections = off
#log_duration = off
#log_error_verbosity = default      # terse, default, or verbose messages
#log_hostname = off
#log_line_prefix = '%m [%p] '       # special values:
#   %a = application name
#   %u = user name
#   %d = database name
#   %r = remote host and port
#   %h = remote host
#   %p = process ID
#   %t = timestamp without milliseconds
#   %m = timestamp with milliseconds
#   %n = timestamp with milliseconds (as a Unix epoch)
#   %i = command tag
#   %e = SQL state
#   %c = session ID
#   %l = session line number
#   %s = session start timestamp
#   %v = virtual transaction ID
#   %x = transaction ID (0 if none)
#   %q = stop here in non-session
#        processes
#   %% = '%'
# e.g. '<%u%%%d> '
#log_lock_waits = off           # log lock waits >= deadlock_timeout
#log_statement = 'none'         # none, ddl, mod, all
#log_replication_commands = off
#log_temp_files = -1            # log temporary files equal or larger
# than the specified size in kilobytes;
# -1 disables, 0 logs all temp files
#log_timezone = 'GMT'
#------------------------------------------------------------------------------
# PROCESS TITLE
#------------------------------------------------------------------------------
#cluster_name = ''          # added to process titles if nonempty
# (change requires restart)
#update_process_title = on
#------------------------------------------------------------------------------
# STATISTICS
#------------------------------------------------------------------------------
# - Query and Index Statistics Collector -
#track_activities = on
#track_counts = on
#track_io_timing = off
#track_functions = none         # none, pl, all
#track_activity_query_size = 1024   # (change requires restart)
#stats_temp_directory = 'pg_stat_tmp'
# - Monitoring -
#log_parser_stats = off
#log_planner_stats = off
#log_executor_stats = off
#log_statement_stats = off
#------------------------------------------------------------------------------
# AUTOVACUUM
#------------------------------------------------------------------------------
#autovacuum = on            # Enable autovacuum subprocess?  'on'
# requires track_counts to also be on.
#log_autovacuum_min_duration = -1   # -1 disables, 0 logs all actions and
# their durations, > 0 logs only
# actions running at least this number
# of milliseconds.
#autovacuum_max_workers = 3     # max number of autovacuum subprocesses
# (change requires restart)
#autovacuum_naptime = 1min      # time between autovacuum runs
#autovacuum_vacuum_threshold = 50   # min number of row updates before
# vacuum
#autovacuum_analyze_threshold = 50  # min number of row updates before
# analyze
#autovacuum_vacuum_scale_factor = 0.2   # fraction of table size before vacuum
#autovacuum_analyze_scale_factor = 0.1  # fraction of table size before analyze
#autovacuum_freeze_max_age = 200000000  # maximum XID age before forced vacuum
# (change requires restart)
#autovacuum_multixact_freeze_max_age = 400000000    # maximum multixact age
# before forced vacuum
# (change requires restart)
#autovacuum_vacuum_cost_delay = 2ms # default vacuum cost delay for
# autovacuum, in milliseconds;
# -1 means use vacuum_cost_delay
#autovacuum_vacuum_cost_limit = -1  # default vacuum cost limit for
# autovacuum, -1 means use
# vacuum_cost_limit
#------------------------------------------------------------------------------
# CLIENT CONNECTION DEFAULTS
#------------------------------------------------------------------------------
# - Statement Behavior -
#client_min_messages = notice       # values in order of decreasing detail:
#   debug5
#   debug4
#   debug3
#   debug2
#   debug1
#   log
#   notice
#   warning
#   error
#search_path = '"$user", public'    # schema names
#row_security = on
#default_tablespace = ''        # a tablespace name, '' uses the default
#temp_tablespaces = ''          # a list of tablespace names, '' uses
# only default tablespace
#check_function_bodies = on
#default_transaction_isolation = 'read committed'
#default_transaction_read_only = off
#default_transaction_deferrable = off
#session_replication_role = 'origin'
#statement_timeout = 0          # in milliseconds, 0 is disabled
#lock_timeout = 0           # in milliseconds, 0 is disabled
#idle_in_transaction_session_timeout = 0    # in milliseconds, 0 is disabled
#vacuum_freeze_min_age = 50000000
#vacuum_freeze_table_age = 150000000
#vacuum_multixact_freeze_min_age = 5000000
#vacuum_multixact_freeze_table_age = 150000000
#vacuum_cleanup_index_scale_factor = 0.1    # fraction of total number of tuples
# before index cleanup, 0 always performs
# index cleanup
#bytea_output = 'hex'           # hex, escape
#xmlbinary = 'base64'
#xmloption = 'content'
#gin_fuzzy_search_limit = 0
#gin_pending_list_limit = 4MB
# - Locale and Formatting -
#datestyle = 'iso, mdy'
#intervalstyle = 'postgres'
#timezone = 'GMT'
#timezone_abbreviations = 'Default'     # Select the set of available time zone
# abbreviations.  Currently, there are
#   Default
#   Australia (historical usage)
#   India
# You can create your own file in
# share/timezonesets/.
#extra_float_digits = 1         # min -15, max 3; any value >0 actually
# selects precise output mode
#client_encoding = sql_ascii        # actually, defaults to database
# encoding
# These settings are initialized by initdb, but they can be changed.
#lc_messages = 'C'          # locale for system error message
# strings
#lc_monetary = 'C'          # locale for monetary formatting
#lc_numeric = 'C'           # locale for number formatting
#lc_time = 'C'              # locale for time formatting
# default configuration for text search
#default_text_search_config = 'pg_catalog.simple'
# - Shared Library Preloading -
#shared_preload_libraries = ''  # (change requires restart)
#local_preload_libraries = ''
#session_preload_libraries = ''
#jit_provider = 'llvmjit'       # JIT library to use
# - Other Defaults -
#dynamic_library_path = '$libdir'
#------------------------------------------------------------------------------
# LOCK MANAGEMENT
#------------------------------------------------------------------------------
#deadlock_timeout = 1s
#max_locks_per_transaction = 64     # min 10
# (change requires restart)
#max_pred_locks_per_transaction = 64    # min 10
# (change requires restart)
#max_pred_locks_per_relation = -2   # negative values mean
# (max_pred_locks_per_transaction
#  / -max_pred_locks_per_relation) - 1
#max_pred_locks_per_page = 2            # min 0
#------------------------------------------------------------------------------
# VERSION AND PLATFORM COMPATIBILITY
#------------------------------------------------------------------------------
# - Previous PostgreSQL Versions -
#array_nulls = on
#backslash_quote = safe_encoding    # on, off, or safe_encoding
#escape_string_warning = on
#lo_compat_privileges = off
#operator_precedence_warning = off
#quote_all_identifiers = off
#standard_conforming_strings = on
#synchronize_seqscans = on
# - Other Platforms and Clients -
#transform_null_equals = off
#------------------------------------------------------------------------------
# ERROR HANDLING
#------------------------------------------------------------------------------
#exit_on_error = off            # terminate session on any error?
#restart_after_crash = on       # reinitialize after backend crash?
#data_sync_retry = off          # retry or panic on failure to fsync
# data?
# (change requires restart)
#------------------------------------------------------------------------------
# CONFIG FILE INCLUDES
#------------------------------------------------------------------------------
# These options allow settings to be loaded from files other than the
# default postgresql.conf.
#include_dir = 'conf.d'         # include files ending in '.conf' from
# directory 'conf.d'
#include_if_exists = 'exists.conf'  # include file only if it exists
#include = 'special.conf'       # include file
#------------------------------------------------------------------------------
# CUSTOMIZED OPTIONS
#------------------------------------------------------------------------------
# Add settings for extensions here

На этом всС, ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ docker-compose up -d. Π›ΠΈΠ±ΠΎ Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ консоли ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ docker-compose up.

Π˜Ρ‚Π°ΠΊ, ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ установили, Π±Π°Π·Ρƒ запустили, ΠΎΡΡ‚Π°Π»ΠΎΡΡŒ ΠΈΡ… Π΄Ρ€ΡƒΠ³ с Π΄Ρ€ΡƒΠ³ΠΎΠΌ ΠΏΠΎΠ΄Ρ€ΡƒΠΆΠΈΡ‚ΡŒ. Для этого Π½ΡƒΠΆΠ½ΠΎ Π² ΠΊΠΎΡ€Π΅Π½ΡŒ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ„Π°ΠΉΠ» ormconfig.js ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ содСрТания:

ormconfig.js

const process = require('process');
const username = process.env.POSTGRES_USER || "postgres";
const password = process.env.POSTGRES_PASSWORD || "example";
module.exports = {
"type": "postgres",
"host": "localhost",
"port": 5432,
username,
password,
"database": "postgres",
"synchronize": true,
"dropSchema": false,
"logging": true,
"entities": [__dirname + "/src/**/*.entity.ts", __dirname + "/dist/**/*.entity.js"],
"migrations": ["migrations/**/*.ts"],
"subscribers": ["subscriber/**/*.ts", "dist/subscriber/**/.js"],
"cli": {
"entitiesDir": "src",
"migrationsDir": "migrations",
"subscribersDir": "subscriber"
}
}

Данная конфигурация Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ для cli typeorm.

ΠžΡΡ‚Π°Π½ΠΎΠ²ΠΈΠΌΡΡ Π½Π° Π΄Π°Π½Π½ΠΎΠΉ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅. Π’ строках 3 ΠΈ 4 ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ имя ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ ΠΈ ΠΏΠ°Ρ€ΠΎΠ»ΡŒ ΠΈΠ· ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… окруТСния. Π­Ρ‚ΠΎ ΡƒΠ΄ΠΎΠ±Π½ΠΎ, ΠΊΠΎΠ³Π΄Π° Ρƒ вас Π΅ΡΡ‚ΡŒ нСсколько ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠΉ (dev, stage, prod, etc). По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ имя ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ postgres, ΠΏΠ°Ρ€ΠΎΠ»ΡŒ β€” example. Π’ ΠΎΡΡ‚Π°Π»ΡŒΠ½ΠΎΠΌ ΠΊΠΎΠ½Ρ„ΠΈΠ³ Ρ‚Ρ€ΠΈΠ²ΠΈΠ°Π»Π΅Π½, поэтому остановимся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° самых интСрСсных ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°Ρ…:

  • synchronize β€” ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, Π΄ΠΎΠ»ΠΆΠ½Π° Π»ΠΈ схСма Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… автоматичСски ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒΡΡ ΠΏΡ€ΠΈ запускС прилоТСния. Π‘ΡƒΠ΄ΡŒΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ с Π΄Π°Π½Π½ΠΎΠΉ ΠΎΠΏΡ†ΠΈΠ΅ΠΉ ΠΈ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Π΅Π΅ Π² production, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС Π²Ρ‹ потСряСтС Π΄Π°Π½Π½Ρ‹Π΅. Данная опция ΡƒΠ΄ΠΎΠ±Π½Π° ΠΏΡ€ΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ΠΈ ΠΎΡ‚Π»Π°Π΄ΠΊΠ΅ прилоТСния. Как Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π° Π΄Π°Π½Π½ΠΎΠΉ ΠΎΠΏΡ†ΠΈΠΈ, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ schema:sync ΠΈΠ· CLI TypeORM.
  • dropSchema β€” ΡΠ±Ρ€Π°ΡΡ‹Π²Π°Ρ‚ΡŒ схСму ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° устанавливаСтся соСдинСниС. Π’Π°ΠΊΠΆΠ΅, ΠΊΠ°ΠΊ ΠΈ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΡƒΡŽ, Π΄Π°Π½Π½ΡƒΡŽ ΠΎΠΏΡ†ΠΈΡŽ слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² процСссС Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΈ ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ прилоТСния.
  • entities β€” ΠΏΠΎ ΠΊΠ°ΠΊΠΈΠΌ путям ΠΈΡΠΊΠ°Ρ‚ΡŒ описаниС ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ поддСрТиваСтся поиск ΠΏΠΎ маскС.
  • cli.entitiesDir β€” дирСктория, ΠΊΡƒΠ΄Π° ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡΠΊΠ»Π°Π΄Ρ‹Π²Π°Ρ‚ΡŒΡΡ ΠΌΠΎΠ΄Π΅Π»ΠΈ, созданныС ΠΈΠ· CLI TypeORM.

Для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΌΡ‹ ΠΌΠΎΠ³Π»ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ всС возмоТности TypeORM Π² нашСм Nest ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ TypeOrmModule Π² AppModule. Π’.Π΅. ваш AppModule Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import * as process from "process";
const username = process.env.POSTGRES_USER || 'postgres';
const password = process.env.POSTGRES_PASSWORD || 'example';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username,
password,
database: 'postgres',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

Как Π²Ρ‹ успСли Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Π² ΠΌΠ΅Ρ‚ΠΎΠ΄ forRoot пСрСдаСтся Ρ‚Π° ΠΆΠ΅ конфигурация для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π±Π°Π·ΠΎΠΉ, Ρ‡Ρ‚ΠΎ ΠΈ Π² Ρ„Π°ΠΉΠ»Π΅ ormconfig.ts

ΠžΡΡ‚Π°Π»ΡΡ Ρ„ΠΈΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΡˆΡ‚Ρ€ΠΈΡ… β€” Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ нСсколько тасков для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с TypeORM Π² package.json. Π”Π΅Π»ΠΎ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ CLI написана Π½Π° javascript ΠΈ запускаСтся Π² срСдС nodejs. Однако всС наши ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΈ ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ Π±ΡƒΠ΄ΡƒΡ‚ написаны Π½Π° typescript. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ провСсти Ρ‚Ρ€Π°Π½ΡΠΏΠΈΠ»ΡΡ†ΠΈΡŽ Π½Π°ΡˆΠΈΡ… ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΉ ΠΈ ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ Π΄ΠΎ использования CLI. Для этого Π½Π°ΠΌ понадобится ΠΏΠ°ΠΊΠ΅Ρ‚ ts-node:

yarn add -D ts-node

ПослС этого Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ Π² package.json:

"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js",
"migration:generate": "yarn run typeorm migration:generate -n",
"migration:create": "yarn run typeorm migration:create -n",
"migration:run": "yarn run typeorm migration:run"

ΠŸΠ΅Ρ€Π²Π°Ρ ΠΊΠΎΠΌΠ°Π½Π΄Π°, typeorm, добавляСт ΠΎΠ±Π΅Ρ€Ρ‚ΠΊΡƒ Π² Π²ΠΈΠ΄Π΅ ts-node для запуска cli TypeORM. ΠžΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ β€” это ΡƒΠ΄ΠΎΠ±Π½Ρ‹Π΅ сокращСния, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ Π²Ρ‹ ΠΊΠ°ΠΊ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π±ΡƒΠ΄Π΅Ρ‚Π΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ практичСски ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ дСнь:
migration:generate β€” созданиС ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ Π½Π° основС ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ Π² Π²Π°ΡˆΠΈΡ… модСлях.
migration:create β€” созданиС пустой ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ.
migration:run β€” запуск ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΉ.
Ну Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Ρ‚ΠΎΡ‡Π½ΠΎ всС, ΠΌΡ‹ Π΄ΠΎΠ±Π°Π²ΠΈΠ»ΠΈ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹, сконфигурировали ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π±Π°Π·ΠΎΠΉ ΠΊΠ°ΠΊ с cli, Ρ‚Π°ΠΊ ΠΈ с самого прилоТСния Π° Ρ‚Π°ΠΊΠΆΠ΅ запустили Π‘Π£Π‘Π”. ΠŸΡ€ΠΈΡˆΠ»ΠΎ врСмя Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π»ΠΎΠ³ΠΈΠΊΡƒ Π² нашС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅.

Установка ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² для создания CRUD

Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Nest ΠΌΠΎΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ API, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ, Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ, ΠΎΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒ ΠΈ ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ. Π’Π°ΠΊΠΎΠ΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ максимально Π³ΠΈΠ±ΠΊΠΈΠΌ ΠΎΠ΄Π½Π°ΠΊΠΎ для Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… случаСв ΠΈΠ·Π±Ρ‹Ρ‚ΠΎΡ‡Π½Ρ‹ΠΌ. К ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ, Ссли Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ быстро ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΡ‚ΠΎΡ‚ΠΈΠΏ, Ρ‚ΠΎ Π·Π°Ρ‡Π°ΡΡ‚ΡƒΡŽ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠΆΠ΅Ρ€Ρ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ Π³ΠΈΠ±ΠΊΠΎΡΡ‚ΡŒΡŽ Ρ€Π°Π΄ΠΈ скорости Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ. МногиС Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠΈ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π» Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ CRUD ΠΏΠΎ описанию ΠΌΠΎΠ΄Π΅Π»ΠΈ Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠΉ сущности. И Nest Π½Π΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅! Π”Π°Π½Π½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ прСдоставляСт ΠΏΠ°ΠΊΠ΅Ρ‚ @nestjsx/crud. ВозмоТности Π΅Π³ΠΎ вСсьма интСрСсны:

  • лСгкая установка ΠΈ настройка;
  • Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡ‚ΡŒ ΠΎΡ‚ Π‘Π£Π‘Π”;
  • ΠΌΠΎΡ‰Π½Ρ‹ΠΉ язык запросов с Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΠΈ, ΠΏΠ°Π³ΠΈΠ½Π°Ρ†ΠΈΠΈ, сортировки, Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ связСй ΠΈ Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Ρ… сущностСй, ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈ Ρ‚.Π΄.;
  • ΠΏΠ°ΠΊΠ΅Ρ‚ для формирования запросов Π½Π° front-end;
  • Π»Π΅Π³ΠΊΠΎΠ΅ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π°;
  • нСбольшой ΠΊΠΎΠ½Ρ„ΠΈΠ³;
  • ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° swagger Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ.

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ Ρ€Π°Π·Π±ΠΈΡ‚Π° Π½Π° нСсколько ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²:

  • @nestjsx/crud β€” Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ прСдоставляСт Π΄Π΅ΠΊΠΎΡ€Π°Ρ‚ΠΎΡ€ Crud() для Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ Ρ€ΠΎΡƒΡ‚ΠΎΠ², конфигурирования ΠΈ Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ;
  • @nestjsx/crud-request β€” ΠΏΠ°ΠΊΠ΅Ρ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ Π±ΠΈΠ»Π΄Π΅Ρ€/парсСр запросов для использования Π½Π° сторонС frontend;
  • @nestjsx/crud-typeorm β€” ΠΏΠ°ΠΊΠ΅Ρ‚ для ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ с TypeORM, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ сСрвис TypeOrmCrudService с CRUD ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌΠΈ Ρ€Π°Π±ΠΎΡ‚Ρ‹ с сущностями Π² Π‘Π”.

Π’ Π΄Π°Π½Π½ΠΎΠΌ руководствС Π½Π°ΠΌ понадобятся ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ nestjsx/crud ΠΈ nestjsx/crud-typeorm. Для Π½Π°Ρ‡Π°Π»Π°, поставим ΠΈΡ…

yarn add @nestjsx/crud class-transformer class-validator

ΠŸΠ°ΠΊΠ΅Ρ‚Ρ‹ class-transformer ΠΈ class-validator Π² Π΄Π°Π½Π½ΠΎΠΌ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ΡΡ для Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ описания ΠΏΡ€Π°Π²ΠΈΠ» трансформирования экзСмпляров ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ ΠΈ Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ входящих запросов соотвСтствСнно. Π”Π°Π½Π½Ρ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ ΠΎΡ‚ ΠΎΠ΄Π½ΠΎΠ³ΠΎ Π°Π²Ρ‚ΠΎΡ€Π°, поэтому интСрфСйсы схоТи.

НСпосрСдствСнная рСализация CRUD

Π’ качСствС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΌΡ‹ возьмСм список ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ. Π£ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ Π±ΡƒΠ΄ΡƒΡ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ поля: id, username, displayName, email. id β€” Π°Π²Ρ‚ΠΎΠΈΠ½ΠΊΡ€Π΅ΠΌΠ΅Π½Ρ‚Π½ΠΎΠ΅ ΠΏΠΎΠ»Π΅, email ΠΈ username β€” ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ поля. ВсС просто! ΠžΡΡ‚Π°Π»ΠΎΡΡŒ Π²ΠΎΠΏΠ»ΠΎΡ‚ΠΈΡ‚ΡŒ Π½Π°ΡˆΡƒ Π·Π°Π΄ΡƒΠΌΠΊΡƒ Π² Π²ΠΈΠ΄Π΅ Nest прилоТСния.
Для Π½Π°Ρ‡Π°Π»Π° Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ users, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚Π²Π΅Ρ‡Π°Ρ‚ΡŒ Π·Π° Ρ€Π°Π±ΠΎΡ‚Ρƒ с ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΌΠΈ. Π’ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡΡ cli ΠΎΡ‚ NestJS, ΠΈ Π² ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠΉ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ нашСго ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΠΌ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ nest g module users.

nest g module users

dmitrii@dmitrii-HP-ZBook-17-G3:~/projects/nest-rest git:(master*)$ nest g module users
CREATE /src/users/users.module.ts (82 bytes)
UPDATE /src/app.module.ts (312 bytes)

Π’ Π΄Π°Π½Π½ΠΎΠΌ ΠΌΠΎΠ΄ΡƒΠ»Π΅ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΏΠ°ΠΏΠΊΡƒ entities, Π³Π΄Π΅ Ρƒ нас Π±ΡƒΠ΄ΡƒΡ‚ Π»Π΅ΠΆΠ°Ρ‚ΡŒ ΠΌΠΎΠ΄Π΅Π»ΠΈ Π΄Π°Π½Π½ΠΎΠ³ΠΎ модуля. Π’ частности, Π΄ΠΎΠ±Π°Π²ΠΈΠΌ сюда Ρ„Π°ΠΉΠ» user.entity.ts с описаниСм ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ:

user.entity.ts

import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: string;
@Column({unique: true})
email: string;
@Column({unique: true})
username: string;
@Column({nullable: true})
displayName: string;
}

Π§Ρ‚ΠΎΠ±Ρ‹ Π΄Π°Π½Π½ΡƒΡŽ модСль «ΡƒΠ²ΠΈΠ΄Π΅Π»ΠΎ» нашС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π² ΠΌΠΎΠ΄ΡƒΠ»ΡŒ UsersModule ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ TypeOrmModule ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ содСрТания:

users.module.ts

import { Module } from '@nestjs/common';
import { UsersController } from './controllers/users/users.controller';
import { UsersService } from './services/users/users.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
@Module({
controllers: [UsersController],
providers: [UsersService],
imports: [
TypeOrmModule.forFeature([User])
]
})
export class UsersModule {}

Π’.Π΅ здСсь ΠΌΡ‹ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ TypeOrmModule, Π³Π΄Π΅ Π² качСствС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° forFeature ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅ΠΌ список ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ, относящихся ΠΊ Π΄Π°Π½Π½ΠΎΠΌΡƒ ΠΌΠΎΠ΄ΡƒΠ»ΡŽ.

ΠžΡΡ‚Π°Π΅Ρ‚ΡΡ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ Π² Π±Π°Π·Π΅ Π΄Π°Π½Π½Ρ‹Ρ…. Для этих Ρ†Π΅Π»Π΅ΠΉ слуТит ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΉ. Π§Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΡŽ Π½Π° основС ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ Π² модСлях, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ npm run migration:generate -- CreateUserTable:

Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ спойлСра

$ npm run migration:generate -- CreateUserTable
Migration /home/dmitrii/projects/nest-rest/migrations/1563346135367-CreateUserTable.ts has been generated successfully.
Done in 1.96s.

Нам Π½Π΅ ΠΏΡ€ΠΈΡˆΠ»ΠΎΡΡŒ ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΡŽ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ, всС ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΎ магичСским ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ. Π­Ρ‚ΠΎ Π»ΠΈ Π½Π΅ Ρ‡ΡƒΠ΄ΠΎ! Однако ΠΈ это Π΅Ρ‰Π΅ Π½Π΅ всС. ВзглянСм Π½Π° созданный Ρ„Π°ΠΉΠ» с ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠ΅ΠΉ:

1563346135367-CreateUserTable.ts

import {MigrationInterface, QueryRunner} from "typeorm";
export class CreateUserTable1563346816726 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`CREATE TABLE "user" ("id" SERIAL NOT NULL, "email" character varying NOT NULL, "username" character varying NOT NULL, "displayName" character varying, CONSTRAINT "UQ_e12875dfb3b1d92d7d7c5377e22" UNIQUE ("email"), CONSTRAINT "UQ_78a916df40e02a9deb1c4b75edb" UNIQUE ("username"), CONSTRAINT "PK_cace4a159ff9f2512dd42373760" PRIMARY KEY ("id"))`);
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`DROP TABLE "user"`);
}
}

Как ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Π±Ρ‹Π» автоматичСски сгСнСрирован Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄ для запуска ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ, Π½ΠΎ ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ для Π΅Π΅ ΠΎΡ‚ΠΊΠ°Ρ‚Π°. Ѐантастика!
ΠžΡΡ‚Π°Π΅Ρ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π°ΠΊΠ°Ρ‚ΠΈΡ‚ΡŒ Π΄Π°Π½Π½ΡƒΡŽ ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΡŽ. ДСлаСтся это ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ:

npm run migration:run.

ВсС, Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ измСнСния схСмы ΠΏΠ΅Ρ€Π΅ΠΊΠΎΡ‡Π΅Π²Π°Π»ΠΈ Π² Π±Π°Π·Ρƒ Π΄Π°Π½Π½Ρ‹Ρ….
Π”Π°Π»Π΅Π΅ создадим сСрвис, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚Π²Π΅Ρ‡Π°Ρ‚ΡŒ Π·Π° Ρ€Π°Π±ΠΎΡ‚Ρƒ с ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΌΠΈ ΠΈ отнаслСдуСм Π΅Π³ΠΎ ΠΎΡ‚ TypeOrmCrudService. Π’ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ конструктора Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΡƒΡŽΡ‰Π΅ΠΉ сущности, Π² нашСм случаС User Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ.

users.service.ts

import { Injectable } from '@nestjs/common';
import { TypeOrmCrudService } from '@nestjsx/crud-typeorm';
import { User } from '../../entities/user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
@Injectable()
export class UsersService extends TypeOrmCrudService<User>{
constructor(@InjectRepository(User) usersRepository: Repository<User>){
super(usersRepository);
}
}

Π”Π°Π½Π½Ρ‹ΠΉ сСрвис Π½Π°ΠΌ понадобится Π² ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π΅ users. Для создания ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π° Π½Π°Π±Π΅Ρ€ΠΈΡ‚Π΅ Π² консоли nest g controller users/controllers/users

nest g controller users/controllers/users

dmitrii@dmitrii-HP-ZBook-17-G3:~/projects/nest-rest git:(master*)$ nest g controller users/controllers/users
CREATE /src/users/controllers/users/users.controller.spec.ts (486 bytes)
CREATE /src/users/controllers/users/users.controller.ts (99 bytes)
UPDATE /src/users/users.module.ts (188 bytes)

ΠžΡ‚ΠΊΡ€ΠΎΠ΅ΠΌ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€ ΠΈ ΠΎΡ‚Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΡƒΠ΅ΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΌΠ°Π³ΠΈΠΈ nestjsx/crud. На класс UsersController Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π΄Π΅ΠΊΠΎΡ€Π°Ρ‚ΠΎΡ€ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ Π²ΠΈΠ΄Π°:

@Crud({
model: {
type: User
}
})

Crud β€” это Π΄Π΅ΠΊΠΎΡ€Π°Ρ‚ΠΎΡ€, Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ Π² ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с модСлью. Π’ΠΈΠΏ ΠΌΠΎΠ΄Π΅Π»ΠΈ указываСтся Π² ΠΏΠΎΠ»Π΅ model.type ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ Π΄Π΅ΠΊΠΎΡ€Π°Ρ‚ΠΎΡ€Π°.
Π’Ρ‚ΠΎΡ€ΠΎΠΉ шаг β€” Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ интСрфСйс CrudController<User>. «Π’ сборС» ΠΊΠΎΠ΄ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π° выглядит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

import { Controller } from '@nestjs/common';
import { Crud, CrudController } from '@nestjsx/crud';
import { User } from '../../entities/user.entity';
import { UsersService } from '../../services/users/users.service';
@Crud({
model: {
type: User
}
})
@Controller('users')
export class UsersController implements CrudController<User>{
constructor(public service: UsersService){}
}

И это всС! Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ вСсь Π½Π°Π±ΠΎΡ€ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ с модСлью! НС Π²Π΅Ρ€ΠΈΡ‚Π΅? Π”Π°Π²Π°ΠΉΡ‚Π΅ ΠΏΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ нашС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π² Π΄Π΅Π»Π΅!

Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ сцСнария запросов Π² TestMace

Для тСстирования нашСго сСрвиса ΠΌΡ‹ Π±ΡƒΠ΄Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ IDE для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с API TestMace. ΠŸΠΎΡ‡Π΅ΠΌΡƒ TestMace? По ΡΡ€Π°Π²Π½Π΅Π½ΠΈΡŽ с Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½Ρ‹ΠΌΠΈ ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚Π°ΠΌΠΈ, ΠΎΠ½ ΠΈΠΌΠ΅Π΅Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ прСимущСства:

  • мощная Ρ€Π°Π±ΠΎΡ‚Π° с ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΌΠΈ. На Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ сущСствуСт нСсколько Π²ΠΈΠ΄ΠΎΠ² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…, ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… выполняСт ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΡƒΡŽ Ρ€ΠΎΠ»ΡŒ: встроСнныС ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅, динамичСскиС ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅, ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ окруТСния. КаТдая пСрСмСнная ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠΈΡ‚ ΠΊΠ°ΠΊΠΎΠΌΡƒ-Π»ΠΈΠ±ΠΎ ΡƒΠ·Π»Ρƒ с ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΎΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° наслСдования;
  • Π»Π΅Π³ΠΊΠΎΠ΅ созданиС сцСнариСв Π±Π΅Π· программирования. Об этом Ρ€Π΅Ρ‡ΡŒ ΠΏΠΎΠΉΠ΄Π΅Ρ‚ Π½ΠΈΠΆΠ΅;
  • Ρ‡Π΅Π»ΠΎΠ²Π΅ΠΊΠΎΡ‡ΠΈΡ‚Π°Π΅ΠΌΡ‹ΠΉ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ ΡΠΎΡ…Ρ€Π°Π½ΡΡ‚ΡŒ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ Π² систСмах контроля вСрсий;
  • Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅, подсвСтка синтаксиса, подсвСтка Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…;
  • ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° описания API с Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ ΠΈΠΌΠΏΠΎΡ€Ρ‚Π° ΠΈΠ· Swagger.

Π”Π°Π²Π°ΠΉΡ‚Π΅ запустим наш сСрвСр ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ npm start ΠΈ ΠΏΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ списку ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ. Бписок ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ, судя ΠΏΠΎ нашСй ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π°, ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΠΎ url localhost:3000/users. Π‘Π΄Π΅Π»Π°Π΅ΠΌ запрос Π½Π° Π΄Π°Π½Π½Ρ‹ΠΉ url.
ПослС запуска TestMace Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ Ρ‚Π°ΠΊΠΎΠΉ интСрфСйс:

БыстроС созданиС CRUD с nest, @nestjsx/crud ΠΈ TestMace

Π‘Π»Π΅Π²Π° свСрху находится Π΄Π΅Ρ€Π΅Π²ΠΎ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠ² с ΠΊΠΎΡ€Π½Π΅Π²Ρ‹ΠΌ ΡƒΠ·Π»ΠΎΠΌ Project. Π”Π°Π²Π°ΠΉΡ‚Π΅ ΠΏΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ запрос Π½Π° ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ списка ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ. Для этого создадим RequestStep ΡƒΠ·Π΅Π». ДСлаСтся это Π² контСкстном мСню Project ΡƒΠ·Π»Π° Add node -> RequestStep.

БыстроС созданиС CRUD с nest, @nestjsx/crud ΠΈ TestMace

Π’ ΠΏΠΎΠ»Π΅ URL Π²ΡΡ‚Π°Π²ΡŒΡ‚Π΅ localhost:3000/users ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚Π΅ запрос. ΠŸΠΎΠ»ΡƒΡ‡ΠΈΠΌ 200 ΠΊΠΎΠ΄ с пустым массивом Π² Ρ‚Π΅Π»Π΅ ΠΎΡ‚Π²Π΅Ρ‚Π°. Оно ΠΈ понятно, ΠΌΡ‹ Π΅Ρ‰Π΅ Π½ΠΈΠΊΠΎΠ³ΠΎ Π½Π΅ добавляли.
Π”Π°Π²Π°ΠΉΡ‚Π΅ создадим сцСнарий ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ Π²ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒ Π² сСбя ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ шаги:

  1. cΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ;
  2. запрос ΠΏΠΎ id Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Ρ‚ΠΎ созданного ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ;
  3. ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎ id ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, созданного Π½Π° шагС 1.

Π˜Ρ‚Π°ΠΊ, ΠΏΠΎΠ΅Ρ…Π°Π»ΠΈ. Для удобства создадим ΡƒΠ·Π΅Π» Ρ‚ΠΈΠΏΠ° Folder. По сути это просто ΠΏΠ°ΠΏΠΊΠ°, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ сохраним вСсь сцСнарий. Для создания Folder ΡƒΠ·Π»Π° Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π² контСкстном мСню Project ΡƒΠ·Π»Π° Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ Add node -> Folder. НазовСм ΡƒΠ·Π΅Π» check-create. Π’Π½ΡƒΡ‚Ρ€ΠΈ ΡƒΠ·Π»Π° check-create создадим наш ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ запрос Π½Π° созданиС ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ. НазовСм вновь созданный ΡƒΠ·Π΅Π» create-user. Π’ΠΎ Π΅ΡΡ‚ΡŒ Π½Π° Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ иСрархия ΡƒΠ·Π»ΠΎΠ² Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

БыстроС созданиС CRUD с nest, @nestjsx/crud ΠΈ TestMace

Π”Π°Π²Π°ΠΉΡ‚Π΅ ΠΏΠ΅Ρ€Π΅ΠΉΠ΄Π΅ΠΌ ΠΊ Π²ΠΊΠ»Π°Π΄ΠΊΠ΅ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΎΠ³ΠΎ create-user ΡƒΠ·Π»Π°. Π’Π²Π΅Π΄Π΅ΠΌ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ для запроса:

  • Π’ΠΈΠΏ запроса β€” POST
  • URL β€” localhost:3000/users
  • Body β€” JSON со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ {"email": "[email protected]", "displayName": "New user", "username": "user"}

Π’Ρ‹ΠΏΠΎΠ»Π½ΠΈΠΌ Π΄Π°Π½Π½Ρ‹ΠΉ запрос. НашС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚, Ρ‡Ρ‚ΠΎ запись создана.

БыстроС созданиС CRUD с nest, @nestjsx/crud ΠΈ TestMace

Π§Ρ‚ΠΎ ΠΆ, Π΄Π°Π²Π°ΠΉΡ‚Π΅ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ Π΄Π°Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΊΡ‚. Π§Ρ‚ΠΎΠ±Ρ‹ Π² ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… ΡˆΠ°Π³Π°Ρ… ΠΎΠΏΠ΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ с id созданного ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, Π΄Π°Π½Π½Ρ‹ΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ. Для этого ΠΎΡ‚Π»ΠΈΡ‡Π½ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ динамичСских ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…. Π”Π°Π²Π°ΠΉΡ‚Π΅ Π½Π° нашСм ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ рассмотрим, ΠΊΠ°ΠΊ происходит Ρ€Π°Π±ΠΎΡ‚Π° с Π½ΠΈΠΌΠΈ. Π’ΠΎ Π²ΠΊΠ»Π°Π΄ΠΊΠ΅ parsed ΠΎΡ‚Π²Π΅Ρ‚Π° Ρƒ ΡƒΠ·Π»Π° id Π² контСкстном мСню Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ ΠΏΡƒΠ½ΠΊΡ‚ Assign to variable. Π’ Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²ΠΎΠΌ ΠΎΠΊΠ½Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π·Π°Π΄Π°Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹:

  • Node β€” Π² ΠΊΠ°ΠΊΠΎΠΌ ΠΈΠ· ΠΏΡ€Π΅Π΄ΠΊΠΎΠ² ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ Π΄ΠΈΠ½Π°ΠΌΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ. Π’Ρ‹Π±Π΅Ρ€Π΅ΠΌ check-create
  • Variable name β€” Π½Π°Π·Π²Π°Π½ΠΈΠ΅ этой ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ. НазовСм userId.

Π’ΠΎΡ‚ ΠΊΠ°ΠΊ выглядит процСсс создания динамичСской ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ:

БыстроС созданиС CRUD с nest, @nestjsx/crud ΠΈ TestMace

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Π΄Π°Π½Π½ΠΎΠ³ΠΎ запроса Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ динамичСской ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒΡΡ. А Ρ‚.ΠΊ. динамичСскиС ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ иСрархичСского наслСдования, пСрСмСнная userId Π±ΡƒΠ΄Π΅Ρ‚ доступна Π² ΠΏΠΎΡ‚ΠΎΠΌΠΊΠ°Ρ… check-create ΡƒΠ·Π»Π° любого уровня влоТСнности.
Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ запросС данная пСрСмСнная Π½Π°ΠΌ пригодится. А ΠΈΠΌΠ΅Π½Π½ΠΎ, ΠΌΡ‹ запросим вновь созданного ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ. Π’ качСствС ΠΏΠΎΡ‚ΠΎΠΌΠΊΠ° ΡƒΠ·Π»Π° check-create ΠΌΡ‹ создадим запрос check-if exists с ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ url Ρ€Π°Π²Π½Ρ‹ΠΌ localhost:3000/users/${$dynamicVar.userId}. ΠšΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡ Π²ΠΈΠ΄Π° ${variable_name} это ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ значСния ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ. Π’.ΠΊ. Ρƒ нас динамичСская пСрСмСнная, Ρ‚ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π΅Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρƒ $dynamicVar, Ρ‚.Π΅ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ ΠΊ динамичСской ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ userId Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ${$dynamicVar.userId}. Π’Ρ‹ΠΏΠΎΠ»Π½ΠΈΠΌ запрос ΠΈ убСдимся, Ρ‡Ρ‚ΠΎ Π΄Π°Π½Π½Ρ‹Π΅ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°ΡŽΡ‚ΡΡ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ.
ΠžΡΡ‚Π°Π»ΡΡ послСдний ΡˆΡ‚Ρ€ΠΈΡ… β€” ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ запрос Π½Π° ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅. Он Π½Π°ΠΌ Π½ΡƒΠΆΠ΅Π½ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ удалСния, Π½ΠΎ ΠΈ, Ρ‚Π°ΠΊ ΡΠΊΠ°Π·Π°Ρ‚ΡŒ, ΠΏΠΎΠ΄Ρ‡ΠΈΡΡ‚ΠΈΡ‚ΡŒ Π·Π° собой Π² Π±Π°Π·Π΅, Ρ‚.ΠΊ. поля email ΠΈ username ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹. Π˜Ρ‚Π°ΠΊ, Π² ΡƒΠ·Π»Π΅ check-create создадим запрос delete-user со ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌΠΈ

  • Π’ΠΈΠΏ запроса β€” DELETE
  • URL β€” localhost:3000/users/${$dynamicVar.userId}

ЗапускаСм. Π–Π΄Π΅ΠΌ. НаслаТдаСмся Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ)

Ну ΠΈ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π² любой ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Π΄Π°Π½Π½Ρ‹ΠΉ сцСнарий. Π§Ρ‚ΠΎΠ±Ρ‹ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ сцСнарий Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ Π² контСкстном мСню check-create ΡƒΠ·Π»Π° ΠΏΡƒΠ½ΠΊΡ‚ Run.

БыстроС созданиС CRUD с nest, @nestjsx/crud ΠΈ TestMace

Π£Π·Π»Ρ‹ Π² сцСнарии выполнятся Π΄Ρ€ΡƒΠ³ Π·Π° Π΄Ρ€ΡƒΠ³ΠΎΠΌ
Π”Π°Π½Π½Ρ‹ΠΉ сцСнарий Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ ΠΊ сСбС Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚, Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΠ² File -> Save project.

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

Π’ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π΄Π°Π½Π½ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠΈ просто Π½Π΅ смогли ΡƒΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒΡΡ всС Ρ„ΠΈΡˆΠΊΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½Π½Ρ‹Ρ… инструмСнтов. Π§Ρ‚ΠΎ касаСтся основного Π²ΠΈΠ½ΠΎΠ²Π½ΠΈΠΊΠ° β€” ΠΏΠ°ΠΊΠ΅Ρ‚Π° nestjsx/crud β€” нСосвСщСнными ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ Ρ‚Π΅ΠΌΡ‹:

  • кастомная валидация ΠΈ трансформация ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ;
  • ΠΌΠΎΡ‰Π½Ρ‹ΠΉ язык запросов ΠΈ ΡƒΠ΄ΠΎΠ±Π½ΠΎΠ΅ Π΅Π³ΠΎ использованиС Π½Π° Ρ„Ρ€ΠΎΠ½Ρ‚Π΅;
  • ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΈ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½ΠΎΠ²Ρ‹Ρ… ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² Π² crud-ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Ρ‹;
  • ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° swagger;
  • ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΊΡΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ.

Однако Π΄Π°ΠΆΠ΅ описанного Π² ΡΡ‚Π°Ρ‚ΡŒΠ΅ достаточно, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ½ΡΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ Π΄Π°ΠΆΠ΅ Ρ‚Π°ΠΊΠΎΠΉ энтСрпрайсный Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ ΠΊΠ°ΠΊ NestJS ΠΈΠΌΠ΅Π΅Ρ‚ Π² загашникС инструмСнты для быстрого прототипирования ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ. А такая классная IDE ΠΊΠ°ΠΊ TestMace позволяСт ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ Π·Π°Π΄Π°Π½Π½Ρ‹ΠΉ Ρ‚Π΅ΠΌΠΏ.

Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ Π΄Π°Π½Π½ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠΈ, вмСстС с ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠΌ TestMace, доступСн Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ https://github.com/TestMace/nest-rest. Для открытия ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° TestMace достаточно Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ File -> Open project.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com