Tạo CRUD nhanh chóng với Nest, @nestjsx/crud và TestMace

Tạo CRUD nhanh chóng với Nest, @nestjsx/crud và TestMace

Hiện tại, REST API đã trở thành tiêu chuẩn để phát triển ứng dụng web, cho phép chia quá trình phát triển thành các phần độc lập. Nhiều framework phổ biến khác nhau như Angular, React, Vue và các framework khác hiện đang được sử dụng cho UI. Các nhà phát triển phụ trợ có thể chọn từ nhiều ngôn ngữ và khung khác nhau. Hôm nay tôi muốn nói về một khuôn khổ như NestJS. Chúng tôi đang trong TestMace Chúng tôi tích cực sử dụng nó cho các dự án nội bộ. Sử dụng tổ và gói @nestjsx/crud, chúng ta sẽ tạo một ứng dụng CRUD đơn giản.

Tại sao NestJS

Gần đây, khá nhiều backend framework đã xuất hiện trong cộng đồng JavaScript. Và nếu về mặt chức năng, chúng cung cấp các khả năng tương tự như Nest, thì có một điều nó chắc chắn thắng - đây là kiến ​​​​trúc. Các tính năng NestJS sau đây cho phép bạn tạo các ứng dụng công nghiệp và phát triển quy mô cho các nhóm lớn:

  • sử dụng TypeScript làm ngôn ngữ phát triển chính. Mặc dù NestJS hỗ trợ JavaScript nhưng một số chức năng có thể không hoạt động, đặc biệt nếu chúng ta đang nói về các gói của bên thứ ba;
  • sự hiện diện của bộ chứa DI, cho phép bạn tạo các thành phần được ghép lỏng lẻo;
  • Bản thân chức năng của khung được chia thành các thành phần độc lập có thể hoán đổi cho nhau. Ví dụ, dưới dạng khung, nó có thể được sử dụng như thể hiệnbuộc chặt, để làm việc với cơ sở dữ liệu, Nest out of the box cung cấp các liên kết tới người đánh máy, cầy mangut, phần tiếp theo;
  • NestJS là nền tảng bất khả tri và hỗ trợ REST, GraphQL, Websockets, gRPC, v.v.

Bản thân khung này được lấy cảm hứng từ khung giao diện Angular và về mặt khái niệm có nhiều điểm chung với nó.

Cài đặt NestJS và triển khai dự án

Nest chứa một gói tổ/cli, cho phép bạn nhanh chóng triển khai khung ứng dụng cơ bản. Hãy cài đặt gói này trên toàn cầu:

npm install --global @nest/cli

Sau khi cài đặt, chúng tôi sẽ tạo khung cơ bản cho ứng dụng của mình với tên tổ-rest. Việc này được thực hiện bằng lệnh nest new nest-rest.

làm tổ mới làm tổ nghỉ ngơi

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

Chúng tôi sẽ chọn sợi làm người quản lý gói của mình.
Tại thời điểm này, bạn có thể khởi động máy chủ bằng lệnh npm start và đi đến địa chỉ http://localhost:3000 bạn có thể xem trang chính Tuy nhiên, đây không phải là lý do tại sao chúng tôi tập hợp ở đây và chúng tôi đang tiếp tục.

Thiết lập công việc với cơ sở dữ liệu

Tôi đã chọn PostrgreSQL làm DBMS cho bài viết này. Không có gì phải bàn cãi về thị hiếu; theo tôi, đây là DBMS trưởng thành nhất, có tất cả các khả năng cần thiết. Như đã đề cập, Nest cung cấp khả năng tích hợp với nhiều gói khác nhau để hoạt động với cơ sở dữ liệu. Bởi vì Vì lựa chọn của tôi thuộc về PostgreSQL, nên sẽ hợp lý hơn nếu chọn TypeORM làm ORM. Hãy cài đặt các gói cần thiết để tích hợp với cơ sở dữ liệu:

yarn add typeorm @nestjs/typeorm pg

Theo thứ tự, mỗi gói cần thiết để làm gì:

  1. typeorm - một gói trực tiếp từ chính ORM;
  2. @nestjs/typeorm - Gói TypeORM cho NestJS. Thêm các mô-đun để nhập vào các mô-đun dự án, cũng như một bộ trang trí trợ giúp;
  3. pg - trình điều khiển để làm việc với PostgreSQL.

Được rồi, các gói đã được cài đặt, bây giờ bạn cần khởi chạy cơ sở dữ liệu. Để triển khai cơ sở dữ liệu, tôi sẽ sử dụng docker-compose.yml với nội dung sau:

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

Như bạn có thể thấy, tệp này định cấu hình khởi chạy 2 vùng chứa:

  1. db là một thùng chứa trực tiếp cơ sở dữ liệu. Trong trường hợp của chúng tôi, phiên bản postgresql 11.2 được sử dụng;
  2. quản trị viên-người quản lý cơ sở dữ liệu. Cung cấp giao diện web để xem và quản lý cơ sở dữ liệu.

Để làm việc với các kết nối tcp, tôi đã thêm cấu hình sau.

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

Chỉ vậy thôi, bạn có thể khởi động container bằng lệnh docker-compose up -d. Hoặc trong một bảng điều khiển riêng biệt với lệnh docker-compose up.

Vậy là các gói đã được cài đặt, cơ sở dữ liệu đã được khởi chạy, tất cả những gì còn lại là kết bạn với nhau. Để thực hiện việc này, bạn cần thêm tệp sau vào thư mục gốc của dự án: 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"
}
}

Cấu hình này sẽ được sử dụng cho cli typeorm.

Hãy xem xét cấu hình này chi tiết hơn. Ở dòng 3 và 4, chúng ta lấy tên người dùng và mật khẩu từ các biến môi trường. Điều này thuận tiện khi bạn có nhiều môi trường (dev, stage, prod, v.v.). Theo mặc định, tên người dùng là postgres và mật khẩu là ví dụ. Phần còn lại của cấu hình không quan trọng nên chúng ta sẽ chỉ tập trung vào những thông số thú vị nhất:

  • đồng bộ hóa - Cho biết liệu lược đồ cơ sở dữ liệu có được tạo tự động hay không khi ứng dụng khởi động. Hãy cẩn thận với tùy chọn này và không sử dụng nó trong sản xuất, nếu không bạn sẽ mất dữ liệu. Tùy chọn này thuận tiện khi phát triển và gỡ lỗi một ứng dụng. Để thay thế cho tùy chọn này, bạn có thể sử dụng lệnh schema:sync từ CLI TypeORM.
  • dropSchema - đặt lại lược đồ mỗi khi kết nối được thiết lập. Cũng giống như tùy chọn trước, tùy chọn này chỉ nên được sử dụng trong quá trình phát triển và gỡ lỗi ứng dụng.
  • thực thể - đường dẫn nào để tìm mô tả mô hình. Xin lưu ý rằng tìm kiếm theo mặt nạ được hỗ trợ.
  • cli.entitiesDir là thư mục lưu trữ các mô hình được tạo từ TypeORM CLI theo mặc định.

Để có thể sử dụng tất cả các tính năng của TypeORM trong ứng dụng Nest, chúng ta cần nhập mô-đun TypeOrmModule в AppModule. Những thứ kia. của bạn AppModule sẽ trông như thế này:

ứng dụng.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 {}

Như bạn có thể đã nhận thấy, phương pháp forRoot cấu hình tương tự để làm việc với cơ sở dữ liệu được chuyển như trong tệp ormconfig.ts

Bước cuối cùng vẫn còn - thêm một số tác vụ để làm việc với TypeORM trong pack.json. Thực tế là CLI được viết bằng javascript và chạy trong môi trường nodejs. Tuy nhiên, tất cả các mô hình và quá trình di chuyển của chúng tôi sẽ được viết bằng bản đánh máy. Do đó, cần phải dịch mã các quá trình di chuyển và mô hình của chúng tôi trước khi sử dụng CLI. Để làm được điều này, chúng ta cần gói ts-node:

yarn add -D ts-node

Sau đó, thêm các lệnh cần thiết vào pack.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"

Lệnh đầu tiên, typeorm, thêm trình bao bọc ts-node để chạy cli TypeORM. Các lệnh còn lại là các phím tắt tiện lợi mà bạn, với tư cách là nhà phát triển, sẽ sử dụng hầu như hàng ngày:
migration:generate — tạo các di chuyển dựa trên những thay đổi trong mô hình của bạn.
migration:create — tạo một di chuyển trống.
migration:run — khởi động quá trình di chuyển.
Chà, bây giờ là vậy đó, chúng tôi đã thêm các gói cần thiết, định cấu hình ứng dụng để hoạt động với cơ sở dữ liệu cả từ cli và từ chính ứng dụng, đồng thời khởi chạy DBMS. Đã đến lúc thêm logic vào ứng dụng của chúng ta.

Cài đặt các gói tạo CRUD

Chỉ sử dụng Nest, bạn có thể tạo một API cho phép bạn tạo, đọc, cập nhật và xóa một thực thể. Giải pháp này sẽ linh hoạt nhất có thể nhưng trong một số trường hợp nó sẽ dư thừa. Ví dụ: nếu bạn cần nhanh chóng tạo một nguyên mẫu, bạn thường có thể hy sinh tính linh hoạt để lấy tốc độ phát triển. Nhiều khung cung cấp chức năng tạo CRUD bằng cách mô tả mô hình dữ liệu của một thực thể nhất định. Và Nest cũng không ngoại lệ! Chức năng này được cung cấp bởi gói @nestjsx/crud. Khả năng của nó rất thú vị:

  • dễ dàng cài đặt và cấu hình;
  • Tính độc lập của DBMS;
  • ngôn ngữ truy vấn mạnh mẽ với khả năng lọc, phân trang, sắp xếp, tải các mối quan hệ và các thực thể lồng nhau, bộ nhớ đệm, v.v.;
  • gói tạo yêu cầu ở giao diện người dùng;
  • dễ dàng ghi đè các phương thức điều khiển;
  • cấu hình nhỏ;
  • hỗ trợ tài liệu vênh vang.

Chức năng này được chia thành nhiều gói:

  • @nestjsx/crud - gói cơ bản mà người trang trí cung cấp Thô sơ() để tạo, cấu hình và xác thực tuyến đường;
  • @nestjsx/crud-request — một gói cung cấp trình tạo truy vấn/trình phân tích cú pháp để sử dụng ở phía giao diện người dùng;
  • @nestjsx/crud-typeorm — một gói để tích hợp với TypeORM, cung cấp dịch vụ TypeOrmCrudService cơ bản với các phương thức CRUD để làm việc với các thực thể trong cơ sở dữ liệu.

Trong hướng dẫn này chúng ta sẽ cần các gói tổjsx/crud và tổjsx/crud-typeorm. Đầu tiên, hãy đặt chúng

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

Các gói máy biến áp lớp и trình xác nhận lớp trong ứng dụng này là cần thiết để mô tả khai báo các quy tắc chuyển đổi các phiên bản mô hình và xác thực các yêu cầu đến tương ứng. Các gói này của cùng một tác giả nên giao diện tương tự nhau.

Triển khai trực tiếp CRUD

Chúng tôi sẽ lấy danh sách người dùng làm mô hình ví dụ. Người dùng sẽ có các trường sau: id, username, displayName, email. id - trường tăng tự động, email и username - các lĩnh vực độc đáo. Thật đơn giản! Tất cả những gì còn lại là triển khai ý tưởng của chúng tôi dưới dạng ứng dụng Nest.
Đầu tiên bạn cần tạo một mô-đun users, người sẽ chịu trách nhiệm làm việc với người dùng. Hãy sử dụng cli từ NestJS và thực thi lệnh trong thư mục gốc của dự án của chúng tôi nest g module users.

người dùng mô-đun Nest G

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)

Trong mô-đun này, chúng tôi sẽ thêm một thư mục thực thể, nơi chúng tôi sẽ có các mô hình của mô-đun này. Cụ thể, hãy thêm vào đây tệp user.entity.ts với mô tả về mô hình người dùng:

người dùng.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;
}

Để ứng dụng của chúng ta có thể “nhìn thấy” mô hình này, cần có trong mô-đun UsersModule nhập khẩu TypeOrmModule nội dung sau:

người dùng.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 {}

Tức là ở đây chúng tôi nhập TypeOrmModule, trong đó là tham số phương thức forFeature Chúng tôi chỉ ra danh sách các mô hình liên quan đến mô-đun này.

Tất cả những gì còn lại là tạo thực thể tương ứng trong cơ sở dữ liệu. Cơ chế di chuyển phục vụ cho những mục đích này. Để tạo di chuyển dựa trên những thay đổi trong mô hình, bạn cần chạy lệnh npm run migration:generate -- CreateUserTable:

tiêu đề tiết lộ

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

Chúng tôi không phải viết quá trình di chuyển theo cách thủ công, mọi thứ diễn ra một cách kỳ diệu. Đây chẳng phải là một phép lạ sao! Tuy nhiên, đó không phải là tất cả. Chúng ta hãy xem tệp di chuyển đã tạo:

1563346135367-CreatUserTable.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"`);
}
}

Như bạn có thể thấy, không chỉ phương thức bắt đầu di chuyển được tạo tự động mà còn cả phương thức khôi phục nó. Tuyệt vời!
Tất cả những gì còn lại là triển khai quá trình di chuyển này. Điều này được thực hiện bằng lệnh sau:

npm run migration:run.

Thế là xong, bây giờ những thay đổi trong lược đồ đã được di chuyển sang cơ sở dữ liệu.
Tiếp theo, chúng ta sẽ tạo một dịch vụ chịu trách nhiệm làm việc với người dùng và kế thừa nó từ TypeOrmCrudService. Kho lưu trữ của thực thể quan tâm phải được chuyển đến tham số của hàm tạo gốc, trong trường hợp của chúng tôi User kho.

người dùng.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);
}
}

Chúng tôi sẽ cần dịch vụ này trong bộ điều khiển users. Để tạo bộ điều khiển, hãy nhập vào bảng điều khiển nest g controller users/controllers/users

người dùng/bộ điều khiển/người dùng bộ điều khiển Nest g

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)

Hãy mở bộ điều khiển này và chỉnh sửa nó để thêm một chút phép thuật tổjsx/crud. Mỗi lớp UsersController Hãy thêm một trang trí như thế này:

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

Thô sơ là một công cụ trang trí bổ sung vào bộ điều khiển các phương thức cần thiết để làm việc với mô hình. Loại mô hình được chỉ định trong trường model.type cấu hình trang trí.
Bước thứ hai là triển khai giao diện CrudController<User>. Mã bộ điều khiển đã được lắp ráp trông như thế này:

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

Và đó là tất cả! Bây giờ bộ điều khiển hỗ trợ toàn bộ hoạt động với mô hình! Không tin tôi? Hãy thử ứng dụng của chúng tôi trong thực tế!

Tạo tập lệnh truy vấn trong TestMace

Để kiểm tra dịch vụ của chúng tôi, chúng tôi sẽ sử dụng IDE để làm việc với API TestMace. Tại sao lại là TestMace? So với các sản phẩm tương tự, nó có những ưu điểm sau:

  • làm việc mạnh mẽ với các biến. Hiện tại, có một số loại biến, mỗi loại đóng một vai trò cụ thể: biến tích hợp, biến động, biến môi trường. Mỗi biến thuộc về một nút có hỗ trợ cơ chế kế thừa;
  • Dễ dàng tạo tập lệnh mà không cần lập trình. Điều này sẽ được thảo luận dưới đây;
  • định dạng mà con người có thể đọc được cho phép bạn lưu dự án trong các hệ thống kiểm soát phiên bản;
  • tự động hoàn thành, tô sáng cú pháp, tô sáng giá trị biến;
  • Hỗ trợ mô tả API với khả năng nhập từ Swagger.

Hãy khởi động máy chủ của chúng tôi bằng lệnh npm start và cố gắng truy cập vào danh sách người dùng. Danh sách người dùng, dựa trên cấu hình bộ điều khiển của chúng tôi, có thể được lấy từ url localhost:3000/users. Hãy thực hiện một yêu cầu tới url này.
Sau khi chạy TestMace bạn có thể thấy giao diện như thế này:

Tạo CRUD nhanh chóng với Nest, @nestjsx/crud và TestMace

Ở trên cùng bên trái là cây dự án có nút gốc Dự án. Hãy thử tạo yêu cầu đầu tiên để lấy danh sách người dùng. Đối với điều này, chúng tôi sẽ tạo ra Bước yêu cầu nút Điều này được thực hiện trong menu ngữ cảnh của nút Dự án Thêm nút -> requestStep.

Tạo CRUD nhanh chóng với Nest, @nestjsx/crud và TestMace

Trong trường URL, dán localhost:3000/users và chạy yêu cầu. Chúng tôi sẽ nhận được mã 200 với một mảng trống trong nội dung phản hồi. Có thể hiểu được, chúng tôi chưa thêm ai cả.
Hãy tạo một tập lệnh bao gồm các bước sau:

  1. tạo người dùng;
  2. yêu cầu id của người dùng mới được tạo;
  3. xóa theo id người dùng đã tạo ở bước 1.

Vì vậy, chúng ta hãy đi. Để thuận tiện, hãy tạo một nút như Thư mục. Về cơ bản, đây chỉ là một thư mục mà chúng ta sẽ lưu toàn bộ tập lệnh. Để tạo nút Thư mục, chọn Dự án từ menu ngữ cảnh của nút Thêm nút -> Thư mục. Hãy gọi nút kiểm tra-tạo. Bên trong một nút kiểm tra-tạo Hãy tạo yêu cầu đầu tiên để tạo người dùng. Hãy gọi nút mới được tạo tạo người dùng. Nghĩa là, hiện tại hệ thống phân cấp nút sẽ trông như thế này:

Tạo CRUD nhanh chóng với Nest, @nestjsx/crud và TestMace

Hãy chuyển đến tab đang mở tạo người dùng nút. Hãy nhập các tham số sau cho yêu cầu:

  • Loại yêu cầu - POST
  • URL - localhost:3000/người dùng
  • Nội dung - JSON có giá trị {"email": "[email protected]", "displayName": "New user", "username": "user"}

Hãy thực hiện yêu cầu này. Ứng dụng của chúng tôi cho biết rằng bản ghi đã được tạo.

Tạo CRUD nhanh chóng với Nest, @nestjsx/crud và TestMace

Vâng, hãy kiểm tra thực tế này. Để hoạt động với id của người dùng đã tạo ở các bước tiếp theo, tham số này phải được lưu lại. Cơ chế này là hoàn hảo cho việc này. biến động. Hãy sử dụng ví dụ của chúng tôi để xem cách làm việc với chúng. Trong tab được phân tích cú pháp của phản hồi, bên cạnh nút id trong menu ngữ cảnh, hãy chọn mục Gán cho biến. Trong hộp thoại bạn phải thiết lập các thông số sau:

  • Node — trong đó tổ tiên tạo ra một biến động. Cùng lựa chọn nào kiểm tra-tạo
  • Tên biến - tên của biến này. Hãy gọi userId.

Đây là quá trình tạo một biến động trông như thế nào:

Tạo CRUD nhanh chóng với Nest, @nestjsx/crud và TestMace

Bây giờ, mỗi lần truy vấn này được thực thi, giá trị của biến động sẽ được cập nhật. Và bởi vì các biến động hỗ trợ cơ chế kế thừa phân cấp, biến userId sẽ có sẵn ở thế hệ con cháu kiểm tra-tạo nút của bất kỳ cấp độ lồng nhau nào.
Biến này sẽ hữu ích cho chúng tôi trong yêu cầu tiếp theo. Cụ thể, chúng tôi sẽ yêu cầu người dùng mới được tạo. Là con của một nút kiểm tra-tạo chúng tôi sẽ tạo một yêu cầu kiểm tra xem có tồn tại không với tham số url như nhau localhost:3000/users/${$dynamicVar.userId}. Xem thiết kế ${variable_name} đây là nhận giá trị của một biến. Bởi vì Chúng tôi có một biến động, vì vậy để có được nó, bạn cần truy cập vào đối tượng $dynamicVar, tức là truy cập hoàn toàn vào một biến động userId sẽ trông như thế này ${$dynamicVar.userId}. Hãy thực hiện yêu cầu và đảm bảo rằng dữ liệu được yêu cầu chính xác.
Bước cuối cùng còn lại là yêu cầu xóa. Chúng tôi cần nó không chỉ để kiểm tra hoạt động xóa mà còn để tự dọn dẹp cơ sở dữ liệu, bởi vì Các trường email và tên người dùng là duy nhất. Vì vậy, trong nút kiểm tra-tạo, chúng tôi sẽ tạo yêu cầu xóa người dùng với các tham số sau

  • Loại yêu cầu - XÓA
  • url - localhost:3000/users/${$dynamicVar.userId}

Hãy khởi động. Chúng tôi đợi. Chúng tôi tận hưởng kết quả)

Chà, bây giờ chúng ta có thể chạy toàn bộ tập lệnh này bất cứ lúc nào. Để chạy tập lệnh, bạn cần chọn từ menu ngữ cảnh kiểm tra-tạo mục nút chạy.

Tạo CRUD nhanh chóng với Nest, @nestjsx/crud và TestMace

Các nút trong tập lệnh sẽ được thực thi lần lượt
Bạn có thể lưu tập lệnh này vào dự án của mình bằng cách chạy Tệp -> Lưu dự án.

Kết luận

Đơn giản là tất cả các tính năng của các công cụ được sử dụng không thể phù hợp với định dạng của bài viết này. Về phần thủ phạm chính - gói hàng tổjsx/crud - các chủ đề sau vẫn chưa được khám phá:

  • xác nhận tùy chỉnh và chuyển đổi mô hình;
  • ngôn ngữ truy vấn mạnh mẽ và cách sử dụng thuận tiện của nó ở phía trước;
  • xác định lại và thêm các phương thức mới vào bộ điều khiển thô;
  • hỗ trợ vênh vang;
  • quản lý bộ nhớ đệm.

Tuy nhiên, ngay cả những gì được mô tả trong bài viết cũng đủ để hiểu rằng ngay cả một khung doanh nghiệp như NestJS cũng có các công cụ để tạo nguyên mẫu ứng dụng nhanh chóng. Và một IDE tuyệt vời như TestMace cho phép bạn duy trì một tốc độ nhất định.

Mã nguồn của bài viết này, cùng với dự án TestMace, có sẵn trong kho https://github.com/TestMace/nest-rest. Để mở một dự án TestMace chỉ cần làm điều đó trong ứng dụng Tệp -> Mở dự án.

Nguồn: www.habr.com

Thêm một lời nhận xét