рдлреБрд▓-рд╕реНрдЯреИрдХ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдРрдкреНрд╕

рдирдорд╕реНрдХрд╛рд░, рд╣реЗрдмреНрд░! рдореИрдВ рдЖрдкрдХреЛ рдПрдирд╛ рд░рд┐рдмреЗрд░реЛ рджреНрд╡рд╛рд░рд╛ рд▓реЗрдЦ "рдлреБрд▓-рд╕реНрдЯреИрдХ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдРрдкреНрд╕ - рднрд╛рдЧ 1: рд╡рд┐рдХрд╛рд╕рд╢реАрд▓ рдмреИрдХрдПрдВрдб рдПрдкреАрдЖрдИ рд╡рд┐рде рдиреЗрд╕реНрдЯ.рдЬреЗрдПрд╕" рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдкреЗрд╢ рдХрд░рддрд╛ рд╣реВрдВред


рднрд╛рдЧ 1: Nest.JS рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рд░реНрд╡рд░ API рдХрд╛ рд╡рд┐рдХрд╛рд╕ рдХрд░рдирд╛


TL; DR: рдпрд╣ рдХреИрд╕реЗ рдХреЛрдгреАрдп рдФрд░ Nest.JS рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╡реЗрдм рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓реЗрдЦреЛрдВ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рд╣реИред рдкрд╣рд▓реЗ рднрд╛рдЧ рдореЗрдВ, рд╣рдо Nest.JS рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╕рд░реНрд╡рд░ рдПрдкреАрдЖрдИ рд▓рд┐рдЦреЗрдВрдЧреЗред рдЗрд╕ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХрд╛ рджреВрд╕рд░рд╛ рд╣рд┐рд╕реНрд╕рд╛ рдХреЛрдгреАрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдлреНрд░рдВрдЯ-рдПрдВрдб рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд рд╣реИред рдЖрдк рдЗрд╕ GitHub рднрдВрдбрд╛рд░ рдореЗрдВ рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рд╡рд┐рдХрд╕рд┐рдд рдЕрдВрддрд┐рдо рдХреЛрдб рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ ред


Nest.Js рдФрд░ рдХреНрдпреЛрдВ рдХреЛрдгреАрдп рд╣реИ?


Nest.js Node.js рд╡реЗрдм рд╕рд░реНрд╡рд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдПрдХ рд░реВрдкрд░реЗрдЦрд╛ рд╣реИред


рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╡рд┐рд╢реЗрд╖рддрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдРрд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдХреЛрдИ рдЕрдиреНрдп рдврд╛рдВрдЪрд╛ рд╣рд▓ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ: рдиреЛрдб.рдЬреЗрдПрд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рд╕рдВрд░рдЪрдирд╛ред рдпрджрд┐ рдЖрдкрдиреЗ рдХрднреА рднреА рдиреЛрдб.рдЬреЗрдПрд╕ рдХреЗ рддрд╣рдд рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЖрдк рдПрдХ рдореЙрдбреНрдпреВрд▓ рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рдХреБрдЫ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдорд┐рдбрд╡реЗрд╡реЗрдпрд░ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рд╕реЗ рд╕рддреНрдпрд╛рдкрди рддрдХ рд╕рдм рдХреБрдЫ рдХрд░ рд╕рдХрддрд╛ рд╣реИ), рдЬреЛ рдЕрдВрдд рдореЗрдВ, рдПрдХ рдЕрд╕рдорд░реНрдерд┐рдд "рдЧрдбрд╝рдмрдбрд╝" рдХрд╛ рдХрд╛рд░рдг рдмрди рд╕рдХрддрд╛ рд╣реИред ред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдиреАрдЪреЗ рджреЗрдЦреЗрдВрдЧреЗ, nest.js рд╡рд┐рднрд┐рдиреНрди рдореБрджреНрджреЛрдВ рдХреЗ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮ рд╡рд░реНрдЧ рдкреНрд░рджрд╛рди рдХрд░рдХреЗ рд╣рдорд╛рд░реА рд╕рд╣рд╛рдпрддрд╛ рдХрд░реЗрдВрдЧреЗред


Nest.js рдХреЛрдгреАрдп рд╕реЗ рдХрд╛рдлреА рдкреНрд░реЗрд░рд┐рдд рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рджреЛрдиреЛрдВ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдЖрдкрдХреЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рдХреБрдЫ рд╣рд┐рд╕реНрд╕реЛрдВ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдпрд╛ рдЙрдиреНрд╣реЗрдВ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдЧрд╛рд░реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рджреЛрдиреЛрдВ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдЗрди рдЧрд╛рд░реНрдбреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ CanActivate рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рдзреНрдпрд╛рди рд░рдЦрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рдХреБрдЫ рд╕рдорд╛рди рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЗ рдмрд╛рд╡рдЬреВрдж, рджреЛрдиреЛрдВ рд╕рдВрд░рдЪрдирд╛рдПрдВ рдПрдХ-рджреВрд╕рд░реЗ рд╕реЗ рд╕реНрд╡рддрдВрддреНрд░ рд╣реИрдВред рдпрд╣реА рд╣реИ, рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рдЕрдкрдиреЗ рдлреНрд░рдВрдЯ-рдПрдВрдб рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрд╡рддрдВрддреНрд░ рдПрдкреАрдЖрдИ рдмрдирд╛рдПрдВрдЧреЗ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рдврд╛рдВрдЪреЗ (рд░рд┐рдПрдХреНрдЯ, рд╡реАрдпреВ.рдЬреЗрдПрд╕ рдФрд░ рдЗрд╕реА рддрд░рд╣) рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


рдСрдирд▓рд╛рдЗрди рдСрд░реНрдбрд░ рдХреЗ рд▓рд┐рдП рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди


рдЗрд╕ рдЧрд╛рдЗрдб рдореЗрдВ, рд╣рдо рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдПрдВрдЧреЗ рдЬрд┐рд╕рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд┐рд╕реА рд░реЗрд╕реНрддрд░рд╛рдВ рдореЗрдВ рдСрд░реНрдбрд░ рджреЗ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдЗрд╕ рддрд░реНрдХ рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдЧрд╛:


  • рдХреЛрдИ рднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдореЗрдиреВ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реИ;
  • рдХреЗрд╡рд▓ рдПрдХ рдЕрдзрд┐рдХреГрдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЯреЛрдХрд░реА рдореЗрдВ рд╕рд╛рдорд╛рди рдЬреЛрдбрд╝ рд╕рдХрддрд╛ рд╣реИ (рдПрдХ рдСрд░реНрдбрд░ рдХрд░реЗрдВ)
  • рдХреЗрд╡рд▓ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдХ рдирдП рдореЗрдиреВ рдЖрдЗрдЯрдо рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред

рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдмрд╛рд╣рд░реА рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ рдФрд░ рд╣рдорд╛рд░реА рд╕реНрдЯреЛрд░ рдЯреЛрдХрд░реА рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред


Nest.js рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рдлрд╝рд╛рдЗрд▓ рд╕рдВрд░рдЪрдирд╛ рдмрдирд╛рдирд╛


Nest.js рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ Node.js (v.8.9.x рдпрд╛ рдЙрдЪреНрдЪрддрд░) рдФрд░ NPM рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд╡реЗрдмрд╕рд╛рдЗрдЯ рд╕реЗ рдЖрдкрдХреЗ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд▓рд┐рдП Node.js рдбрд╛рдЙрдирд▓реЛрдб рдФрд░ рдЗрдВрд╕реНрдЯреЙрд▓ рдХрд░реЗрдВ (NPM рд╢рд╛рдорд┐рд▓ рд╣реИ)ред рдЬрдм рд╕рдм рдХреБрдЫ рд╕реНрдерд╛рдкрд┐рдд рд╣реЛ рдЬрд╛рдП, рддреЛ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ:


node -v # v12.11.1 npm -v # 6.11.3 

Nest.js рдХреЗ рд╕рд╛рде рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рдиреЗ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рддрд░реАрдХреЗ рд╣реИрдВ; рд╡реЗ рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ рдкрд╛рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдо nest-cli рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдЗрд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ:


npm i -g @nestjs/cli


рдЕрдЧрд▓рд╛, рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдХрдорд╛рдВрдб рдХреЗ рд╕рд╛рде рд╣рдорд╛рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рдПрдВ:


nest new nest-restaurant-api


рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ, рдШреЛрдВрд╕рд▓рд╛ рд╣рдореЗрдВ рдПрдХ рдкреИрдХреЗрдЬ рдореИрдиреЗрдЬрд░ рдЪреБрдирдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣реЗрдЧрд╛: npm рдпрд╛ yarn


рдпрджрд┐ рд╕рдм рдХреБрдЫ рдареАрдХ рд░рд╣рд╛, рддреЛ nest рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлрд╝рд╛рдЗрд▓ рд╕рдВрд░рдЪрдирд╛ рдмрдирд╛рдПрдЧрд╛:


 nest-restaurant-api тФЬтФАтФА src тФВ тФЬтФАтФА app.controller.spec.ts тФВ тФЬтФАтФА app.controller.ts тФВ тФЬтФАтФА app.module.ts тФВ тФЬтФАтФА app.service.ts тФВ тФФтФАтФА main.ts тФЬтФАтФА test тФВ тФЬтФАтФА app.e2e-spec.ts тФВ тФФтФАтФА jest-e2e.json тФЬтФАтФА .gitignore тФЬтФАтФА .prettierrc тФЬтФАтФА nest-cli.json тФЬтФАтФА package.json тФЬтФАтФА package-lock.json тФЬтФАтФА README.md тФЬтФАтФА tsconfig.build.json тФЬтФАтФА tsconfig.json тФФтФАтФА tslint.json 

рдмрдирд╛рдИ рдЧрдИ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдкрд░ рдЬрд╛рдПрдВ рдФрд░ рд╡рд┐рдХрд╛рд╕ рд╕рд░реНрд╡рд░ рд╢реБрд░реВ рдХрд░реЗрдВ:


  #    cd nest-restaurant-api #   npm run start:dev 

рдПрдХ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдЦреЛрд▓реЗрдВ рдФрд░ http://localhost:3000 ред рд╕реНрдХреНрд░реАрди рдкрд░ рд╣рдо рджреЗрдЦреЗрдВрдЧреЗ:


рдЗрд╕ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреЗ рднрд╛рдЧ рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдо рдЕрдкрдиреЗ рдПрдкреАрдЖрдИ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ (рд╣рд╛рд▓рд╛рдБрдХрд┐ рдЖрдкрдХреЛ рдХрд┐рд╕реА рднреА рддреИрдпрд╛рд░-рд╕реЗ-рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП)ред рдЗрд╕ рддрд░рд╣ рдЖрдк test рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЛ рд╕рд╛рдлрд╝ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ src/app.controller.spec.ts (рдЬреЛ рдкрд░реАрдХреНрд╖рдг рдПрдХ рд╣реИ) рдХреЛ рд╣рдЯрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╣рдорд╛рд░реЗ рд╕реНрд░реЛрдд рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдирд┐рдореНрди рдлрд╝рд╛рдЗрд▓реЗрдВ рд╣реИрдВ:


  • src/app.controller.ts рдФрд░ src/app.module.ts : рдпреЗ рдлрд╛рдЗрд▓реЗрдВ / рдорд╛рд░реНрдЧ рдХреЗ рд╕рд╛рде Hello world рд╕рдВрджреЗрд╢ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИрдВред рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрд┐рдВрджреБ рдЗрд╕ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд▓рд┐рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рдЙрдиреНрд╣реЗрдВ рд╣рдЯрд╛рддреЗ рд╣реИрдВред рдЬрд▓реНрдж рд╣реА рдЖрдк рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдЬрд╛рдиреЗрдВрдЧреЗ рдХрд┐ рдирд┐рдпрдВрддреНрд░рдХ рдФрд░ рд╕реЗрд╡рд╛рдПрдВ рдХреНрдпрд╛ рд╣реИрдВ ред
  • src/app.module.ts : рдореЗрдВ рдкреНрд░рдХрд╛рд░ рдореЙрдбреНрдпреВрд▓ рдХреЗ рдПрдХ рд╡рд░реНрдЧ рдХрд╛ рд╡рд┐рд╡рд░рдг рд╢рд╛рдорд┐рд▓ рд╣реИ, рдЬреЛ рдХрд┐ рдШреЛрдВрд╕рд▓реЗ рдХреЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдФрд░ рдкреНрд░рджрд╛рддрд╛рдУрдВ рдХреЗ рдЖрдпрд╛рдд, рдирд┐рд░реНрдпрд╛рдд рдХреЛ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдХрдо рд╕реЗ рдХрдо рдПрдХ рдореЙрдбреНрдпреВрд▓ рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди ( рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ рдЕрдзрд┐рдХ) рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдореЙрдбреНрдпреВрд▓ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдорд╛рд░рд╛ рдЖрд╡реЗрджрди рдХреЗрд╡рд▓ рдПрдХ рдореЙрдбреНрдпреВрд▓ рд╣реЛрдЧрд╛ред
  • src/main.ts : рдпрд╣ рд╕рд░реНрд╡рд░ рдХреЛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдлрд╛рдЗрд▓ рд╣реИред

рдиреЛрдЯ: src/app.controller.ts рдФрд░ src/app.module.ts рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рдмрд╛рдж src/app.module.ts рдЖрдк рдЕрдкрдирд╛ рдЖрд╡реЗрджрди рд╢реБрд░реВ рдирд╣реАрдВ рдХрд░ рдкрд╛рдПрдВрдЧреЗред рдЪрд┐рдВрддрд╛ рди рдХрд░реЗрдВ, рд╣рдо рдЗрд╕реЗ рдЬрд▓реНрдж рд╣реА рдареАрдХ рдХрд░ рджреЗрдВрдЧреЗред

рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБ (рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ) рдмрдирд╛рдПрдВ



рд╣рдорд╛рд░рд╛ рдПрдкреАрдЖрдИ /items рдорд╛рд░реНрдЧ рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реЛрдЧрд╛ред рдЗрд╕ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрд┐рдВрджреБ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдХ рдореЗрдиреВ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рддреЗ рд╣реИрдВред рдЪрд▓реЛ рдЗрд╕реЗ рдмрдирд╛рддреЗ рд╣реИрдВред


рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, src рдЕрдВрджрд░ items рдирд╛рдордХ рдПрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдмрдирд╛рдПрдВред /items рд░реВрдЯ рд╕реЗ рдЬреБрдбрд╝реА рд╕рднреА рдлрд╛рдЗрд▓реЗрдВ рдЗрд╕ рдирдИ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХреА рдЬрд╛рдПрдВрдЧреАред


рдирд┐рдпрдВрддреНрд░рдХ рдмрдирд╛рдирд╛


nest.js , рдХрдИ рдЕрдиреНрдп рд░реВрдкрд░реЗрдЦрд╛рдУрдВ рдХреА рддрд░рд╣, рдирд┐рдпрдВрддреНрд░рдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╡рд╛рд▓реЗ рдорд╛рдирдЪрд┐рддреНрд░рдг рдорд╛рд░реНрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИрдВред nest.js рдореЗрдВ рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП nest.js рдбреЗрдХреЛрд░реЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд░реЗрдВ: @Controller(${ENDPOINT}) ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╡рд┐рднрд┐рдиреНрди HTTP рд╡рд┐рдзрд┐рдпреЛрдВ, рдЬреИрд╕реЗ GET рдФрд░ POST , рдХреЛ рдореИрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдЬреНрдЬрд╛рдХрд╛рд░ @Get , @Post , @Delete , рдЖрджрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдореЗрдВ рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рд░реЗрд╕реНрддрд░рд╛рдВ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╡реНрдпрдВрдЬрди рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдФрд░ рдЬреЛ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдХ рдореЗрдиреВ рдХреА рд╕рд╛рдордЧреНрд░реА рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдЖрдЗрдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд╛рдордЧреНрд░рд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде src/items рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ items.controller.tc рдирд╛рдордХ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ:


  import { Get, Post, Controller } from '@nestjs/common'; @Controller('items') export class ItemsController { @Get() async findAll(): Promise<string[]> { return ['Pizza', 'Coke']; } @Post() async create() { return 'Not yet implemented'; } } 

рд╣рдорд╛рд░реЗ рдирдП рдирд┐рдпрдВрддреНрд░рдХ рдХреЛ рд╣рдорд╛рд░реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдЙрдкрд▓рдмреНрдз рдХрд░рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕реЗ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдкрдВрдЬреАрдХреГрдд рдХрд░реЗрдВ:


  import { Module } from '@nestjs/common'; import { ItemsController } from './items/items.controller'; @Module({ imports: [], controllers: [ItemsController], providers: [], }) export class AppModule {} 

рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЛ рд▓реЙрдиреНрдЪ рдХрд░реЗрдВ: npm run start:dev рдФрд░ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЦреЛрд▓реЗрдВ http: // localhost: 3000 / items , рдЕрдЧрд░ рдЖрдкрдиреЗ рд╕рдм рдХреБрдЫ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рд╣рдорд╛рд░реЗ рдЕрдиреБрд░реЛрдз рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдП: ['Pizza', 'Coke'] ред


рдЕрдиреБрд╡рд╛рджрдХ рдХрд╛ рдиреЛрдЯ: рдирдП рдирд┐рдпрдВрддреНрд░рдХ, рд╕рд╛рде рд╣реА nest.js рдЕрдиреНрдп рддрддреНрд╡реЛрдВ рдХреЛ nest.js рдХреЗ рд▓рд┐рдПред nest.js : рд╕реЗрд╡рд╛рдПрдВ, рдкреНрд░рджрд╛рддрд╛, рдЖрджрд┐, рдпрд╣ nest-cli рд╕реЗ nest generate рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдирд┐рдпрдВрддреНрд░рдХ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк nest generate controller items рдХрдорд╛рдВрдб nest generate controller items рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдШреЛрдВрд╕рд▓рд╛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд╛рдордЧреНрд░реА рдХреЗ src/items/items.controller.tc src/items/items.controller.spec.tc рдФрд░ src/items/items.controller.tc :


  import { Get, Post, Controller } from '@nestjs/common'; @Controller('items') export class ItemsController {} 

рдФрд░ app.molule.tc рдореЗрдВ рдЗрд╕реЗ рдкрдВрдЬреАрдХреГрдд рдХрд░реЗрдВ


рдПрдХ рд╕реЗрд╡рд╛ рдХреЛ рдЬреЛрдбрд╝рдирд╛


рдЕрдм, рдЬрдм /items рдПрдХреНрд╕реЗрд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдорд╛рд░рд╛ рдЖрд╡реЗрджрди рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реА рд╕рд░рдгреА рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдо рдмрджрд▓ рдирд╣реАрдВ рд╕рдХрддреЗ рд╣реИрдВред рдбреЗрдЯрд╛ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдирд╛ рдФрд░ рд╕рд╣реЗрдЬрдирд╛ рдирд┐рдпрдВрддреНрд░рдХ рдХрд╛ рд╡реНрдпрд╡рд╕рд╛рдп рдирд╣реАрдВ рд╣реИ, рдЗрд╕ рдЙрджреНрджреЗрд╢реНрдп рдХреЗ рд▓рд┐рдП рд╕реЗрд╡рд╛рдУрдВ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп n.js рд╣реИ
рдШреЛрдВрд╕рд▓реЗ рдореЗрдВ рд╕реЗрд╡рд╛рдПрдБ @Injectable
рдбреЗрдХреЛрд░реЗрдЯрд░ рдХрд╛ рдирд╛рдо рд╕реНрд╡рдпрдВ рдХреЗ рд▓рд┐рдП рдмреЛрд▓рддрд╛ рд╣реИ, рдЗрд╕ рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЛ рдХрдХреНрд╖рд╛ рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рд╕реЗ рдпрд╣ рдЕрдиреНрдп рдШрдЯрдХреЛрдВ рдЬреИрд╕реЗ рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдореЗрдВ рдЗрдВрдЬреЗрдХреНрдЯреЗрдмрд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
рдЪрд▓реЛ рд╣рдорд╛рд░реА рд╕реЗрд╡рд╛ рдмрдирд╛рдПрдБред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде items.service.ts рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ items.service.ts рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ:


  import { Injectable } from '@nestjs/common'; @Injectable() export class ItemsService { private readonly items: string[] = ['Pizza', 'Coke']; findAll(): string[] { return this.items; } create(item: string) { this.items.push(item); } } 

рдФрд░ рд╣рдорд╛рд░реА рд╕реЗрд╡рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП items.controller.ts рдХрдВрдЯреНрд░реЛрд▓рд░ ( items.controller.ts рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред items.controller.ts ) items.controller.ts :


  import { Get, Post, Body, Controller } from '@nestjs/common'; import { ItemsService } from './items.service'; @Controller('items') export class ItemsController { constructor(private readonly itemsService: ItemsService) {} @Get() async findAll(): Promise<string[]> { return this.itemsService.findAll(); } @Post() async create(@Body() item: string) { this.itemsService.create(item); } } 

рдирд┐рдпрдВрддреНрд░рдХ рдХреЗ рдирдП рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ, рд╣рдордиреЗ рд╡рд┐рдзрд┐ рд╡рд┐рдзрд┐ рддрд░реНрдХ create рд▓рд┐рдП @Body рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ред рдпрд╣ рддрд░реНрдХ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ req.body ['item'] рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд╛рд╕ рдХрд┐рдП рдЧрдП рдбреЗрдЯрд╛ рдХреЛ рддрд░реНрдХ рд╕реЗ (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, item ) рдореЗрдВ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдорд┐рд▓рд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдорд╛рд░реЗ рдирд┐рдпрдВрддреНрд░рдХ рдХреЛ ItemsService рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред ItemsService рдХреЛ ItemsService рд░реВрдк рдореЗрдВ рдШреЛрд╖рд┐рдд ItemsService private readonly рддреМрд░ рдкрд░ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЛ ItemsService рдФрд░ рдХреЗрд╡рд▓ рдХрдХреНрд╖рд╛ рдХреЗ рдЕрдВрджрд░ рджреГрд╢реНрдпрдорд╛рди рдмрдирд╛рддрд╛ рд╣реИред
рдФрд░ app.module.ts рдореЗрдВ рд╣рдорд╛рд░реА рд╕реЗрд╡рд╛ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рдирд╛ рди рднреВрд▓реЗрдВ:


  import { Module } from '@nestjs/common'; import { ItemsController } from './items/items.controller'; import { ItemsService } from './items/items.service'; @Module({ imports: [], controllers: [ItemsController], providers: [ItemsService], }) export class AppModule {} 

рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рдмрд╛рдж, рдЖрдЗрдП рдореЗрдиреВ рдореЗрдВ HTTP POST рдЕрдиреБрд░реЛрдз рднреЗрдЬреЗрдВ:


  curl -X POST -H 'content-type: application/json' -d '{"item": "Salad"}' localhost:3000/items 

рдлрд┐рд░ рд╣рдо рдЬрд╛рдВрдЪреЗрдВрдЧреЗ рдХрд┐ рдХреНрдпрд╛ GET рдЕрдиреБрд░реЛрдз (рдпрд╛ http: // localhost: 3000 / рдПрдХ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЖрдЗрдЯрдо ) рдХрд░рдХреЗ рд╣рдорд╛рд░реЗ рдореЗрдиреВ рдкрд░ рдирдП рд╡реНрдпрдВрдЬрди рджрд┐рдЦрд╛рдИ рджрд┐рдП рд╣реИрдВ рдпрд╛ рдирд╣реАрдВ


  curl localhost:3000/items 

рд╢реЙрдкрд┐рдВрдЧ рдХрд╛рд░реНрдЯ рд░реВрдЯ рдмрдирд╛рдирд╛


рдЕрдм рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣рдорд╛рд░реЗ рдПрдкреАрдЖрдИ рдХреЗ рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБ /items рдкрд╣рд▓рд╛ рд╕рдВрд╕реНрдХрд░рдг рд╣реИ, рддреЛ рдЪрд▓реЛ рд╢реЙрдкрд┐рдВрдЧ рдХрд╛рд░реНрдЯ рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдмрдирд╛рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкрд╣рд▓реЗ рд╕реЗ рдирд┐рд░реНрдорд┐рдд рдПрдкреАрдЖрдИ рд╕реЗ рдмрд╣реБрдд рдЕрд▓рдЧ рдирд╣реАрдВ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдореИрдиреБрдЕрд▓ рдХреЛ рдЕрд╡реНрдпрд╡рд╕реНрдерд┐рдд рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдШрдЯрдХ рдмрдирд╛рдПрдВрдЧреЗ рдЬреЛ рдПрдХреНрд╕реЗрд╕ рдХрд░рддреЗ рд╕рдордп рдУрдХреЗ рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИред


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, ./src/shopping-cart/ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ ./src/shopping-cart/ shoping-cart.controller.ts :


  import { Post, Controller } from '@nestjs/common'; @Controller('shopping-cart') export class ShoppingCartController { @Post() async addItem() { return 'This is a fake service :D'; } } 

рдЗрд╕ рдХрдВрдЯреНрд░реЛрд▓рд░ рдХреЛ рд╣рдорд╛рд░реЗ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдкрдВрдЬреАрдХреГрдд рдХрд░реЗрдВ ( app.module.ts ):


  import { Module } from '@nestjs/common'; import { ItemsController } from './items/items.controller'; import { ShoppingCartController } from './shopping-cart/shopping-cart.controller'; import { ItemsService } from './items/items.service'; @Module({ imports: [], controllers: [ItemsController, ShoppingCartController], providers: [ItemsService], }) export class AppModule {} 

рдЗрд╕ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрд┐рдВрджреБ рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрди рдХрдорд╛рдВрдб рдХреЛ рдЪрд▓рд╛рдПрдВ, рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдХрд┐ рдЖрд╡реЗрджрди рдЪрд▓ рд░рд╣рд╛ рд╣реИ:


  curl -X POST localhost:3000/shopping-cart 

рдЖрдЗрдЯрдо рдХреЗ рд▓рд┐рдП рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЬреЛрдбрд╝рдирд╛


рд╡рд╛рдкрд╕ рд╣рдорд╛рд░реЗ items рд╕реЗрд╡рд╛ рдХреЗ рд▓рд┐рдПред рдЕрдм рд╣рдо рдХреЗрд╡рд▓ рдкрдХрд╡рд╛рди рдХреЗ рдирд╛рдо рдХреЛ рдмрдЪрд╛рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИ, рдФрд░, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рд╣рдо рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкрдХрд╡рд╛рди рдХреА рд▓рд╛рдЧрдд) рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕ рдмрд╛рдд рд╕реЗ рд╕рд╣рдордд рд╣реЛрдВрдЧреЗ рдХрд┐ рдЗрд╕ рдбреЗрдЯрд╛ рдХреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреА рдПрдХ рд╕рд░рдгреА рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдирд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рд╣реИ?
рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╡рд╕реНрддреБрдУрдВ рдХреА рдПрдХ рд╕рд░рдгреА рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдХреИрд╕реЗ рдмрдЪрд╛рдпрд╛ рдЬрд╛рдП? рдпрд╣рд╛рдВ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╣рдорд╛рд░реА рдорджрдж рдХрд░реЗрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ рд╣рдо items рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВред src/items рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ item.interface.ts рдирд╛рдордХ рдПрдХ рдирдИ рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ:


  export interface Items { readonly name: string; readonly price: number; } 

рдЗрд╕рдХреЗ рдмрд╛рдж items.service.ts рдлрд╝рд╛рдЗрд▓


 import { Injectable } from '@nestjs/common'; import { Item } from './item.interface'; @Injectable() export class ItemsService { private readonly items: Item[] = []; findAll(): Item[] { return this.items; } create(item: Item) { this.items.push(item); } } 

рдФрд░ items.controller.ts рдореЗрдВ рднреАред items.controller.ts ред items.controller.ts :


 import { Get, Post, Body, Controller } from '@nestjs/common'; import { ItemsService } from './items.service'; import { Item } from './item.interface'; @Controller('items') export class ItemsController { constructor(private readonly itemsService: ItemsService) {} @Get() async findAll(): Promise<Item[]> { return this.itemsService.findAll(); } @Post() async create(@Body() item: Item) { this.itemsService.create(item); } } 

Nest.js рдореЗрдВ рдЗрдирдкреБрдЯ рдХрд╛ рд╕рддреНрдпрд╛рдкрди


рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ рд╣рдордиреЗ item рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА рд╕рдВрд░рдЪрдирд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреА рд╣реИ, рдЕрдЧрд░ рд╣рдо рдПрдХ рдЕрдорд╛рдиреНрдп рдкреЛрд╕реНрдЯ рдЕрдиреБрд░реЛрдз (рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХрд╛ рдбреЗрдЯрд╛ рдирд╣реАрдВ) рднреЗрдЬрддреЗ рд╣реИрдВ, рддреЛ рд╣рдорд╛рд░рд╛ рдЖрд╡реЗрджрди рдПрдХ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рд▓реМрдЯрд╛рдПрдЧрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рддрд░рд╣ рдХреЗ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП:


  curl -H 'Content-Type: application/json' -d '{ "name": 3, "price": "any" }' http://localhost:3000/items 

рд╕рд░реНрд╡рд░ рдХреЛ 400 (рдЦрд░рд╛рдм рдЕрдиреБрд░реЛрдз) рдХреА рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рдЬрд╡рд╛рдм рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╣рдорд╛рд░рд╛ рдЖрд╡реЗрджрди 200 (рдУрдХреЗ) рдХреА рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рдЬрд╡рд╛рдм рджреЗрдЧрд╛ред


рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдбреАрдЯреАрдУ (рдбреЗрдЯрд╛ рдЯреНрд░рд╛рдВрд╕рдлрд░ рдСрдмреНрдЬреЗрдХреНрдЯ) рдФрд░ рдПрдХ рдкрд╛рдЗрдк рдШрдЯрдХ (рдЪреИрдирд▓) рдмрдирд╛рдПрдВред


рдбреАрдЯреАрдУ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реИ рдЬреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдбреЗрдЯрд╛ рдХреЛ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рдмреАрдЪ рдХреИрд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдо DTO рдХреЛ src/items/create-item.dto.ts рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд░рддреЗ рд╣реИрдВ:


  import { IsString, IsInt } from 'class-validator'; export class CreateItemDto { @IsString() readonly name: string; @IsInt() readonly price: number; } 

Nest.js рдореЗрдВ рдкрд╛рдЗрдк рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдШрдЯрдХ рд╣реИрдВред рд╣рдорд╛рд░реЗ рдПрдкреАрдЖрдИ рдХреЗ рд▓рд┐рдП, рдПрдХ рдЪреИрдирд▓ рдмрдирд╛рдПрдВ рдЬрд┐рд╕рдореЗрдВ рдпрд╣ рдЬрд╛рдВрдЪреЗ рдХрд┐ рд╡рд┐рдзрд┐ рдХреЛ рднреЗрдЬрд╛ рдЧрдпрд╛ рдбреЗрдЯрд╛ рдбреАрдЯреАрдУ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред рдПрдХ рдЪреИрдирд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд┐рднрд┐рдиреНрди рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдлрд╝рд╛рдЗрд▓ validation.pipe.ts рд╕рд╛рде src/common/ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдмрдирд╛рдПрдВред


  import { ArgumentMetadata, BadRequestException, Injectable, PipeTransform, } from '@nestjs/common'; import { validate } from 'class-validator'; import { plainToClass } from 'class-transformer'; @Injectable() export class ValidationPipe implements PipeTransform<any> { async transform(value, metadata: ArgumentMetadata) { const { metatype } = metadata; if (!metatype || !this.toValidate(metatype)) { return value; } const object = plainToClass(metatype, value); const errors = await validate(object); if (errors.length > 0) { throw new BadRequestException('Validation failed'); } return value; } private toValidate(metatype): boolean { const types = [String, Boolean, Number, Array, Object]; return !types.find(type => metatype === type); } } 

рдиреЛрдЯ: рд╣рдореЗрдВ рджреЛ рдореЙрдбреНрдпреВрд▓ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: class-validator рдФрд░ class-transformer ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдХрдВрд╕реЛрд▓ рдореЗрдВ npm install class-validator class-transformer рдФрд░ рд╕рд░реНрд╡рд░ рдХреЛ рдкреБрдирд░рд╛рд░рдВрдн рдХрд░реЗрдВред

рд╣рдорд╛рд░реЗ рдирдП рдкрд╛рдЗрдк рдФрд░ DTO рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП items.controller.ts рдХреЛ items.controller.ts :


  import { Get, Post, Body, Controller, UsePipes } from '@nestjs/common'; import { CreateItemDto } from './create-item.dto'; import { ItemsService } from './items.service'; import { Item } from './item.interface'; import { ValidationPipe } from '../common/validation.pipe'; @Controller('items') export class ItemsController { constructor(private readonly itemsService: ItemsService) {} @Get() async findAll(): Promise<Item[]> { return this.itemsService.findAll(); } @Post() @UsePipes(new ValidationPipe()) async create(@Body() createItemDto: CreateItemDto) { this.itemsService.create(createItemDto); } } 

рдЖрдЗрдП рд╣рдорд╛рд░реЗ рдХреЛрдб рдХреЛ рдлрд┐рд░ рд╕реЗ рдЬрд╛рдВрдЪреЗрдВ, рдЕрдм рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ /items рдХреЗрд╡рд▓ рдбреЗрдЯрд╛ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдпрджрд┐ рд╡реЗ рдбреАрдЯреАрдУ рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:


  curl -H 'Content-Type: application/json' -d '{ "name": "Salad", "price": 3 }' http://localhost:3000/items 

рдЕрдорд╛рдиреНрдп рдбреЗрдЯрд╛ рдореЗрдВ рдЪрд┐рдкрдХрд╛рдПрдБ (рдбреЗрдЯрд╛ рдЬреЛ ValidationPipe рдореЗрдВ рд╕рддреНрдпрд╛рдкрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ), рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рд╣рдореЗрдВ рдЙрддреНрддрд░ рдорд┐рд▓рддрд╛ рд╣реИ:


  {"statusCode":400,"error":"Bad Request","message":"Validation failed"} 

рдорд┐рдбрд┐рд▓рд╡реЗрдпрд░ рдмрдирд╛рдирд╛

Auth0 рдХреНрд╡рд┐рдХ рд╕реНрдЯрд╛рд░реНрдЯ рдЧрд╛рдЗрдб рдкреЗрдЬ рдХреЗ рдЕрдиреБрд╕рд╛рд░ , Auth0 рджреНрд╡рд╛рд░рд╛ рдЬрд╛рд░реА JWT рдЯреЛрдХрди рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд╢рдВрд╕рд┐рдд рддрд░реАрдХрд╛ express-jwt рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИред рдпрд╣ рдорд┐рдбрд┐рд▓рд╡реЗрдпрд░ рдХрд╛рдо рдХрд╛ рдПрдХ рдмрдбрд╝рд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рддрд╛ рд╣реИред


рдЖрдЗрдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдХреЗ рд╕рд╛рде src / common рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЗ рдЕрдВрджрд░ рдПрдХ authentication.middleware.ts рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдпреЗрдВ:


  import { NestMiddleware } from '@nestjs/common'; import * as jwt from 'express-jwt'; import { expressJwtSecret } from 'jwks-rsa'; export class AuthenticationMiddleware implements NestMiddleware { use(req, res, next) { jwt({ secret: expressJwtSecret({ cache: true, rateLimit: true, jwksRequestsPerMinute: 5, jwksUri: 'https://${DOMAIN}/.well-known/jwks.json', }), audience: 'http://localhost:3000', issuer: 'https://${DOMAIN}/', algorithm: 'RS256', })(req, res, err => { if (err) { const status = err.status || 500; const message = err.message || 'Sorry, we were unable to process your request.'; return res.status(status).send({ message, }); } next(); }); }; } 

Auth0 рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреА рд╕реЗрдЯрд┐рдВрдЧ рд╕реЗ рдбреЛрдореЗрди рдореВрд▓реНрдп рдХреЗ рд╕рд╛рде ${DOMAIN} рдХреЛ рдмрджрд▓реЗрдВ


рдЕрдиреБрд╡рд╛рджрдХ рдХрд╛ рдзреНрдпрд╛рди рджреЗрдВ: рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ, DOMAIN рдХреЛ рдПрдХ рд╕реНрдерд┐рд░рд╛рдВрдХ рдореЗрдВ рдмрд╛рд╣рд░ DOMAIN , рдФрд░ env (рдЖрднрд╛рд╕реА рд╡рд╛рддрд╛рд╡рд░рдг) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕рдХрд╛ рдорд╛рди рд╕реЗрдЯ рдХрд░реЗрдВ

express-jwt jwks-rsa рдФрд░ jwks-rsa рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ:


  npm install express-jwt jwks-rsa 

рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЗ рд▓рд┐рдП рдмрдирд╛рдП рдЧрдП рдорд┐рдбрд▓рд╡реЗрдпрд░ (рд╣реИрдВрдбрд▓рд░) рдХреЛ рдХрдиреЗрдХреНрдЯ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, ./src/app.module.ts рдлрд╝рд╛рдЗрд▓ рдореЗрдВ:


  import { Module, MiddlewareConsumer, RequestMethod } from '@nestjs/common'; import { AuthenticationMiddleware } from './common/authentication.middleware'; import { ItemsController } from './items/items.controller'; import { ShoppingCartController } from './shopping-cart/shopping-cart.controller'; import { ItemsService } from './items/items.service'; @Module({ imports: [], controllers: [ItemsController, ShoppingCartController], providers: [ItemsService], }) export class AppModule { public configure(consumer: MiddlewareConsumer) { consumer .apply(AuthenticationMiddleware) .forRoutes( { path: '/items', method: RequestMethod.POST }, { path: '/shopping-cart', method: RequestMethod.POST }, ); } } 

рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдХрд╛ рдХрд╣рдирд╛ рд╣реИ рдХрд┐ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдорд┐рдбрд▓рд╡реЗрдпрд░ рджреНрд╡рд╛рд░рд╛ /items рдФрд░ /shopping-cart рдорд╛рд░реНрдЧреЛрдВ рдХреЗ рд▓рд┐рдП POST рдЕрдиреБрд░реЛрдз рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИрдВ, рдЬреЛ рдЕрдиреБрд░реЛрдз рдореЗрдВ рдкрд╣реБрдБрдЪ рдЯреЛрдХрди рдХреЗ рд▓рд┐рдП рдЬрд╛рдБрдЪ рдХрд░рддрд╛ рд╣реИред


рд╡рд┐рдХрд╛рд╕ рд╕рд░реНрд╡рд░ рдХреЛ рдкреБрдирдГ рдЖрд░рдВрдн рдХрд░реЗрдВ ( npm run start:dev ) рдФрд░ Nest.js API рдкрд░ рдХреЙрд▓ рдХрд░реЗрдВ:


  #     curl -X POST http://localhost:3000/shopping-cart #      TOKEN="eyJ0eXAiO...Mh0dpeNpg" # and issue a POST request with it curl -X POST -H 'authorization: Bearer '$TOKEN http://localhost:3000/shopping-cart 

Auth0 рдХреЗ рд╕рд╛рде рднреВрдорд┐рдХрд╛ рдкреНрд░рдмрдВрдзрди

рдлрд┐рд▓рд╣рд╛рд▓, рд╕рддреНрдпрд╛рдкрд┐рдд рдЯреЛрдХрди рд╡рд╛рд▓рд╛ рдХреЛрдИ рднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╣рдорд╛рд░реЗ рдПрдкреАрдЖрдИ рдореЗрдВ рдЖрдЗрдЯрдо рдкреЛрд╕реНрдЯ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╣рдо рдЪрд╛рд╣реЗрдВрдЧреЗ рдХрд┐ рдХреЗрд╡рд▓ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдХ рдЕрдзрд┐рдХрд╛рд░реЛрдВ рд╡рд╛рд▓реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╣реА рдРрд╕рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдирд┐рдпрдореЛрдВ (рдирд┐рдпрдореЛрдВ) Auth0 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ ред


рддреЛ, рдирд┐рдпрдо рдЕрдиреБрднрд╛рдЧ рдореЗрдВ, Auth0 рдирд┐рдпрдВрддреНрд░рдг рдХрдХреНрд╖ рдкрд░ рдЬрд╛рдПрдВред рд╡рд╣рд╛рдВ, + CREATE RULE рдФрд░ рдирд┐рдпрдо рдореЙрдбрд▓ рдХреЗ рд░реВрдк рдореЗрдВ "рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рднреВрдорд┐рдХрд╛рдПрдВ рд╕реЗрдЯ рдХрд░реЗрдВ" рдЪреБрдиреЗрдВред



рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдореЗрдВ рдПрдХ рдирд┐рдпрдо рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рд╕рд╛рде рдПрдХ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдлрд╝рд╛рдЗрд▓ рдорд┐рд▓рддреА рд╣реИ рдЬреЛ рдХрд┐рд╕реА рднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдХ рднреВрдорд┐рдХрд╛ рдЬреЛрдбрд╝рддреА рд╣реИ рдЬрд┐рд╕рдХреЗ рдкрд╛рд╕ рдПрдХ рдИрдореЗрд▓ рд╣реИ рдЬреЛ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдбреЛрдореЗрди рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИред рдЪрд▓рд┐рдП рдЗрд╕ рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ рдХреБрдЫ рд╡рд┐рд╡рд░рдг рдмрджрд▓рдХрд░ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВред рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЗ рд▓рд┐рдП, рд╣рдо рдХреЗрд╡рд▓ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдИрдореЗрд▓ рдкрддреЗ рдкрд░ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдХ рдХреЛ рдкрд╣реБрдВрдЪ рдкреНрд░рджрд╛рди рдХрд░реЗрдВрдЧреЗред рд╣рдореЗрдВ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдХ рд╕реНрдерд┐рддрд┐ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдерд╛рди рдмрджрд▓рдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред


рдлрд┐рд▓рд╣рд╛рд▓, рдпрд╣ рдЬрд╛рдирдХрд╛рд░реА рдПрдХ рдкрд╣рдЪрд╛рди рдЯреЛрдХрди (рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рддреА рд╣реИ) рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИ, рд▓реЗрдХрд┐рди рдПрдкреАрдЖрдИ рдореЗрдВ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдХреНрд╕реЗрд╕ рдЯреЛрдХрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рдмрд╛рдж рдХрд╛ рдХреЛрдб рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:


  function (user, context, callback) { user.app_metadata = user.app_metadata || {}; if (user.email && user.email === '${YOUR_EMAIL}') { user.app_metadata.roles = ['admin']; } else { user.app_metadata.roles = ['user']; } auth0.users .updateAppMetadata(user.user_id, user.app_metadata) .then(function() { context.accessToken['http://localhost:3000/roles'] = user.app_metadata.roles; callback(null, user, context); }) .catch(function(err) { callback(err); }); } 

рдиреЛрдЯ: ${YOUR_EMAIL} рдХреЛ рдЕрдкрдиреЗ рдИрдореЗрд▓ рдкрддреЗ рд╕реЗ рдмрджрд▓реЗрдВред рдпрд╣ рдиреЛрдЯ рдХрд░рдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐, рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, рдЬрдм рдЖрдк Auth0 рдирд┐рдпрдореЛрдВ рдореЗрдВ рдИрдореЗрд▓ рд╕реЗ рдирд┐рдкрдЯрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдИрдореЗрд▓ рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрджрд░реНрд╢ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдИрдореЗрд▓ рдкрддреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред

рдЕрдиреБрд╡рд╛рджрдХ рдХрд╛ рдиреЛрдЯ: рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдЯреБрдХрдбрд╝рд╛ рдХреЛ Auth0 рдирд┐рдпрдо рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдкреГрд╖реНрда рдкрд░ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рджрд░реНрдЬ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ

рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ рдПрдкреАрдЖрдИ рдореЗрдВ рдЯреЛрдХрди рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВ, рд╣рдореЗрдВ рдЯреЛрдХрди рдХреА рдЬрд░реВрд░рдд рд╣реИ, рд╣рдореЗрдВ рдПрдХ рдЧрд╛рд░реНрдб Nest.js. src/common рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ, admin.guard.ts рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ


  import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; @Injectable() export class AdminGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const user = context.getArgs()[0].user['http://localhost:3000/roles'] || ''; return user.indexOf('admin') > -1; } } 

рдЕрдм, рдпрджрд┐ рд╣рдо рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рд▓реЙрдЧрд┐рди рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рджреЛрд╣рд░рд╛рддреЗ рд╣реИрдВ рдФрд░ рдирд┐рдпрдо рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдИрдореЗрд▓ рдкрддреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдПрдХ рдирдпрд╛ access_token ред рдЗрд╕ access_token рдХреА рд╕рд╛рдордЧреНрд░реА рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕рд╛рдЗрдЯ https://jwt.io/ рдХреЗ Encoded рдлрд╝реАрд▓реНрдб рдореЗрдВ рдЯреЛрдХрди рдХреЛ рдХреЙрдкреА рдФрд░ рдкреЗрд╕реНрдЯ https://jwt.io/ ред рд╣рдо рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдЗрд╕ рдЯреЛрдХрди рдХреЗ рдкреЗрд▓реЛрдб рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд░рдгреА рд╣реИрдВ:


  "http://localhost:3000/roles": [ "admin" ] 

рдпрджрд┐ рд╣рдорд╛рд░реЗ рдЯреЛрдХрди рдореЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣ рдЬрд╛рдирдХрд╛рд░реА рд╢рд╛рдорд┐рд▓ рд╣реИ, рддреЛ рд╣рдо Auth0 рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг рдЬрд╛рд░реА рд░рдЦрддреЗ рд╣реИрдВред рддреЛ, items.controller.ts рдЦреЛрд▓реЗрдВ items.controller.ts рдФрд░ рд╡рд╣рд╛рдВ рд╣рдорд╛рд░рд╛ рдирдпрд╛ рдЧрд╛рд░реНрдб рдЬреЛрдбрд╝реЗрдВ:


  import { Get, Post, Body, Controller, UsePipes, UseGuards, } from '@nestjs/common'; import { CreateItemDto } from './create-item.dto'; import { ItemsService } from './items.service'; import { Item } from './item.interface'; import { ValidationPipe } from '../common/validation.pipe'; import { AdminGuard } from '../common/admin.guard'; @Controller('items') export class ItemsController { constructor(private readonly itemsService: ItemsService) {} @Get() async findAll(): Promise<Item[]> { return this.itemsService.findAll(); } @Post() @UseGuards(new AdminGuard()) @UsePipes(new ValidationPipe()) async create(@Body() createItemDto: CreateItemDto) { this.itemsService.create(createItemDto); } } 

рдЕрдм, рд╣рдорд╛рд░реЗ рдирдП рдЯреЛрдХрди рдХреЗ рд╕рд╛рде, рд╣рдо рдЕрдкрдиреЗ рдПрдкреАрдЖрдИ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдирдП рдЖрдЗрдЯрдо рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ:


  #    npm run start:dev #  POST       curl -X POST -H 'Content-Type: application/json' \ -H 'authorization: Bearer '$TOKEN -d '{ "name": "Salad", "price": 3 }' http://localhost:3000/items 

рдЕрдиреБрд╡рд╛рджрдХ рдХрд╛ рдиреЛрдЯ: рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП, рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреНрдпрд╛ рд╣реИ:
 curl -X GET http://localhost:3000/items 


рдкрд░рд┐рдгрд╛рдо


рдмрдзрд╛рдИ! рд╣рдордиреЗ рдЕрднреА рдЕрдкрдирд╛ Nest.JS API рдмрдирд╛рдирд╛ рд╢реБрд░реВ рдХрд┐рдпрд╛ рдФрд░ рдЕрдм рд╣рдо рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдлреНрд░рдВрдЯреЗрдВрдб рднрд╛рдЧ рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ! рдЗрд╕ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рджреВрд╕рд░реЗ рднрд╛рдЧ рдХреЛ рджреЗрдЦрдирд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ: рдлреБрд▓-рд╕реНрдЯреИрдХ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдРрдкреНрд╕ - рднрд╛рдЧ 2: рдлреНрд░рдВрдЯрд┐рдВрдЧ рдХреЛрдгреАрдп рдХреЛрдгреАрдп рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ред


рдЕрдиреБрд╡рд╛рджрдХ рдХрд╛ рдиреЛрдЯ: рджреВрд╕рд░реЗ рднрд╛рдЧ рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдЬрд╛рд░реА рд╣реИред

рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рд╣рдордиреЗ Nest.js рдФрд░ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреА рд╡рд┐рднрд┐рдиреНрди рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛: рдореЙрдбреНрдпреВрд▓, рдирд┐рдпрдВрддреНрд░рдХ, рд╕реЗрд╡рд╛рдПрдВ, рдЗрдВрдЯрд░рдлреЗрд╕, рдкрд╛рдЗрдк, рдорд┐рдбрд▓рд╡реЗрдпрд░ рдФрд░ рдЧрд╛рд░реНрдб рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдкреАрдЖрдИред рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рдЕрдЪреНрдЫрд╛ рдЕрдиреБрднрд╡ рд╣реИ рдФрд░ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рд░реА рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИрдВред рдпрджрд┐ рдЖрдкрдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ, рддреЛ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ n.js рдкреНрд░рд▓реЗрдЦрди рдЙрддреНрддрд░ рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдЪреНрдЫрд╛ рд╕реНрд░реЛрдд рд╣реИ

Source: https://habr.com/ru/post/hi471348/


All Articles