Krijimi i shpejtë CRUD me nest, @nestjsx/crud dhe TestMace

Krijimi i shpejtë CRUD me nest, @nestjsx/crud dhe TestMace

Aktualisht, REST API është bërë standardi për zhvillimin e aplikacioneve në ueb, duke ju lejuar të ndani zhvillimin në pjesë të pavarura. Për UI, korniza të ndryshme të njohura si Angular, React, Vue dhe të tjera përdoren aktualisht. Zhvilluesit e Backend-it mund të zgjedhin nga një shumëllojshmëri e gjerë gjuhësh dhe kornizash. Sot do të doja të flisja për një kornizë të tillë si NestJS. Ne jemi në TestMace Ne e përdorim atë në mënyrë aktive për projekte të brendshme. Përdorimi i folesë dhe paketës @nestjsx/crud, do të krijojmë një aplikacion të thjeshtë CRUD.

Pse NestJS

Kohët e fundit, shumë korniza mbështetëse janë shfaqur në komunitetin JavaScript. Dhe nëse për sa i përket funksionalitetit ato ofrojnë mundësi të ngjashme me Nest, atëherë ai përfundimisht fiton në një gjë - kjo është arkitektura. Karakteristikat e mëposhtme të NestJS ju lejojnë të krijoni aplikacione industriale dhe të zhvilloni shkallë për ekipe të mëdha:

  • duke përdorur TypeScript si gjuhën kryesore të zhvillimit. Megjithëse NestJS mbështet JavaScript, disa nga funksionet mund të mos funksionojnë, veçanërisht kur bëhet fjalë për paketat e palëve të treta;
  • prania e një kontejneri DI, i cili ju lejon të krijoni komponentë të lidhur lirshëm;
  • funksionaliteti i vetë kornizës është i ndarë në komponentë të pavarur të këmbyeshëm. Për shembull, nën kapuç si kornizë mund të përdoret si ekspresDhe agjëroj, për të punuar me bazën e të dhënave fole jashtë kutisë ofron lidhje me tip tipik, manguta, vazhdimin;
  • NestJS është i pavarur nga platforma dhe mbështet REST, GraphQL, Websockets, gRPC, etj.

Vetë korniza është frymëzuar nga korniza Angular frontend dhe konceptualisht ka shumë të përbashkëta me të.

Instalimi i NestJS dhe vendosja e një projekti

Nest përmban një paketë fole/cli, i cili ju lejon të vendosni shpejt një kornizë bazë aplikacioni. Instaloni këtë paketë globalisht:

npm install --global @nest/cli

Pas instalimit, ne do të gjenerojmë kornizën bazë të aplikacionit tonë me emrin fole-rest. Kjo bëhet duke përdorur komandën nest new nest-rest.

fole e re 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

Ne do të zgjedhim fije si menaxherin tonë të paketave.
Tani për tani, ju mund të filloni serverin me komandën npm start dhe duke shkuar në adresë http://localhost:3000 ju mund të shihni faqen kryesore. Megjithatë, ne jemi këtu për këtë dhe ne po ecim përpara.

Vendosja e punës me bazën e të dhënave

Si një DBMS për këtë artikull, zgjodha PostrgreSQL. Nuk ka asnjë mosmarrëveshje për shijet, për mendimin tim, kjo është DBMS më e pjekur që ka të gjitha tiparet e nevojshme. Siç u përmend tashmë, Nest ofron integrim me paketa të ndryshme për të punuar me bazat e të dhënave. Sepse Meqenëse zgjedhja ime ra në PostgreSQL, do të ishte logjike të zgjidhja TypeORM si ORM. Instaloni paketat e nevojshme për integrim me bazën e të dhënave:

yarn add typeorm @nestjs/typeorm pg

Me radhë, për çfarë shërben çdo paketë:

  1. typeorm - një paketë direkt nga vetë ORM;
  2. @nestjs/typeorm - Paketa TypeORM për NestJS. Shton module për import në modulet e projektit, si dhe një grup dekoruesish ndihmës;
  3. pg është një drejtues për të punuar me PostgreSQL.

Në rregull, paketat janë instaluar, tani ju duhet të filloni vetë bazën e të dhënave. Për të vendosur bazën, unë do të përdor docker-compose.yml me përmbajtjen e mëposhtme:

prerës-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

Siç mund ta shihni, ky skedar konfiguron nisjen e 2 kontejnerëve:

  1. db është një kontejner direkt me një bazë të dhënash. Në rastin tonë, përdoret versioni 11.2 i postgresql;
  2. adminer - menaxher i bazës së të dhënave. Ofron një ndërfaqe në internet për shikimin dhe menaxhimin e bazës së të dhënave.

Për të punuar me lidhjet tcp, shtova konfigurimin e mëposhtëm.

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

Kjo është e gjitha, ju mund të ekzekutoni kontejnerët me komandën docker-compose up -d. Ose në një tastierë të veçantë me komandën docker-compose up.

Pra, paketat u instaluan, baza u lançua, mbetet t'i bëjmë miq me njëri-tjetrin. Për ta bërë këtë, shtoni skedarin ormconfig.js në rrënjën e projektit me përmbajtjen e mëposhtme:

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

Ky konfigurim do të përdoret për cli typeorm.

Le të hedhim një vështrim më të afërt në këtë konfigurim. Në rreshtat 3 dhe 4 marrim emrin e përdoruesit dhe fjalëkalimin nga variablat e mjedisit. Kjo është e dobishme kur keni mjedise të shumta (dev, skena, prod, etj). Emri i parazgjedhur i përdoruesit është postgres, fjalëkalimi është shembull. Përndryshe, konfigurimi është i parëndësishëm, kështu që ne do të përqendrohemi vetëm në parametrat më interesantë:

  • synchronize Përcakton nëse skema e bazës së të dhënave duhet të krijohet automatikisht kur të fillojë aplikacioni. Kini kujdes me këtë opsion dhe mos e përdorni në prodhim, përndryshe do të humbni të dhëna. Ky opsion është i dobishëm kur zhvilloni dhe korrigjoni një aplikacion. Si një alternativë ndaj këtij opsioni, mund të përdorni komandën schema:sync nga CLI TypeORM.
  • dropSchema - Hiqeni skemën sa herë që vendoset një lidhje. Gjithashtu, si ai i mëparshmi, ky opsion duhet të përdoret vetëm gjatë zhvillimit dhe korrigjimit të aplikacionit.
  • entitete - cilat shtigje duhet kërkuar për përshkrimin e modeleve. Ju lutemi vini re se kërkimi i maskave mbështetet.
  • cli.entitiesDir është drejtoria ku modelet e krijuara nga CLI TypeORM duhet të shtohen si parazgjedhje.

Në mënyrë që ne të përdorim të gjitha veçoritë e TypeORM në aplikacionin tonë Nest, duhet të importojmë modulin TypeOrmModule в AppModule. Ato. juaj AppModule do të duket kështu:

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

Siç e keni vënë re, në metodë forRoot kalohet i njëjti konfigurim për të punuar me bazën e të dhënave si në skedarin ormconfig.ts

Prekja e fundit mbetet - për të shtuar disa detyra për të punuar me TypeORM në package.json. Fakti është se CLI është shkruar në javascript dhe funksionon në mjedisin nodejs. Megjithatë, të gjitha modelet dhe migrimet tona do të shkruhen me shkrim. Prandaj, është e nevojshme të transpilojmë migrimet dhe modelet tona përpara se të përdorim CLI. Për ta bërë këtë, na duhet paketa ts-node:

yarn add -D ts-node

Pas kësaj, shtoni komandat e nevojshme në 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"

Komanda e parë, typeorm, shton një mbështjellës ts-nyje për të nisur klipin TypeORM. Pjesa tjetër e komandave janë shkurtore të dobishme që ju, si zhvillues, do t'i përdorni pothuajse çdo ditë:
migration:generate - krijoni migrime bazuar në ndryshimet në modelet tuaja.
migration:create - krijimi i një migrimi bosh.
migration:run - filloni migrimet.
Epo, tani kjo është e gjitha e sigurt, ne kemi shtuar paketat e nevojshme, kemi konfiguruar aplikacionin të punojë me bazën e të dhënave si nga cli ashtu edhe nga vetë aplikacioni, dhe gjithashtu kemi nisur DBMS. Është koha për të shtuar logjikën në aplikacionin tonë.

Instalimi i paketave për krijimin e CRUD

Duke përdorur vetëm Nest, mund të krijosh një API që të lejon të krijosh, lexosh, përditësosh dhe fshish një entitet. Një zgjidhje e tillë do të jetë sa më fleksibël, por në disa raste do të jetë e tepërt. Për shembull, nëse duhet të krijoni shpejt një prototip, atëherë shpesh mund të sakrifikoni fleksibilitetin për hir të shpejtësisë së zhvillimit. Shumë korniza ofrojnë funksionalitetin e gjenerimit të CRUD duke përshkruar modelin e të dhënave të një entiteti të caktuar. Dhe Nest nuk bën përjashtim! Ky funksion ofrohet nga paketa @nestjsx/crud. Mundësitë e tij janë shumë interesante:

  • instalim dhe konfigurim i lehtë;
  • pavarësia nga DBMS;
  • gjuhë e fuqishme e pyetjeve me aftësinë për të filtruar, faqezuar, renditur, ngarkuar marrëdhëniet dhe entitetet e ndërlidhura, caching, etj.;
  • një paketë për gjenerimin e kërkesave për front-end;
  • ripërcaktimi i lehtë i metodave të kontrolluesit;
  • konfigurim i vogël;
  • mbështetje për dokumentacionin e rrëmbyeshëm.

Funksionaliteti është i ndarë në disa paketa:

  • @nestjsx/crud - paketa bazë e ofruar nga dekoruesi E papërpunuar() për gjenerimin, konfigurimin dhe vlefshmërinë e rrugës;
  • @nestjsx/crud-request - një paketë që ofron një ndërtues pyetjesh / analizues për përdorim në anën e përparme;
  • @nestjsx/crud-typeform - një paketë për integrim me TypeORM, e cila ofron një shërbim bazë TypeOrmCrudService me metoda CRUD për të punuar me entitetet në bazën e të dhënave.

Për këtë udhëzues, do të na duhen paketa folejsx/crud dhe folejsx/crud-typeform. Së pari, le t'i vendosim ato

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

Paketat klasë-transformator и klas-validues në këtë aplikacion kërkohet përshkrimi deklarativ i rregullave për transformimin e instancave model dhe vërtetimin e kërkesave hyrëse, përkatësisht. Këto paketa janë nga i njëjti autor, kështu që ndërfaqet janë të ngjashme.

Zbatimi i drejtpërdrejtë i CRUD

Si shembull i një modeli, ne do të marrim një listë të përdoruesve. Përdoruesit do të kenë fushat e mëposhtme: id, username, displayName, email. id - fusha e rritjes automatike, email и username - fusha unike. Gjithçka është e thjeshtë! Mbetet të realizojmë idenë tonë në formën e një aplikacioni Nest.
Së pari ju duhet të krijoni një modul usersi cili do të jetë përgjegjës për të punuar me përdoruesit. Le të përdorim cli nga NestJS, dhe në direktorinë rrënjë të projektit tonë ne do të ekzekutojmë komandën nest g module users.

përdoruesit e modulit 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)

Në këtë modul do të shtojmë dosjen entities ku do të kemi modelet e këtij moduli. Në veçanti, le të shtojmë skedarin user.entity.ts këtu me një përshkrim të modelit të përdoruesit:

përdorues.entitet.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;
}

Në mënyrë që ky model të "shihet" nga aplikacioni ynë, është e nevojshme në modul UsersModule importit TypeOrmModule përmbajtjen e mëposhtme:

përdoruesit.moduli.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 {}

Pra, këtu po importojmë TypeOrmModule, ku si parametër i metodës forFeature specifikoni listën e modeleve që lidhen me këtë modul.

Mbetet për të krijuar entitetin përkatës në bazën e të dhënave. Për këto qëllime përdoret mekanizmi i migrimit. Për të krijuar një migrim bazuar në ndryshimet e modelit, ekzekutoni komandën npm run migration:generate -- CreateUserTable:

titull spoiler

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

Nuk duhej ta shkruanim migrimin me dorë, gjithçka ndodhi me magji. A nuk është kjo një mrekulli! Megjithatë, kjo nuk është e gjitha. Le të hedhim një vështrim në skedarin e migrimit të krijuar:

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

Siç mund ta shihni, jo vetëm metoda për fillimin e migrimit u krijua automatikisht, por edhe metoda për ta kthyer atë. Fantastike!
Mbetet vetëm për të rrokullisur këtë migrim. Kjo bëhet me komandën e mëposhtme:

npm run migration:run.

Kjo është ajo, tani ndryshimet e skemës kanë migruar në bazën e të dhënave.
Më pas, ne do të krijojmë një shërbim që do të jetë përgjegjës për të punuar me përdoruesit dhe për ta trashëguar atë TypeOrmCrudService. Është e nevojshme të kalohet depoja e entitetit me interes në parametrin e konstruktorit mëmë, në rastin tonë User depo.

përdoruesit.shërbimi.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);
}
}

Ne kemi nevojë për këtë shërbim në kontrollues users. Për të krijuar një kontrollues, shkruani në tastierë nest g controller users/controllers/users

nest g kontrollues përdorues/kontrollues/përdorues

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)

Hapeni këtë kontrollues dhe modifikoni për të shtuar pak magji folejsx/crud. për klasë UsersController Le të shtojmë një dekorues si ky:

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

E papërpunuar është një dekorues që i shton kontrolluesit metodat e nevojshme për të punuar me modelin. Lloji i modelit tregohet në fushë model.type konfigurimi i dekoruesit.
Hapi i dytë është zbatimi i ndërfaqes CrudController<User>. Kodi "i montuar" i kontrolluesit duket si ky:

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

Dhe kjo është e gjitha! Tani kontrolluesi mbështet të gjithë grupin e operacioneve me modelin! Nuk besoj? Le ta provojmë aplikacionin tonë në veprim!

Kërkesat e skriptimit në TestMace

Për të testuar shërbimin tonë, ne do të përdorim IDE për të punuar me API TestMace. Pse të testoni Mac? Krahasuar me produkte të ngjashme, ai ka përparësitë e mëposhtme:

  • punë e fuqishme me variabla. Për momentin, ekzistojnë disa lloje të variablave, secila prej të cilave kryen një rol specifik: variablat e integruar, variablat dinamikë, variablat e mjedisit. Çdo variabël i përket një nyje me mbështetje për mekanizmin e trashëgimisë;
  • skriptim i lehtë pa programim. Kjo do të diskutohet më poshtë;
  • format i lexueshëm nga njeriu që ju lejon të ruani projektin në sistemet e kontrollit të versionit;
  • plotësimi automatik, theksimi i sintaksës, nxjerrja në pah e vlerave të variablave;
  • Mbështetje për përshkrimin e API-së me aftësinë për të importuar nga Swagger.

Le të fillojmë serverin tonë me komandën npm start dhe përpiquni të hyni në listën e përdoruesve. Lista e përdoruesve, duke gjykuar nga konfigurimi i kontrolluesit tonë, mund të merret nga url localhost:3000/users. Le të bëjmë një kërkesë për këtë url.
Pas ekzekutimit të TestMace, mund të shihni këtë ndërfaqe:

Krijimi i shpejtë CRUD me nest, @nestjsx/crud dhe TestMace

Në krye të majtë është pema e projektit me nyjen rrënjë Projekt. Le të përpiqemi të krijojmë kërkesën e parë për të marrë një listë të përdoruesve. Për ta bërë këtë, ne do të krijojmë Hapi i kërkesës nyje. Kjo bëhet në menynë e kontekstit të nyjës së Projektit. Shto nyje -> RequestStep.

Krijimi i shpejtë CRUD me nest, @nestjsx/crud dhe TestMace

Ngjit localhost:3000/users në fushën URL dhe ekzekuto kërkesën. Ne marrim kodin 200 me një grup bosh në trupin e përgjigjes. Është e kuptueshme, ende nuk kemi shtuar asnjë.
Le të krijojmë një skript që do të përfshijë hapat e mëposhtëm:

  1. krijimi i përdoruesve;
  2. pyetja sipas ID-së së përdoruesit të sapokrijuar;
  3. fshini sipas ID-së së përdoruesit të krijuar në hapin 1.

Pra, le të shkojmë. Për lehtësi, le të krijojmë një nyje si Dosje. Në fakt, kjo është vetëm një dosje në të cilën do të ruajmë të gjithë skriptin. Për të krijuar një nyje Folder, në menynë e kontekstit të nyjes së Projektit, zgjidhni Shto nyje -> Dosja. Le ta quajmë nyjen kontrollo-krijoj. Brenda nyjes kontrollo-krijoj Le të krijojmë kërkesën tonë të parë për të krijuar një përdorues. Le të emërtojmë nyjen e krijuar rishtazi krijo-përdorues. Kjo do të thotë, për momentin hierarkia e nyjeve do të duket kështu:

Krijimi i shpejtë CRUD me nest, @nestjsx/crud dhe TestMace

Le të shkojmë te skeda e hapur krijo-përdorues nyje. Le të fusim parametrat e mëposhtëm për kërkesën:

  • Lloji i kërkesës - POST
  • URL - localhost:3000/përdorues
  • Trupi - JSON me vlerë {"email": "[email protected]", "displayName": "New user", "username": "user"}

Le ta zbatojmë këtë kërkesë. Aplikacioni ynë thotë se hyrja është krijuar.

Krijimi i shpejtë CRUD me nest, @nestjsx/crud dhe TestMace

Epo, le ta kontrollojmë këtë fakt. Për të funksionuar me ID-në e përdoruesit të krijuar në hapat e mëpasshëm, ky parametër duhet të ruhet. Ky mekanizëm është i përsosur për këtë. variablat dinamike. Le të hedhim një vështrim se si ne punojmë me ta duke përdorur shembullin tonë. Në skedën e analizuar të përgjigjes, në nyjen id në menynë e kontekstit, zgjidhni artikullin Cakto në variabël. Parametrat e mëposhtëm duhet të specifikohen në kutinë e dialogut:

  • Nyjë - në cilin prej paraardhësve të krijojë një ndryshore dinamike. Le të zgjedhim kontrollo-krijoj
  • Emri i ndryshueshëm është emri i kësaj variabli. Le të thërrasim userId.

Ja se si duket procesi i krijimit të një ndryshoreje dinamike:

Krijimi i shpejtë CRUD me nest, @nestjsx/crud dhe TestMace

Tani, sa herë që ekzekutohet ky pyetje, vlera e ndryshores dinamike do të përditësohet. Dhe që nga ajo kohë variablat dinamike mbështesin mekanizmin e trashëgimisë hierarkike, variabël userId do të jetë në dispozicion në pasardhës kontrollo-krijoj nyje e çdo niveli foleje.
Në kërkesën tjetër, kjo variabël do të jetë e dobishme për ne. Domethënë, ne do të kërkojmë një përdorues të krijuar rishtazi. Si një fëmijë i një nyje kontrollo-krijoj ne do të krijojmë një kërkesë kontrolloni nëse ekziston me parametër url të barabartë localhost:3000/users/${$dynamicVar.userId}. Shikoni ndërtimin ${variable_name} po merr vlerën e një ndryshoreje. Sepse ne kemi një ndryshore dinamike, atëherë për ta marrë atë duhet t'i referoheni objektit $dynamicVar, pra aksesi i plotë i një ndryshoreje dinamike userId do të duket kështu ${$dynamicVar.userId}. Le të ekzekutojmë kërkesën dhe të sigurohemi që të dhënat janë kërkuar në mënyrë korrekte.
Mbetet prekja e fundit - të bëni një kërkesë për fshirje. Na duhet jo vetëm për të kontrolluar funksionimin e heqjes, por edhe, si të thuash, për të pastruar veten në bazën e të dhënave, sepse fushat e emailit dhe emrit të përdoruesit janë unike. Pra, në nyjen check-create, ne do të krijojmë një kërkesë delete-user me parametrat e mëposhtëm

  • Lloji i Kërkesës - FSHIJE
  • URL - localhost:3000/users/${$dynamicVar.userId}

Ne nisim. Ne presim. shijoni rezultatin)

Epo, tani ne mund ta ekzekutojmë plotësisht këtë skenar në çdo kohë. Për të ekzekutuar skriptin, zgjidhni nga menyja e kontekstit kontrollo-krijoj pikë nyje run.

Krijimi i shpejtë CRUD me nest, @nestjsx/crud dhe TestMace

Nyjet në skript do të ekzekutohen njëra pas tjetrës
Ju mund ta ruani këtë skript në projektin tuaj duke ekzekutuar Skedari -> Ruaj projektin.

Përfundim

Të gjitha çipat e mjeteve të përdorura thjesht nuk mund të përshtateshin në formatin e këtij artikulli. Sa i përket fajtorit kryesor - paketës folejsx/crud - temat e mëposhtme mbetën të pambuluara:

  • vlefshmëria dhe transformimi me porosi i modeleve;
  • gjuhë e fuqishme e pyetjeve dhe përdorimi i përshtatshëm i saj në pjesën e përparme;
  • ripërcaktimi dhe shtimi i metodave të reja te kontrollorët e papërpunuar;
  • suporti swagger;
  • menaxhimi i caching.

Sidoqoftë, edhe ajo që përshkruhet në artikull është e mjaftueshme për të kuptuar se edhe një kornizë e tillë ndërmarrje si NestJS ka mjete për prototipimin e shpejtë të aplikimit. Dhe një IDE kaq e lezetshme si TestMace ju lejon të mbani një ritëm të caktuar.

Kodi burimor për këtë artikull, së bashku me projektin TestMace, në dispozicion në depo https://github.com/TestMace/nest-rest. Për të hapur një projekt TestMace mjafton të ekzekutohet në aplikacion Skedari -> Hap projektin.

Burimi: www.habr.com

Shto një koment