Mabilis na paggawa ng CRUD gamit ang nest, @nestjsx/crud at TestMace

Mabilis na paggawa ng CRUD gamit ang nest, @nestjsx/crud at TestMace

Sa kasalukuyan, ang REST API ay naging isang pamantayan para sa pagbuo ng web application, na nagpapahintulot sa pag-unlad na hatiin sa mga independiyenteng bahagi. Kasalukuyang ginagamit para sa UI ang iba't ibang sikat na framework gaya ng Angular, React, Vue at iba pa. Ang mga developer ng backend ay maaaring pumili mula sa isang malawak na iba't ibang mga wika at mga framework. Ngayon nais kong pag-usapan ang tungkol sa isang balangkas tulad ng NestJS. Tayo ay nasa TestMace Aktibong ginagamit namin ito para sa mga panloob na proyekto. Gamit ang pugad at pakete @nestjsx/crud, gagawa kami ng simpleng CRUD application.

Bakit ang NestJS

Kamakailan, napakaraming backend framework ang lumitaw sa komunidad ng JavaScript. At kung sa mga tuntunin ng pag-andar ay nagbibigay sila ng mga pagkakataon na katulad ng Nest, kung gayon sa isang bagay tiyak na panalo ito - ito ang arkitektura. Nagbibigay-daan sa iyo ang mga sumusunod na feature ng NestJS na lumikha ng mga pang-industriya na application at pag-develop ng sukat sa malalaking team:

  • gamit ang TypeScript bilang pangunahing wika ng pag-unlad. Bagama't sinusuportahan ng NestJS ang JavaScript, maaaring hindi gumana ang ilang functionality, lalo na kung pinag-uusapan natin ang tungkol sa mga third-party na package;
  • ang pagkakaroon ng isang lalagyan ng DI, na nagpapahintulot sa iyo na lumikha ng maluwag na pinagsamang mga bahagi;
  • Ang pag-andar ng mismong balangkas ay nahahati sa mga independiyenteng mapagpapalit na mga bahagi. Halimbawa, sa ilalim ng talukbong bilang isang balangkas maaari itong magamit bilang ekspresAt fastify, upang gumana sa database, ang nest out of the box ay nagbibigay ng mga binding sa typorm, mongoose, sequelize;
  • Ang NestJS ay platform agnostic at sumusuporta sa REST, GraphQL, Websockets, gRPC, atbp.

Ang framework mismo ay inspirasyon ng Angular frontend framework at sa konsepto ay may maraming pagkakatulad dito.

Pag-install ng NestJS at Pag-deploy ng Project

Naglalaman ng package ang Nest pugad/cli, na nagbibigay-daan sa iyong mabilis na mag-deploy ng pangunahing balangkas ng aplikasyon. I-install natin ang package na ito sa buong mundo:

npm install --global @nest/cli

Pagkatapos ng pag-install, bubuo kami ng pangunahing balangkas ng aming aplikasyon na may pangalan nest-rest. Ginagawa ito gamit ang command nest new nest-rest.

pugad bagong pugad-pahinga

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

Pipili kami ng sinulid bilang aming manager ng package.
Sa puntong ito maaari mong simulan ang server gamit ang utos npm start at pumunta sa address http://localhost:3000 makikita mo ang pangunahing pahina. Gayunpaman, hindi ito ang dahilan kung bakit kami nagtipon dito at kami ay nagpapatuloy.

Pag-set up ng trabaho sa database

Pinili ko ang PostrgreSQL bilang DBMS para sa artikulong ito. Walang pagtatalo tungkol sa panlasa; sa palagay ko, ito ang pinaka-mature na DBMS, na mayroong lahat ng kinakailangang kakayahan. Gaya ng nabanggit na, nagbibigay ang Nest ng integration sa iba't ibang package para gumana sa mga database. kasi Dahil ang aking pinili ay nahulog sa PostgreSQL, magiging lohikal na piliin ang TypeORM bilang isang ORM. I-install natin ang mga kinakailangang pakete para sa pagsasama sa database:

yarn add typeorm @nestjs/typeorm pg

Sa pagkakasunud-sunod, kung ano ang kailangan ng bawat pakete para sa:

  1. typeorm - isang pakete nang direkta mula sa ORM mismo;
  2. @nestjs/typeorm - TypeORM package para sa NestJS. Nagdaragdag ng mga module para sa pag-import sa mga module ng proyekto, pati na rin ang isang hanay ng mga helper decorator;
  3. pg - driver para sa pagtatrabaho sa PostgreSQL.

Okay, ang mga pakete ay naka-install, ngayon kailangan mong ilunsad ang database mismo. Upang i-deploy ang database, gagamitin ko ang docker-compose.yml na may sumusunod na nilalaman:

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

Gaya ng nakikita mo, kino-configure ng file na ito ang paglulunsad ng 2 container:

  1. Ang db ay isang lalagyan na direktang naglalaman ng database. Sa aming kaso, postgresql bersyon 11.2 ay ginagamit;
  2. tagapangasiwaβ€”tagapamahala ng database. Nagbibigay ng web interface para sa pagtingin at pamamahala ng database.

Upang gumana sa mga koneksyon sa tcp, idinagdag ko ang sumusunod na config.

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

Iyon lang, maaari mong simulan ang mga lalagyan gamit ang command docker-compose up -d. O sa isang hiwalay na console na may utos docker-compose up.

Kaya, ang mga pakete ay na-install, ang database ay inilunsad, ang natitira lamang ay upang makipagkaibigan sa isa't isa. Upang gawin ito, kailangan mong idagdag ang sumusunod na file sa root ng proyekto: 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"
}
}

Gagamitin ang configuration na ito para sa cli typeorm.

Tingnan natin ang pagsasaayos na ito nang mas detalyado. Sa mga linya 3 at 4 nakukuha namin ang username at password mula sa mga variable ng kapaligiran. Maginhawa ito kapag mayroon kang maraming kapaligiran (dev, stage, prod, atbp). Bilang default, ang username ay postgres at ang password ay halimbawa. Ang natitirang bahagi ng config ay walang halaga, kaya't kami ay tumutuon lamang sa mga pinaka-kagiliw-giliw na mga parameter:

  • i-synchronize - Isinasaad kung ang database schema ay dapat na awtomatikong gawin kapag nagsimula ang application. Mag-ingat sa pagpipiliang ito at huwag gamitin ito sa paggawa, kung hindi, mawawalan ka ng data. Ang pagpipiliang ito ay maginhawa kapag bumubuo at nagde-debug ng isang application. Bilang kahalili sa opsyong ito, maaari mong gamitin ang command schema:sync mula sa CLI TypeORM.
  • dropSchema - i-reset ang schema tuwing magkakaroon ng koneksyon. Tulad ng nauna, ang opsyon na ito ay dapat gamitin lamang sa panahon ng pag-develop at pag-debug ng application.
  • entity - kung aling mga landas ang hahanapin para sa mga paglalarawan ng mga modelo. Pakitandaan na ang paghahanap sa pamamagitan ng maskara ay suportado.
  • Ang cli.entitiesDir ay ang direktoryo kung saan ang mga modelong ginawa mula sa TypeORM CLI ay dapat na nakaimbak bilang default.

Para magamit namin ang lahat ng feature ng TypeORM sa aming Nest application, kailangan naming i-import ang module TypeOrmModule Π² AppModule. Yung. iyong AppModule ganito ang ganito:

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

Tulad ng napansin mo, ang pamamaraan forRoot ang parehong configuration para sa pagtatrabaho sa database ay inililipat tulad ng sa ormconfig.ts file

Ang huling pagpindot ay nananatili - magdagdag ng ilang mga gawain para sa pagtatrabaho sa TypeORM sa package.json. Ang katotohanan ay ang CLI ay nakasulat sa javascript at tumatakbo sa kapaligiran ng nodejs. Gayunpaman, ang lahat ng aming mga modelo at paglilipat ay isusulat sa typescript. Samakatuwid, kinakailangang i-transpilate ang aming mga paglilipat at modelo bago gamitin ang CLI. Para dito kailangan namin ang ts-node package:

yarn add -D ts-node

Pagkatapos nito, idagdag ang mga kinakailangang command sa 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"

Ang unang command, typeorm, ay nagdaragdag ng ts-node wrapper upang patakbuhin ang TypeORM cli. Ang natitirang mga utos ay mga maginhawang shortcut na gagamitin mo, bilang isang developer, halos araw-araw:
migration:generate β€” paggawa ng mga paglilipat batay sa mga pagbabago sa iyong mga modelo.
migration:create β€” paglikha ng walang laman na paglipat.
migration:run β€” paglulunsad ng mga migrasyon.
Well, iyon na ngayon, idinagdag namin ang mga kinakailangang pakete, na-configure ang application upang gumana sa database kapwa mula sa cli at mula sa application mismo, at inilunsad din ang DBMS. Panahon na upang magdagdag ng lohika sa aming aplikasyon.

Pag-install ng mga pakete para sa paglikha ng CRUD

Gamit lang ang Nest, makakagawa ka ng API na nagbibigay-daan sa iyong gumawa, magbasa, mag-update, at magtanggal ng entity. Ang solusyon na ito ay magiging flexible hangga't maaari, ngunit sa ilang mga kaso ito ay magiging kalabisan. Halimbawa, kung kailangan mong mabilis na lumikha ng isang prototype, maaari mong madalas na isakripisyo ang kakayahang umangkop para sa bilis ng pag-unlad. Maraming mga frameworks ang nagbibigay ng functionality para sa pagbuo ng CRUD sa pamamagitan ng paglalarawan ng data model ng isang partikular na entity. At ang Nest ay walang pagbubukod! Ang pag-andar na ito ay ibinibigay ng package @nestjsx/crud. Ang mga kakayahan nito ay lubhang kawili-wili:

  • madaling pag-install at pagsasaayos;
  • pagsasarili ng DBMS;
  • malakas na wika ng query na may kakayahang mag-filter, mag-paginate, mag-sort, mag-load ng mga relasyon at nested entity, caching, atbp.;
  • package para sa pagbuo ng mga kahilingan sa front-end;
  • madaling pag-override ng mga pamamaraan ng controller;
  • maliit na config;
  • suporta sa dokumentasyon ng swagger.

Ang pag-andar ay nahahati sa ilang mga pakete:

  • @nestjsx/crud - ang pangunahing pakete na ibinibigay ng dekorador Crud() para sa pagbuo ng ruta, pagsasaayos at pagpapatunay;
  • @nestjsx/crud-request β€” isang package na nagbibigay ng query builder/parser para gamitin sa frontend side;
  • @nestjsx/crud-typeorm β€” isang pakete para sa pagsasama sa TypeORM, na nagbibigay ng pangunahing serbisyo ng TypeOrmCrudService na may mga pamamaraan ng CRUD para sa pakikipagtulungan sa mga entity sa database.

Sa tutorial na ito kakailanganin namin ang mga pakete pugadjsx/crud at pugadjsx/crud-typeorm. Una, ilagay natin sila

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

Mga package class-transformer ΠΈ class-validator sa application na ito ay kinakailangan para sa isang deklaratibong paglalarawan ng mga panuntunan para sa pagbabago ng mga instance ng modelo at pagpapatunay ng mga papasok na kahilingan, ayon sa pagkakabanggit. Ang mga paketeng ito ay mula sa parehong may-akda, kaya magkatulad ang mga interface.

Direktang pagpapatupad ng CRUD

Kukuha kami ng isang listahan ng mga user bilang isang halimbawang modelo. Ang mga gumagamit ay magkakaroon ng mga sumusunod na field: id, username, displayName, email. id - field ng auto-incrementing, email ΠΈ username - natatanging mga patlang. Ito ay simple! Ang natitira na lang ay ipatupad ang aming ideya sa anyo ng isang Nest application.
Una kailangan mong lumikha ng isang module users, na magiging responsable para sa pakikipagtulungan sa mga user. Gamitin natin ang cli mula sa NestJS at isagawa ang command sa root directory ng ating proyekto nest g module users.

mga gumagamit ng nest g module

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)

Sa modyul na ito magdaragdag tayo ng folder ng entity, kung saan magkakaroon tayo ng mga modelo ng modyul na ito. Sa partikular, idagdag natin dito ang file na user.entity.ts na may paglalarawan ng modelo ng user:

user.entity.ts

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

Upang ang modelong ito ay "makita" ng aming aplikasyon, ito ay kinakailangan sa modyul UsersModule angkat TypeOrmModule sumusunod na nilalaman:

users.module.ts

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

Ibig sabihin, dito tayo nag-import TypeOrmModule, kung saan bilang isang parameter ng pamamaraan forFeature Nagsasaad kami ng listahan ng mga modelong nauugnay sa modyul na ito.

Ang natitira na lang ay lumikha ng kaukulang entity sa database. Ang mekanismo ng paglipat ay nagsisilbi para sa mga layuning ito. Upang lumikha ng paglipat batay sa mga pagbabago sa mga modelo, kailangan mong patakbuhin ang command npm run migration:generate -- CreateUserTable:

pamagat ng spoiler

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

Hindi namin kailangang isulat nang manu-mano ang paglipat, ang lahat ay nangyari sa mahiwagang. Hindi ba ito isang himala! Gayunpaman, hindi lang iyon. Tingnan natin ang ginawang migration file:

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

Tulad ng nakikita mo, hindi lamang ang paraan para sa pagsisimula ng paglipat ay awtomatikong nabuo, kundi pati na rin ang paraan para sa pagbabalik nito. Fantastic!
Ang natitira na lang ay ilunsad ang migration na ito. Ginagawa ito gamit ang sumusunod na utos:

npm run migration:run.

Iyon lang, ngayon ang mga pagbabago sa schema ay lumipat sa database.
Susunod, gagawa kami ng isang serbisyo na magiging responsable para sa pakikipagtulungan sa mga user at pagmamana nito mula sa TypeOrmCrudService. Ang repository ng entity ng interes ay dapat na maipasa sa parameter ng parent constructor, sa aming kaso User imbakan.

users.service.ts

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

Kakailanganin namin ang serbisyong ito sa controller users. Para gumawa ng controller, i-type ang console nest g controller users/controllers/users

mga user/controller/user ng nest g controller

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)

Buksan natin ang controller na ito at i-edit ito para magdagdag ng kaunting magic pugadjsx/crud. Kada klase UsersController Magdagdag tayo ng isang dekorador tulad nito:

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

Crud ay isang dekorador na nagdaragdag sa controller ng mga kinakailangang pamamaraan para sa pagtatrabaho sa modelo. Ang uri ng modelo ay ipinahiwatig sa field model.type mga pagsasaayos ng dekorador.
Ang ikalawang hakbang ay upang ipatupad ang interface CrudController<User>. Ang "Assembled" controller code ay ganito ang hitsura:

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

At lahat na! Sinusuportahan na ngayon ng controller ang buong hanay ng mga operasyon kasama ang modelo! Huwag maniwala sa akin? Subukan natin ang aming application sa aksyon!

Paggawa ng Query Script sa TestMace

Upang subukan ang aming serbisyo ay gagamit kami ng IDE upang gumana sa API TestMace. Bakit TestMace? Kung ikukumpara sa mga katulad na produkto, mayroon itong mga sumusunod na pakinabang:

  • makapangyarihang gawain na may mga variable. Sa ngayon, may ilang uri ng mga variable, na ang bawat isa ay gumaganap ng isang partikular na papel: mga built-in na variable, dynamic na variable, environment variable. Ang bawat variable ay nabibilang sa isang node na may suporta para sa mekanismo ng pamana;
  • Madaling gumawa ng mga script nang walang programming. Ito ay tatalakayin sa ibaba;
  • isang format na nababasa ng tao na nagbibigay-daan sa iyong i-save ang proyekto sa mga version control system;
  • autocompletion, syntax highlighting, variable value highlighting;
  • Suporta sa paglalarawan ng API na may kakayahang mag-import mula sa Swagger.

Simulan natin ang aming server gamit ang utos npm start at subukang i-access ang listahan ng mga gumagamit. Ang listahan ng mga user, batay sa configuration ng aming controller, ay maaaring makuha mula sa url localhost:3000/users. Gumawa tayo ng kahilingan sa url na ito.
Pagkatapos patakbuhin ang TestMace maaari mong makita ang isang interface tulad nito:

Mabilis na paggawa ng CRUD gamit ang nest, @nestjsx/crud at TestMace

Sa kaliwang itaas ay isang project tree na may root node proyekto. Subukan nating gawin ang unang kahilingan para makakuha ng listahan ng mga user. Para dito tayo ay lilikha RequestStep node Ginagawa ito sa menu ng konteksto ng Project node Magdagdag ng node -> RequestStep.

Mabilis na paggawa ng CRUD gamit ang nest, @nestjsx/crud at TestMace

Sa field ng URL, i-paste ang localhost:3000/users at patakbuhin ang kahilingan. Makakatanggap kami ng code 200 na may isang walang laman na hanay sa katawan ng pagtugon. Ito ay naiintindihan, hindi pa kami nagdaragdag ng sinuman.
Gumawa tayo ng script na magsasama ng mga sumusunod na hakbang:

  1. paglikha ng isang gumagamit;
  2. kahilingan para sa id ng bagong likhang user;
  3. pagtanggal ng user id na ginawa sa hakbang 1.

So, tara na. Para sa kaginhawahan, gumawa tayo ng isang node na tulad ng Polder. Mahalaga, ito ay isang folder lamang kung saan ise-save namin ang buong script. Para gumawa ng Folder node, piliin ang Project mula sa context menu ng node Magdagdag ng node -> Folder. Tawagan natin ang node check-create. Sa loob ng isang node check-create Gawin natin ang ating unang kahilingang gumawa ng user. Tawagan natin ang bagong likhang node lumikha-gumagamit. Iyon ay, sa sandaling ito ang hierarchy ng node ay magiging ganito:

Mabilis na paggawa ng CRUD gamit ang nest, @nestjsx/crud at TestMace

Pumunta tayo sa bukas na tab lumikha-gumagamit node. Ipasok natin ang mga sumusunod na parameter para sa kahilingan:

  • Uri ng kahilingan - POST
  • URL - localhost:3000/users
  • Body - JSON na may halaga {"email": "[email protected]", "displayName": "New user", "username": "user"}

Tuparin natin ang kahilingang ito. Sinasabi ng aming aplikasyon na ang talaan ay nilikha.

Mabilis na paggawa ng CRUD gamit ang nest, @nestjsx/crud at TestMace

Well, suriin natin ang katotohanang ito. Upang gumana gamit ang id ng nilikhang user sa mga susunod na hakbang, dapat na i-save ang parameter na ito. Ang mekanismo ay perpekto para dito. mga dynamic na variable. Gamitin natin ang ating halimbawa upang tingnan kung paano magtrabaho sa kanila. Sa na-parse na tab ng tugon, sa tabi ng id node sa menu ng konteksto, piliin ang item Italaga sa variable. Sa dialog box dapat mong itakda ang mga sumusunod na parameter:

  • Node β€” kung alin sa mga ninuno ang gagawa ng dynamic na variable. Pumili tayo check-create
  • Variable na pangalan β€” ang pangalan ng variable na ito. Tawagin natin userId.

Narito kung ano ang hitsura ng proseso ng paglikha ng isang dynamic na variable:

Mabilis na paggawa ng CRUD gamit ang nest, @nestjsx/crud at TestMace

Ngayon, sa tuwing isasagawa ang query na ito, maa-update ang halaga ng dynamic na variable. At dahil sinusuportahan ng mga dynamic na variable ang mekanismo ng hierarchical inheritance, variable userId ay makukuha sa mga inapo check-create node ng anumang antas ng nesting.
Ang variable na ito ay magiging kapaki-pakinabang sa amin sa susunod na kahilingan. Ibig sabihin, hihilingin namin ang bagong likhang user. Bilang isang anak ng isang node check-create gagawa kami ng kahilingan check-kung mayroon may parameter url katumbas localhost:3000/users/${$dynamicVar.userId}. Tingnan ang disenyo ${variable_name} ito ay nakakakuha ng halaga ng isang variable. kasi Mayroon kaming dynamic na variable, kaya para makuha ito kailangan mong i-access ang object $dynamicVar, ibig sabihin, ganap na pag-access sa isang dynamic na variable userId magiging ganito ang hitsura ${$dynamicVar.userId}. Isagawa natin ang kahilingan at siguraduhing tama ang hinihiling ng data.
Ang huling hakbang na natitira ay humiling ng pagtanggal. Kailangan namin ito hindi lamang upang suriin ang pagpapatakbo ng pagtanggal, kundi pati na rin, wika nga, upang linisin ang ating sarili sa database, dahil Ang mga field ng email at username ay natatangi. Kaya, sa check-create node gagawa kami ng hiling na tanggalin ang user na may mga sumusunod na parameter

  • Uri ng kahilingan - I-DELETE
  • URL - localhost:3000/users/${$dynamicVar.userId}

Ilunsad natin. Naghihintay kami. Nasisiyahan kami sa resulta)

Ngayon, maaari na nating patakbuhin ang buong script na ito anumang oras. Upang patakbuhin ang script kailangan mong pumili mula sa menu ng konteksto check-create item ng node Tumakbo.

Mabilis na paggawa ng CRUD gamit ang nest, @nestjsx/crud at TestMace

Ang mga node sa script ay isasagawa nang paisa-isa
Maaari mong i-save ang script na ito sa iyong proyekto sa pamamagitan ng pagpapatakbo File -> I-save ang proyekto.

Konklusyon

Ang lahat ng mga tampok ng mga tool na ginamit ay hindi magkasya sa format ng artikulong ito. Tulad ng para sa pangunahing salarin - ang pakete pugadjsx/crud - ang mga sumusunod na paksa ay nananatiling walang takip:

  • pasadyang pagpapatunay at pagbabago ng mga modelo;
  • malakas na wika ng query at ang maginhawang paggamit nito sa harap;
  • muling pagtukoy at pagdaragdag ng mga bagong pamamaraan sa mga crud controller;
  • suporta sa pagmamayabang;
  • pamamahala ng caching.

Gayunpaman, kahit na kung ano ang inilarawan sa artikulo ay sapat na upang maunawaan na kahit na ang tulad ng isang enterprise framework bilang NestJS ay may mga tool para sa mabilis na application prototyping. At tulad ng isang cool na IDE TestMace nagbibigay-daan sa iyo upang mapanatili ang isang naibigay na bilis.

Source code para sa artikulong ito, kasama ang proyekto TestMace, magagamit sa repositoryo https://github.com/TestMace/nest-rest. Upang magbukas ng isang proyekto TestMace gawin mo lang sa app File -> Buksan ang proyekto.

Pinagmulan: www.habr.com

Magdagdag ng komento