{"id":314700,"date":"2020-12-11T15:00:28","date_gmt":"2020-12-11T15:00:28","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=314700"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=314700","title":{"rendered":"\u0414\u0438\u043d\u043e (Deno): \u0421\u043e\u0437\u0434\u0430\u0442\u044c API \u0434\u043b\u044f \u043e\u0442\u0434\u044b\u0445\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e JWT"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<blockquote>\n<p><strong>\u0412 \u043f\u0440\u0435\u0434\u0434\u0432\u0435\u0440\u0438\u0438 \u0441\u0442\u0430\u0440\u0442\u0430 \u043a\u0443\u0440\u0441\u0430 <\/strong><a href=\"https:\/\/otus.pw\/5GFJ\/\"><strong>&#171;Node.JS Developer&#187;<\/strong><\/a><strong> \u043f\u0440\u0438\u0433\u043b\u0430\u0448\u0430\u0435\u043c \u0432\u0441\u0435\u0445 \u0436\u0435\u043b\u0430\u044e\u0449\u0438\u0445 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u0443\u0440\u043e\u043a \u043d\u0430 \u0442\u0435\u043c\u0443 <\/strong><a href=\"https:\/\/otus.pw\/JUKY\/\"><strong>&#171;\u0414\u043e\u043a\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f Node.js \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439&#187;<\/strong><\/a><strong>.<\/strong><\/p>\n<p><em>\u0410 \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u0435\u043b\u0438\u043c\u0441\u044f \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u043c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u043e\u043c \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0433\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430. \u041f\u0440\u0438\u044f\u0442\u043d\u043e\u0433\u043e \u0447\u0442\u0435\u043d\u0438\u044f.<\/em><\/p>\n<\/blockquote>\n<hr>\n<p>\u0421\u043e \u0432\u0440\u0435\u043c\u0435\u043d \u043f\u0435\u0440\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 Deno \u0441\u0442\u0430\u043b \u043c\u043e\u0434\u043d\u044b\u043c \u0441\u043b\u043e\u0432\u043e\u043c \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 Javascript\/TypeScript\/Node. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0433\u0440\u0443\u0437\u0438\u043c\u0441\u044f \u0432 \u044d\u0442\u0443 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e, \u0441\u043e\u0437\u0434\u0430\u0432 \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u044b\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e JWT REST API.<\/p>\n<p>\u0416\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0436\u0435 \u0438\u043c\u0435\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0441\u043d\u043e\u0432\u044b \u0432 Node \u0438 \u0435\u0433\u043e \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0435 (Express, Nodemon, Sequelize \u0438 \u0442.\u0434.), \u0447\u0442\u043e\u0431\u044b \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u043c\u0443 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0443.<\/p>\n<h3>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0414\u0438\u043d\u043e (Deno)?<\/h3>\n<p>Deno &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0430\u044f \u0441\u0440\u0435\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f JavaScript \u0438 TypeScript, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 V8 \u0438 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0432 Rust.<\/p>\n<p>\u0423\u0436\u0435 \u0435\u0441\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0441\u0442\u0430\u0442\u0435\u0439, \u0434\u0435\u0442\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0449\u0438\u0445 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043d\u0435\u0439. \u042f \u043c\u043e\u0433\u0443 \u043f\u043e\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/blog.bitsrc.io\/what-is-deno-and-will-it-replace-nodejs-a13aa1734a74\"><u>\u044d\u0442\u0443<\/u><\/a>.<\/p>\n<h3>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0421 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u043b\u0438\u0437\u0430 <a href=\"https:\/\/deno.land\/v1\"><strong><u>V1<\/u><\/strong><\/a>, Deno \u0441\u0442\u0430\u043b &#171;\u043c\u043e\u0434\u043d\u044b\u043c \u0441\u043b\u043e\u0432\u0435\u0447\u043a\u043e\u043c&#187; \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043d\u0435\u0434\u0435\u043b\u044c (\u0434\u043b\u044f \u0444\u0430\u043d\u0430, \u0432\u043e\u0442 \u043a\u0440\u0438\u0432\u0430\u044f \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438 &#171;deno&#187; \u043f\u043e\u0438\u0441\u043a\u0430 \u0432 Google).<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/90b\/94e\/2ee\/90b94e2eed2aa0f8cda02c7db2310425\" width=\"700\" height=\"343\"><figcaption><\/figcaption><\/figure>\n<p>\u0427\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u043e\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043b\u044f Typescript and Javascript&#187;?<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u043d\u044f\u0442\u044c \u0438 \u0432\u044b\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0432\u043e\u0435 \u043c\u043d\u0435\u043d\u0438\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u0440\u0430\u0441\u0442\u0443\u0449\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u044f \u0440\u0435\u0448\u0438\u043b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u044b\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e JWT REST API \u0438 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0430\u043c\u0438 \u0441\u0432\u043e\u0438\u043c\u0438 \u0447\u0443\u0432\u0441\u0442\u0432\u0430\u043c\u0438.<\/p>\n<p>\u042f \u043f\u0440\u0438\u0432\u044b\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Node.js \u0438 <a href=\"https:\/\/expressjs.com\/\"><u>Express<\/u><\/a>.<\/p>\n<h3>\u0426\u0435\u043b\u044c<\/h3>\n<p>\u0426\u0435\u043b\u044c\u044e \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u043e\u0433\u043e REST API, \u0447\u0442\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0441 ORM \u0438 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>CRUD-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u043e\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 JWT<\/p>\n<\/li>\n<\/ul>\n<h3>\u041f\u0440\u0435\u0434\u043f\u043e\u0441\u044b\u043b\u043a\u0430<\/h3>\n<p>\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0433\u043e REST API \u0441 JWT, \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c :<\/p>\n<ul>\n<li>\n<p>Deno (\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438: <a href=\"https:\/\/deno.land\/#installation\"><u>\u0437\u0434\u0435\u0441\u044c<\/u><\/a>)<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>VSCode \u0438 \u043f\u043b\u0430\u0433\u0438\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 Deno, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u043f\u043e <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=denoland.vscode-deno\"><u>\u0441\u0441\u044b\u043b\u043a\u0435<\/u><\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0410 \u0442\u0430\u043a\u0436\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u043a\u0435\u0442\u044b (\u044f \u0431\u0443\u0434\u0443 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u044d\u0442\u043e\u043c\u0443 \u043d\u0430 \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u0438\u0438 \u0432\u0441\u0435\u0433\u043e \u0443\u0440\u043e\u043a\u0430):<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/deno.land\/x\/denon\"><u>Denon<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/deno.land\/x\/oak\"><u>Oak<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/deno.land\/x\/djwt\"><u>Djwt<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/deno.land\/x\/denodb\"><u>Denodb<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/deno.land\/x\/bcrypt\"><u>Bcrypt<\/u><\/a>&nbsp;<\/p>\n<\/li>\n<\/ul>\n<h3>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430<\/h3>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043b\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0447\u0438\u0441\u0442\u043e\u0433\u043e \u0438 &#171;\u0433\u043e\u0442\u043e\u0432\u043e\u0433\u043e \u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0441\u0442\u0432\u0443&#187; \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<pre><code class=\"javascript\">|-- DenoRestJwt     |-- controllers\/     |   |-- database\/     |   |-- models\/     |-- helpers\/     |-- middlewares\/     |-- routers\/     |-- app.ts<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u0431\u044b\u043b\u0438 \u043d\u0430 Node + Express \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438, \u044f \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b Nodemon \u0434\u043b\u044f \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, Nodemon \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0441\u043b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u043a\u043e\u0434\u0435.<\/p>\n<blockquote>\n<p><a href=\"https:\/\/www.npmjs.com\/package\/nodemon\"><u>Nodemon<\/u><\/a><u> <\/u>&#8212; \u044d\u0442\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 node.js, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 Node \u043f\u0440\u0438 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0444\u0430\u0439\u043b\u0435 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435.<\/p>\n<\/blockquote>\n<p>\u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0442\u043e\u0442 \u0436\u0435 &#171;\u043a\u043e\u043c\u0444\u043e\u0440\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438&#187;, \u044f \u0440\u0435\u0448\u0438\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/deno.land\/x\/denon\/\"><u>Denon<\/u><\/a>, \u0435\u0433\u043e \u0430\u043d\u0430\u043b\u043e\u0433 \u0434\u043b\u044f Deno.<\/p>\n<pre><code class=\"javascript\">deno install --allow-read --allow-run --allow-write -f --unstable  https:\/\/deno.land\/x\/denon\/denon.ts<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e Denon. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u043f\u043e\u0437\u0436\u0435 (\u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f).<\/p>\n<pre><code class=\"javascript\">\/\/ into denon.json {   \"$schema\": \"https:\/\/deno.land\/x\/denon\/schema.json\",   \"env\": {},   \"scripts\": {     \"start\": {       \"cmd\": \"deno run app.ts\"     }   } }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445! \u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Denon, \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0435 <code>denon start<\/code>:<\/p>\n<pre><code class=\"javascript\">\u279c denon start [denon] v2.0.2 [denon] watching path(s): *.* [denon] watching extensions: ts,js,json [denon] starting `deno run app.ts` Compile file:\/\/\/deno-crashtest\/app.ts [denon] clean exit - waiting for changes before restart<\/code><\/pre>\n<p>\u0412\u044b \u0432\u0438\u0434\u0438\u0442\u0435, \u0447\u0442\u043e \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u2026 \u043d\u043e \u043e\u043d \u043b\u043e\u043c\u0430\u0435\u0442\u0441\u044f! \u042d\u0442\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e, \u0443 \u043d\u0435\u0433\u043e \u043d\u0435\u0442 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0432 <code>app.ts<\/code>.<\/p>\n<h3>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440<\/h3>\n<p>\u042f \u0440\u0435\u0448\u0438\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a &nbsp;<a href=\"https:\/\/deno.land\/x\/oak\"><u>Oak<\/u><\/a>.<\/p>\n<p>Oak &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f http-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 Deno, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u0435 \u041f\u041e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u0430. \u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u0435\u043d Koa, \u0430 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440 \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u0435\u043d <code>@koa\/router<\/code>.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Oak :<\/p>\n<pre><code class=\"javascript\">\/\/ app.ts import { Application, Router, Status } from \"https:\/\/deno.land\/x\/oak\/mod.ts\";  \/\/ Initialise app const app = new Application();  \/\/ Initialise router const router = new Router();  \/\/ Create first default route router.get(\"\/\", (ctx) =&gt; {     ctx.response.status = Status.OK;     ctx.response.body = { message: \"It's work !\" }; });  app.use(router.routes()); app.use(router.allowedMethods());  console.log(\"? Deno start !\"); await app.listen(\"0.0.0.0:3001\");<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0435\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 <code>denon start<\/code>.<\/p>\n<pre><code class=\"javascript\">error: Uncaught PermissionDenied: network access to \"0.0.0.0:3001\",  run again with the --allow-net flag<\/code><\/pre>\n<p>\u042d\u0442\u043e \u043e\u0434\u043d\u043e \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0439 \u043c\u0435\u0436\u0434\u0443 Deno \u0438 Node: Deno \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u0435\u043d \u0438 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a <code>network<\/code>. \u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e:<\/p>\n<pre><code class=\"javascript\">\/\/ into denon.json \"scripts\": {     \"start\": {       \/\/ add --allow-net       \"cmd\": \"deno run --allow-net app.ts\"     }   }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u0438\u0437 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 (\u0445\u043e\u0442\u044f \u044f \u0441\u043e\u0432\u0435\u0442\u0443\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/www.postman.com\/\"><u>Postman<\/u><\/a>) \u043a <a href=\"http:\/\/localhost:3001\/\"><u>localhost:3001<\/u><\/a> :<\/p>\n<pre><code class=\"javascript\">{     \"message\": \"It's work !\" }<\/code><\/pre>\n<h3>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445<\/h3>\n<p>\u042f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/eveningkid\/denodb\"><u>DenoDB <\/u><\/a>\u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 ORM (\u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 Sqlite3). \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043e\u043d \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 <a href=\"http:\/\/sequelize\"><u>Sequelize<\/u><\/a> (\u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u044f \u043f\u0440\u0438\u0432\u044b\u043a).<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 <code>Database<\/code> \u0438 \u0444\u0430\u0439\u043b Sqlite3.<\/p>\n<pre><code class=\"javascript\">|-- DenoRestJwt     |-- controllers\/ \t|   |-- Database.ts         |   |-- database\/ \t|   |   |-- db.sqlite     |   |-- models\/     |-- app.ts<\/code><\/pre>\n<pre><code class=\"javascript\">\/\/ Database.ts import { Database } from \"https:\/\/deno.land\/x\/denodb\/mod.ts\";  export class DatabaseController {   client: Database;  \t\/**    * Initialise database client    *\/   constructor() {     this.client = new Database(\"sqlite3\", {       filepath: Deno.realPathSync(\".\/controllers\/database\/db.sqlite\"),     });   }    \/**    * Initialise models    *\/   async initModels() {     this.client.link([]);     await this.client.sync({});   } }<\/code><\/pre>\n<p>\u041d\u0430\u0448 ORM \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <code>realPathSync<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c <code>--allow-read<\/code> \u043d\u0435\u0434\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0435 \u0438 <code>--allow-write<\/code> \u043d\u0435\u0434\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0435 \u0432 <code>denon.json<\/code>:<\/p>\n<pre><code class=\"javascript\">\"scripts\": {     \"start\": {       \"cmd\": \"deno run --allow-write --allow-read --allow-net app.ts\"     }   }<\/code><\/pre>\n<p>\u0412\u0441\u0435, \u0447\u0442\u043e \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u044d\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0447\u0435\u0440\u0435\u0437 \u043d\u0430\u0448 ORM:<\/p>\n<pre><code class=\"javascript\">|-- DenoRestJwt     |-- controllers\/     |   |-- models\/     |       |-- User.ts     |-- app.ts<\/code><\/pre>\n<pre><code class=\"javascript\">\/\/ User.ts import { Model, DATA_TYPES } from \"https:\/\/deno.land\/x\/denodb\/mod.ts\"; import nanoid from \"https:\/\/deno.land\/x\/nanoid\/mod.ts\";  export interface IUser {   id?: string;   firstName: string;   lastName: string;   password: string; }  export class User extends Model {   static table = \"users\";   static timestamps = true;      static fields = {     id: {       primaryKey: true,       type: DATA_TYPES.STRING,     },     firstName: {       type: DATA_TYPES.STRING,     },     lastName: {       type: DATA_TYPES.STRING,     },     password: {       type: DATA_TYPES.TEXT,     },   };    \t\/\/ Id will generate a nanoid by default   static defaults = {     id: nanoid(),   }; }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e, \u0442\u0430\u043a \u0447\u0442\u043e \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u044d\u0442\u043e\u043c. (ps: \u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <code>nanoid<\/code> \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0438\u043c UUID, \u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044e \u0432\u0430\u043c \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u044d\u0442\u0443 \u043e\u0447\u0435\u043d\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e \u043e\u0431 \u044d\u0442\u043e\u043c).<\/p>\n<p>\u042f \u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0441\u044c \u044d\u0442\u043e\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u043f\u043e\u0437\u0436\u0435: \u0445\u044d\u0448 \u043f\u0430\u0440\u043e\u043b\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <a href=\"https:\/\/deno.land\/x\/bcrypt\"><u>Bcrypt<\/u><\/a>:<\/p>\n<pre><code class=\"javascript\">\/\/ inside User's class import * as bcrypt from \"https:\/\/deno.land\/x\/bcrypt\/mod.ts\";  \/\/ ... static async hashPassword(password: string) {     const salt = await bcrypt.genSalt(8);     return bcrypt.hash(password, salt); }<\/code><\/pre>\n<p>\u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u0432\u044f\u0436\u0435\u043c \u043d\u0430\u0448\u0443 \u043c\u043e\u0434\u0435\u043b\u044c \u0441 \u043d\u0430\u0448\u0438\u043c ORM :<\/p>\n<pre><code class=\"javascript\">\/\/ Database.ts import { User } from \".\/models\/User.ts\";  export class DatabaseController { \/\/...   initModels() {       \/\/ Add User here       this.client.link([User]);       return this.client.sync({});   } }<\/code><\/pre>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e! \u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u043c\u0435\u0441\u0442\u0435, \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u043e\u0432\u2026&nbsp;<\/p>\n<h2>User controller<\/h2>\n<p>\u041d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u0431\u043e\u043b\u0435\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e, \u0447\u0435\u043c \u0445\u043e\u0440\u043e\u0448\u0438\u0439 CRUD:<\/p>\n<pre><code class=\"javascript\">|-- DenoRestJwt     |-- controllers\/     |   |-- Database.ts     |   |-- UserController.ts<\/code><\/pre>\n<pre><code class=\"javascript\">import * as bcrypt from \"https:\/\/deno.land\/x\/bcrypt\/mod.ts\"; import { IUser, User } from \".\/models\/index.ts\";  export class UserController {   async create(values: IUser) {     \/\/ Call static user method     const password = await User.hashPassword(values.password);      const user: IUser = {       firstName: values.firstName,       lastName: values.lastName,       password,     };      await User.create(user as any);      return values;   }   async delete(id: string) {     await User.deleteById(id);   }    getAll() {     return User.all();   }    getOne(id: string) {     return User.where(\"id\", id).first();   }    async update(id: string, values: IUser) {     await User.where(\"id\", id).update(values as any);     return this.getOne(id);   }    async login(lastName: string, password: string) {     const user = await User.where(\"lastName\", lastName).first();     if (!user || !(await bcrypt.compare(password, user.password))) {       return false;     }      \/\/ TODO generate JWT    } }<\/code><\/pre>\n<p>\u042f \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043c\u0435\u0442\u043e\u0434\u044b, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 ORM. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 JWT.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u0438<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u0438 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u0441\u0432\u0435\u0436\u0435\u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440.<\/p>\n<pre><code class=\"javascript\">|-- DenoRestJwt     |-- routers         |-- UserRoute.ts<\/code><\/pre>\n<pre><code class=\"javascript\">import { Router, Status } from \"https:\/\/deno.land\/x\/oak\/mod.ts\"; import { UserController } from \"..\/controllers\/UserController.ts\"; import { BadRequest } from \"..\/helpers\/BadRequest.ts\"; import { NotFound } from \"..\/helpers\/NotFound.ts\";  \/\/ instantiate our controller const controller = new UserController();  export function UserRoutes(router: Router) {   return router     .get(\"\/users\", async (ctx) =&gt; {       const users = await controller.getAll();        if (users) {         ctx.response.status = Status.OK;         ctx.response.body = users;        } else {         ctx.response.status = Status.NotFound;         ctx.response.body = [];       }        return;     })     .post(\"\/login\", async (ctx) =&gt; {       if (!ctx.request.hasBody) {         return BadRequest(ctx);       }       const { value } = await ctx.request.body();        \/\/ TODO generate JWT        ctx.response.status = Status.OK;       ctx.response.body = { jwt };     })     .get(\"\/user\/:id\", async (ctx) =&gt; {       if (!ctx.params.id) {         return BadRequest(ctx);       }        const user = await controller.getOne(ctx.params.id);       if (user) {         ctx.response.status = Status.OK;         ctx.response.body = user;         return;       }        return NotFound(ctx);     })     .post(\"\/user\", async (ctx) =&gt; {       if (!ctx.request.hasBody) {         return BadRequest(ctx);       }        const { value } = await ctx.request.body();       const user = await controller.create(value);        if (user) {         ctx.response.status = Status.OK;         ctx.response.body = user;         return;       }        return NotFound(ctx);     })     .patch(\"\/user\/:id\", async (ctx) =&gt; {       if (!ctx.request.hasBody || !ctx.params.id) {         return BadRequest(ctx);       }        const { value } = await ctx.request.body();       const user = await controller.update(ctx.params.id, value);        if (user) {         ctx.response.status = Status.OK;         ctx.response.body = user;         return;       }        return NotFound(ctx);     })     .delete(\"\/user\/:id\", async (ctx) =&gt; {       if (!ctx.params.id) {         return BadRequest(ctx);       }        await controller.delete(ctx.params.id);        ctx.response.status = Status.OK;       ctx.response.body = { message: \"Ok\" };     }); }<\/code><\/pre>\n<p>\u0412\u0441\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u044d\u0442\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u043b\u043e\u0433\u0438\u043a\u0443 \u0438\u0437 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430.<\/p>\n<p>\u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043c\u0435\u0442\u043e\u0434\u044b HTTP \u0434\u043b\u044f \u0447\u0435\u0442\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432. \u042f \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043b \u0445\u0435\u043b\u043f\u0435\u0440\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u043c\u0438 \u043e\u0448\u0438\u0431\u043a\u0430\u043c\u0438. \u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043f\u0440\u044f\u043c\u043e \u0438\u0437 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 GitHub! \u0412\u0441\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u044d\u0442\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440 \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438:<\/p>\n<pre><code class=\"javascript\">\/\/ app.ts import { DatabaseController } from \".\/controllers\/Database.ts\"; import { UserRoutes } from \".\/routers\/UserRoute.ts\";  const userRoutes = UserRoutes(router); app.use(userRoutes.routes()); app.use(userRoutes.allowedMethods());  await new DatabaseController().initModels();<\/code><\/pre>\n<h3>\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0438 JWT<\/h3>\n<p>\u041f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u043a \u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443! \u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <a href=\"https:\/\/jwt.io\/\"><u>JWT <\/u><\/a>\u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/09a\/915\/975\/09a9159750e4e9cf34d3dc323dd099a0\" width=\"1600\" height=\"840\"><figcaption><\/figcaption><\/figure>\n<h4>1. \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442<\/h4>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e, \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u0441\u043b\u043e\u0439:<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a &#171;Authorization&#187;.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0441\u0442\u0430\u0435\u0442 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a<\/p>\n<\/li>\n<li>\n<p>\u0412\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u0442 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a&nbsp;<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 \/ \u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442<\/p>\n<\/li>\n<\/ul>\n<p>\u042f \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0441\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 <a href=\"https:\/\/deno.land\/x\/djwt\"><u>Djwt<\/u><\/a>.<\/p>\n<pre><code class=\"javascript\">|-- DenoRestJwt     |-- middlewares\/     |   |-- jwt.ts<\/code><\/pre>\n<p>\u041d\u0430\u0448\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u044f\u0442\u044c \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0442\u043e\u043a\u0435\u043d \u0438\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432, \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0435\u0433\u043e \u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u043d\u043e\u0441\u0442\u044c \u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c.<\/p>\n<pre><code class=\"javascript\">import { Context, Status } from \"https:\/\/deno.land\/x\/oak\/mod.ts\"; import { validateJwt } from \"https:\/\/deno.land\/x\/djwt\/validate.ts\";  \/**  * Create a default configuration  *\/ export const JwtConfig = {   header: \"Authorization\",   schema: \"Bearer\", \t\/\/ use Env variable   secretKey: Deno.env.get(\"SECRET\") || \"\",   expirationTime: 60000,   type: \"JWT\",   alg: \"HS256\", };  export async function jwtAuth(   ctx: Context&lt;Record&lt;string, any&gt;&gt;,   next: () =&gt; Promise&lt;void&gt; ) {     \/\/ Get the token from the request     const token = ctx.request.headers       .get(JwtConfig.header)       ?.replace(`${JwtConfig.schema} `, \"\");          \/\/ reject request if token was not provide     if (!token) {       ctx.response.status = Status.Unauthorized;       ctx.response.body = { message: \"Unauthorized\" };       return;     }          \/\/ check the validity of the token     if (       !(await validateJwt(token, JwtConfig.secretKey, { isThrowing: false }))     ) {       ctx.response.status = Status.Unauthorized;       ctx.response.body = { message: \"Wrong Token\" };       return;     }          \/\/ JWT is correct, so continue and call the private route     next();   }<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043a\u043b\u044e\u0447, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u0442\u043e\u043a\u0435\u043d. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f Deno. \u0422\u0430\u043a \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u043d\u0435\u0441\u0442\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e Denon: \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u0448\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c Deno \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"javascript\">{   \"$schema\": \"&lt;https:\/\/deno.land\/x\/denon\/schema.json&gt;\",   \/\/ Add env variable   \"env\": {     \"SECRET\": \"ADRIEN_IS_THE_BEST_AUTHOR_ON_MEDIUM\"   },   \"scripts\": {     \"start\": {       \/\/ add the permission with --allow-env       \"cmd\": \"deno run --allow-env --allow-read --allow-net app.ts\"     }   } }<\/code><\/pre>\n<p>(ps: \u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435<strong> <\/strong>\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<strong>,<\/strong> \u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u044d\u0442\u043e<a href=\"https:\/\/medium.com\/javascript-in-plain-english\/im-now-versioning-my-app-secrets-in-git-here-is-why-you-should-do-the-same-2a72c1a49039\"><u> \u0443\u0447\u0435\u0431\u043d\u043e\u0435 \u043f\u043e\u0441\u043e\u0431\u0438\u0435<\/u><\/a>)<\/p>\n<p>\u0422\u043e\u0433\u0434\u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0430\u0448 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442.<\/p>\n<pre><code class=\"javascript\">|-- DenoRestJwt     |-- routers         |-- UserRoute.ts         |-- PrivateRoute.ts<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0437\u043e\u0432\u0438\u0442\u0435 \u043d\u0430\u0448 \u043c\u0435\u0442\u043e\u0434 \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u043d\u0430\u0448\u0435\u0433\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430:<\/p>\n<pre><code class=\"javascript\">import { Router, Status } from \"https:\/\/deno.land\/x\/oak\/mod.ts\"; import { jwtAuth } from \"..\/middlewares\/jwt.ts\";  export function PrivateRoutes(router: Router) {   \/\/ call our middleware before our private route   return router.get(\"\/private\", jwtAuth, async (ctx) =&gt; {     ctx.response.status = Status.OK;     ctx.response.body = { message: \"Conntected !\" };   }); }<\/code><\/pre>\n<p>\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"javascript\">import { Router, Status } from \"https:\/\/deno.land\/x\/oak\/mod.ts\"; import { jwtAuth } from \"..\/middlewares\/jwt.ts\";  export function PrivateRoutes(router: Router) {   \/\/ call our middleware before our private route   return router.get(\"\/private\", jwtAuth, async (ctx) =&gt; {     ctx.response.status = Status.OK;     ctx.response.body = { message: \"Conntected !\" };   }); }<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043d\u0430\u0448 API \u043d\u0430 \/private , \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442:<\/p>\n<pre><code class=\"javascript\">{     \"message\": \"Unauthorized\" }<\/code><\/pre>\n<h4>2.&nbsp; JWT \u043f\u043e\u043a\u043e\u043b\u0435\u043d\u0438\u0435<\/h4>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u043f\u0440\u0438 \u0432\u0445\u043e\u0434\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443. \u041f\u043e\u043c\u043d\u0438\u0442\u0435, \u0447\u0442\u043e \u043c\u044b \u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \/\/ TODO generate JWT \u0432 \u043d\u0430\u0448\u0435\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435. \u041f\u0435\u0440\u0435\u0434 \u0435\u0433\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435\u043c \u043c\u044b \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 \u0432 \u043d\u0430\u0448\u0443 \u043c\u043e\u0434\u0435\u043b\u044c User, \u0447\u0442\u043e\u0431\u044b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d.<\/p>\n<pre><code class=\"javascript\">\/\/ User.ts import {   makeJwt,   setExpiration,   Jose,   Payload, } from \"https:\/\/deno.land\/x\/djwt\/create.ts\"; import { JwtConfig } from \"..\/..\/middlewares\/jwt.ts\"; \/\/ ...  export class User extends Model { \/\/ ... \tstatic generateJwt(id: string) { \t    \/\/ Create the payload with the expiration date (token have an expiry date) and the id of current user (you can add that you want) \t    const payload: Payload = { \t      id, \t      exp: setExpiration(new Date().getTime() + JwtConfig.expirationTime), \t    }; \t    const header: Jose = { \t      alg: JwtConfig.alg as Jose[\"alg\"], \t      typ: JwtConfig.type, \t    };  \t    \/\/ return the generated token \t    return makeJwt({ header, payload, key: JwtConfig.secretKey }); \t  } \t\/\/ ... }<\/code><\/pre>\n<p>\u0412\u044b\u0437\u043e\u0432\u0435\u043c \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432 \u043d\u0430\u0448\u0435\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435 :<\/p>\n<pre><code class=\"javascript\">\/\/ UserController.ts  export class UserController { \/\/ ... \tasync login(lastName: string, password: string) { \t\t\tconst user = await User.where(\"lastName\", lastName).first(); \t\t\tif (!user || !(await bcrypt.compare(password, user.password))) { \t\t\t\treturn false; \t\t\t} \t\t\t\/\/ Call our new static method \t\t\treturn User.generateJwt(user.id); \t } }<\/code><\/pre>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u044d\u0442\u0443 \u043b\u043e\u0433\u0438\u043a\u0443 \u0432 \u043d\u0430\u0448 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440:<\/p>\n<pre><code class=\"javascript\">\/\/ UserRoute.ts  \/\/ ... .post(\"\/login\", async (ctx) =&gt; {       if (!ctx.request.hasBody) {         return BadRequest(ctx);       }       const { value } = await ctx.request.body(); \t\t\t       \/\/ generate jwt       const jwt = await controller.login(value.lastName, value.password);       if (!jwt) {         return BadRequest(ctx);       }        ctx.response.status = Status.OK;       \/\/ and return it       ctx.response.body = { jwt };     }) \/\/ ...<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0435\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c :<\/p>\n<pre><code class=\"javascript\">\/\/ localhost:3001\/login {     \"jwt\":  \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IlEyY0ZZcUxKWk5Hc0toN0FWV0hzUiIsImV4cCI6MTU5MDg0NDU2MDM5MH0.drQ3ay5_DYuXEOnH2Z0RKbhq9nZElWCMvmypjI4BjIk\" }<\/code><\/pre>\n<p>(\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0440\u0430\u043d\u044c\u0448\u0435)<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u044d\u0442\u043e\u0442 \u0442\u043e\u043a\u0435\u043d \u0432 \u043d\u0430\u0448\u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 <code>Authorization<\/code> \u0438 \u0441\u043d\u043e\u0432\u0430 \u0432\u044b\u0437\u043e\u0432\u0435\u043c \u043d\u0430\u0448 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442:<\/p>\n<pre><code class=\"javascript\">\/\/ localhost:3001\/private with token in headers {     \"message\": \"Connected !\" }<\/code><\/pre>\n<p>\u0417\u0434\u043e\u0440\u043e\u0432\u043e! \u0415\u0441\u0442\u044c \u043d\u0430\u0448 \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u044b\u0439 API ?.<\/p>\n<p>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438 \u044d\u0442\u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 \u043c\u043e\u0435\u043c Github: <a href=\"https:\/\/github.com\/Trobyss\/deno-api-rest-jwt\"><u>\u0437\u0434\u0435\u0441\u044c <\/u><\/a>(\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u043f\u043e\u0447\u0442\u0430\u043b\u044c\u043e\u043d\u0430, \u0447\u0442\u043e\u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441).<\/p>\n<h2>\u041c\u043e\u0438 \u0432\u043f\u0435\u0447\u0430\u0442\u043b\u0435\u043d\u0438\u044f \u043e Deno<\/h2>\n<p>\u042f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0430\u043c\u0438 \u0441\u0432\u043e\u0438\u043c\u0438 \u0432\u043f\u0435\u0447\u0430\u0442\u043b\u0435\u043d\u0438\u044f\u043c\u0438 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e Depo, \u0447\u0442\u043e \u0432\u0430\u043c \u0434\u0430\u0441\u0442 \u043d\u0435\u043a\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e \u043d\u0435\u043c:<\/p>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u043f\u043e URL \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440-\u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u0435\u043d: \u0432\u0441\u0435\u0433\u0434\u0430 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c <code>npm i<\/code> \u0438\u043b\u0438 &nbsp;<code>yarn add<\/code>. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043d\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c Deno, \u0447\u0442\u043e\u0431\u044b \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u044b, \u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0430\u0432\u0442\u043e\u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044e.<\/p>\n<pre><code class=\"javascript\">The remote module XXX has not been cached<\/code><\/pre>\n<ul>\n<li>\n<p>\u042f \u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e TypeScript \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043d\u0430 Javascript, \u0442\u0430\u043a \u0447\u0442\u043e \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u044f \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u043b\u0441\u044f. \u041d\u0430\u043f\u0440\u043e\u0442\u0438\u0432, \u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0437\u043d\u0430\u043a\u043e\u043c \u0441 \u043d\u0438\u043c.<\/p>\n<\/li>\n<li>\n<p>\u0418\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442: permissions. \u042f \u0434\u0443\u043c\u0430\u044e, \u0445\u043e\u0440\u043e\u0448\u043e, \u0447\u0442\u043e Deno, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0440\u0435\u0431\u0443\u0435\u0442 permissions \u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0441\u0435\u0442\u0438. \u042d\u0442\u043e \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0441, \u043a\u0430\u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0431\u044b\u0442\u044c \u0432 \u043a\u0443\u0440\u0441\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438 \u043f\u0440\u0430\u0432 \u043d\u0430\u0448\u0435\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b. (\u0431\u043e\u043b\u0435\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e)<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u044b \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0442\u0430\u043b\u0438\u0441\u044c \u0432 \u0442\u043e\u043c, \u0433\u0434\u0435 \u0438\u0441\u043a\u0430\u0442\u044c \u043f\u0430\u043a\u0435\u0442\u044b (https:\/\/deno.land\/x \u2192 460 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0438 NPM \u2192 + 1 \u043c\u0438\u043b\u043b\u0438\u043e\u043d).<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u0431\u044b\u0442\u044c \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u043f\u0430\u043a\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 Deno \u0438\u043b\u0438 \u043d\u0435\u0442. \u0412\u044b +\u0432\u0441\u0435\u0433\u0434\u0430 \u0445\u043e\u0442\u0438\u0442\u0435 \u0431\u044b\u0442\u044c \u0431\u043b\u0438\u0436\u0435 \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0437\u043d\u0430\u0435\u0442\u0435 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u043d\u0430 Node, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0435\u0433\u043e \u043d\u0430 Deno. \u042f \u043d\u0435 \u0437\u043d\u0430\u044e, \u0445\u043e\u0440\u043e\u0448\u043e \u044d\u0442\u043e \u0438\u043b\u0438 \u043f\u043b\u043e\u0445\u043e, \u044d\u0442\u043e \u0432\u0441\u0451 \u0435\u0449\u0451 javascript\u2026<\/p>\n<\/li>\n<\/ul>\n<hr>\n<blockquote>\n<p>\u0423\u0437\u043d\u0430\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u043a\u0443\u0440\u0441\u0435 <a href=\"https:\/\/otus.pw\/5GFJ\/\">&#171;Node.JS Developer&#187;<\/a>.<\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u0443\u0440\u043e\u043a \u043d\u0430 \u0442\u0435\u043c\u0443 <a href=\"https:\/\/otus.pw\/JUKY\/\">&#171;\u0414\u043e\u043a\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f Node.js \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439&#187;<\/a>.<\/p>\n<\/blockquote>\n<hr>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/03d\/1e7\/93c\/03d1e793c40da80a43bffd98462db76e.jpg\" width=\"780\" height=\"300\"><figcaption><\/figcaption><\/figure>\n<p><a href=\"https:\/\/otus.pw\/EipQ\/\"><strong>\u0417\u0410\u0411\u0420\u0410\u0422\u042c \u0421\u041a\u0418\u0414\u041a\u0423<\/strong><\/a><\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/otus\/blog\/532582\/\"> https:\/\/habr.com\/ru\/company\/otus\/blog\/532582\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<blockquote>\n<p><strong>\u0412 \u043f\u0440\u0435\u0434\u0434\u0432\u0435\u0440\u0438\u0438 \u0441\u0442\u0430\u0440\u0442\u0430 \u043a\u0443\u0440\u0441\u0430 <\/strong><a href=\"https:\/\/otus.pw\/5GFJ\/\"><strong>&#171;Node.JS Developer&#187;<\/strong><\/a><strong> \u043f\u0440\u0438\u0433\u043b\u0430\u0448\u0430\u0435\u043c \u0432\u0441\u0435\u0445 \u0436\u0435\u043b\u0430\u044e\u0449\u0438\u0445 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u0443\u0440\u043e\u043a \u043d\u0430 \u0442\u0435\u043c\u0443 <\/strong><a href=\"https:\/\/otus.pw\/JUKY\/\"><strong>&#171;\u0414\u043e\u043a\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f Node.js \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439&#187;<\/strong><\/a><strong>.<\/strong><\/p>\n<p><em>\u0410 \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u0435\u043b\u0438\u043c\u0441\u044f \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u043c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u043e\u043c \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0433\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430. \u041f\u0440\u0438\u044f\u0442\u043d\u043e\u0433\u043e \u0447\u0442\u0435\u043d\u0438\u044f.<\/em><\/p>\n<\/blockquote>\n<hr>\n<p>\u0421\u043e \u0432\u0440\u0435\u043c\u0435\u043d \u043f\u0435\u0440\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 Deno \u0441\u0442\u0430\u043b \u043c\u043e\u0434\u043d\u044b\u043c \u0441\u043b\u043e\u0432\u043e\u043c \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 Javascript\/TypeScript\/Node. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0433\u0440\u0443\u0437\u0438\u043c\u0441\u044f \u0432 \u044d\u0442\u0443 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e, \u0441\u043e\u0437\u0434\u0430\u0432 \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u044b\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e JWT REST API.<\/p>\n<p>\u0416\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0436\u0435 \u0438\u043c\u0435\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0441\u043d\u043e\u0432\u044b \u0432 Node \u0438 \u0435\u0433\u043e \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0435 (Express, Nodemon, Sequelize \u0438 \u0442.\u0434.), \u0447\u0442\u043e\u0431\u044b \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u043c\u0443 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0443.<\/p>\n<h3>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0414\u0438\u043d\u043e (Deno)?<\/h3>\n<p>Deno &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0430\u044f \u0441\u0440\u0435\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f JavaScript \u0438 TypeScript, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 V8 \u0438 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0432 Rust.<\/p>\n<p>\u0423\u0436\u0435 \u0435\u0441\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0441\u0442\u0430\u0442\u0435\u0439, \u0434\u0435\u0442\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0449\u0438\u0445 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043d\u0435\u0439. \u042f \u043c\u043e\u0433\u0443 \u043f\u043e\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/blog.bitsrc.io\/what-is-deno-and-will-it-replace-nodejs-a13aa1734a74\"><u>\u044d\u0442\u0443<\/u><\/a>.<\/p>\n<h3>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0421 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u043b\u0438\u0437\u0430 <a href=\"https:\/\/deno.land\/v1\"><strong><u>V1<\/u><\/strong><\/a>, Deno \u0441\u0442\u0430\u043b &#171;\u043c\u043e\u0434\u043d\u044b\u043c \u0441\u043b\u043e\u0432\u0435\u0447\u043a\u043e\u043c&#187; \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043d\u0435\u0434\u0435\u043b\u044c (\u0434\u043b\u044f \u0444\u0430\u043d\u0430, \u0432\u043e\u0442 \u043a\u0440\u0438\u0432\u0430\u044f \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438 &#171;deno&#187; \u043f\u043e\u0438\u0441\u043a\u0430 \u0432 Google).<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0427\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u043e\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043b\u044f Typescript and Javascript&#187;?<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u043d\u044f\u0442\u044c \u0438 \u0432\u044b\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0432\u043e\u0435 \u043c\u043d\u0435\u043d\u0438\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u0440\u0430\u0441\u0442\u0443\u0449\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u044f \u0440\u0435\u0448\u0438\u043b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u044b\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e JWT REST API \u0438 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0430\u043c\u0438 \u0441\u0432\u043e\u0438\u043c\u0438 \u0447\u0443\u0432\u0441\u0442\u0432\u0430\u043c\u0438.<\/p>\n<p>\u042f \u043f\u0440\u0438\u0432\u044b\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Node.js \u0438 <a href=\"https:\/\/expressjs.com\/\"><u>Express<\/u><\/a>.<\/p>\n<h3>\u0426\u0435\u043b\u044c<\/h3>\n<p>\u0426\u0435\u043b\u044c\u044e \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u043e\u0433\u043e REST API, \u0447\u0442\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0441 ORM \u0438 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>CRUD-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u043e\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 JWT<\/p>\n<\/li>\n<\/ul>\n<h3>\u041f\u0440\u0435\u0434\u043f\u043e\u0441\u044b\u043b\u043a\u0430<\/h3>\n<p>\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0433\u043e REST API \u0441 JWT, \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c :<\/p>\n<ul>\n<li>\n<p>Deno (\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438: <a href=\"https:\/\/deno.land\/#installation\"><u>\u0437\u0434\u0435\u0441\u044c<\/u><\/a>)<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>VSCode \u0438 \u043f\u043b\u0430\u0433\u0438\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 Deno, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u043f\u043e <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=denoland.vscode-deno\"><u>\u0441\u0441\u044b\u043b\u043a\u0435<\/u><\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0410 \u0442\u0430\u043a\u0436\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u043a\u0435\u0442\u044b (\u044f \u0431\u0443\u0434\u0443 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u044d\u0442\u043e\u043c\u0443 \u043d\u0430 \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u0438\u0438 \u0432\u0441\u0435\u0433\u043e \u0443\u0440\u043e\u043a\u0430):<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/deno.land\/x\/denon\"><u>Denon<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/deno.land\/x\/oak\"><u>Oak<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/deno.land\/x\/djwt\"><u>Djwt<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/deno.land\/x\/denodb\"><u>Denodb<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/deno.land\/x\/bcrypt\"><u>Bcrypt<\/u><\/a>&nbsp;<\/p>\n<\/li>\n<\/ul>\n<h3>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430<\/h3>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043b\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0447\u0438\u0441\u0442\u043e\u0433\u043e \u0438 &#171;\u0433\u043e\u0442\u043e\u0432\u043e\u0433\u043e \u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0441\u0442\u0432\u0443&#187; \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<pre><code class=\"javascript\">|-- DenoRestJwt     |-- controllers\/     |   |-- database\/     |   |-- models\/     |-- helpers\/     |-- middlewares\/     |-- routers\/     |-- app.ts<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u0431\u044b\u043b\u0438 \u043d\u0430 Node + Express \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438, \u044f \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b Nodemon \u0434\u043b\u044f \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, Nodemon \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0441\u043b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u043a\u043e\u0434\u0435.<\/p>\n<blockquote>\n<p><a href=\"https:\/\/www.npmjs.com\/package\/nodemon\"><u>Nodemon<\/u><\/a><u> <\/u>&#8212; \u044d\u0442\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 node.js, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 Node \u043f\u0440\u0438 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0444\u0430\u0439\u043b\u0435 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435.<\/p>\n<\/blockquote>\n<p>\u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0442\u043e\u0442 \u0436\u0435 &#171;\u043a\u043e\u043c\u0444\u043e\u0440\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438&#187;, \u044f \u0440\u0435\u0448\u0438\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/deno.land\/x\/denon\/\"><u>Denon<\/u><\/a>, \u0435\u0433\u043e \u0430\u043d\u0430\u043b\u043e\u0433 \u0434\u043b\u044f Deno.<\/p>\n<pre><code class=\"javascript\">deno install --allow-read --allow-run --allow-write -f --unstable  https:\/\/deno.land\/x\/denon\/denon.ts<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e Denon. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u043f\u043e\u0437\u0436\u0435 (\u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f).<\/p>\n<pre><code class=\"javascript\">\/\/ into denon.json {   \"$schema\": \"https:\/\/deno.land\/x\/denon\/schema.json\",   \"env\": {},   \"scripts\": {     \"start\": {       \"cmd\": \"deno run app.ts\"     }   } }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445! \u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Denon, \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0435 <code>denon start<\/code>:<\/p>\n<pre><code class=\"javascript\">\u279c denon start [denon] v2.0.2 [denon] watching path(s): *.* [denon] watching extensions: ts,js,json [denon] starting `deno run app.ts` Compile file:\/\/\/deno-crashtest\/app.ts [denon] clean exit - waiting for changes before restart<\/code><\/pre>\n<p>\u0412\u044b \u0432\u0438\u0434\u0438\u0442\u0435, \u0447\u0442\u043e \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u2026 \u043d\u043e \u043e\u043d \u043b\u043e\u043c\u0430\u0435\u0442\u0441\u044f! \u042d\u0442\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e, \u0443 \u043d\u0435\u0433\u043e \u043d\u0435\u0442 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0432 <code>app.ts<\/code>.<\/p>\n<h3>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440<\/h3>\n<p>\u042f \u0440\u0435\u0448\u0438\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a &nbsp;<a href=\"https:\/\/deno.land\/x\/oak\"><u>Oak<\/u><\/a>.<\/p>\n<p>Oak &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f http-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 Deno, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u0435 \u041f\u041e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u0430. \u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u0435\u043d Koa, \u0430 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440 \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u0435\u043d <code>@koa\/router<\/code>.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Oak :<\/p>\n<pre><code class=\"javascript\">\/\/ app.ts import { Application, Router, Status } from \"https:\/\/deno.land\/x\/oak\/mod.ts\";  \/\/ Initialise app const app = new Application();  \/\/ Initialise router const router = new Router();  \/\/ Create first default route router.get(\"\/\", (ctx) =&gt; {     ctx.response.status = Status.OK;     ctx.response.body = { message: \"It's work !\" }; });  app.use(router.routes()); app.use(router.allowedMethods());  console.log(\"? Deno start !\"); await app.listen(\"0.0.0.0:3001\");<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0435\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 <code>denon start<\/code>.<\/p>\n<pre><code class=\"javascript\">error: Uncaught PermissionDenied: network access to \"0.0.0.0:3001\",  run again with the --allow-net flag<\/code><\/pre>\n<p>\u042d\u0442\u043e \u043e\u0434\u043d\u043e \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0439 \u043c\u0435\u0436\u0434\u0443 Deno \u0438 Node: Deno \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u0435\u043d \u0438 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a <code>network<\/code>. \u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e:<\/p>\n<pre><code class=\"javascript\">\/\/ into denon.json \"scripts\": {     \"start\": {       \/\/ add --allow-net       \"cmd\": \"deno run --allow-net app.ts\"     }   }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u0438\u0437 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 (\u0445\u043e\u0442\u044f \u044f \u0441\u043e\u0432\u0435\u0442\u0443\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/www.postman.com\/\"><u>Postman<\/u><\/a>) \u043a <a href=\"http:\/\/localhost:3001\/\"><u>localhost:3001<\/u><\/a> :<\/p>\n<pre><code class=\"javascript\">{     \"message\": \"It's work !\" }<\/code><\/pre>\n<h3>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445<\/h3>\n<p>\u042f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/eveningkid\/denodb\"><u>DenoDB <\/u><\/a>\u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 ORM (\u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 Sqlite3). \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043e\u043d \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 <a href=\"http:\/\/sequelize\"><u>Sequelize<\/u><\/a> (\u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u044f \u043f\u0440\u0438\u0432\u044b\u043a).<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 <code>Database<\/code> \u0438 \u0444\u0430\u0439\u043b Sqlite3.<\/p>\n<pre><code class=\"javascript\">|-- DenoRestJwt     |-- controllers\/ \t|   |-- Database.ts         |   |-- database\/ \t|   |   |-- db.sqlite     |   |-- models\/     |-- app.ts<\/code><\/pre>\n<pre><code class=\"javascript\">\/\/ Database.ts import { Database } from \"https:\/\/deno.land\/x\/denodb\/mod.ts\";  export class DatabaseController {   client: Database;  \t\/**    * Initialise database client    *\/   constructor() {     this.client = new Database(\"sqlite3\", {       filepath: Deno.realPathSync(\".\/controllers\/database\/db.sqlite\"),     });   }    \/**    * Initialise models    *\/   async initModels() {     this.client.link([]);     await this.client.sync({});   } }<\/code><\/pre>\n<p>\u041d\u0430\u0448 ORM \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <code>realPathSync<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c <code>--allow-read<\/code> \u043d\u0435\u0434\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0435 \u0438 <code>--allow-write<\/code> \u043d\u0435\u0434\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0435 \u0432 <code>denon.json<\/code>:<\/p>\n<pre><code class=\"javascript\">\"scripts\": {     \"start\": {       \"cmd\": \"deno run --allow-write --allow-read --allow-net app.ts\"     }   }<\/code><\/pre>\n<p>\u0412\u0441\u0435, \u0447\u0442\u043e \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u044d\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0447\u0435\u0440\u0435\u0437 \u043d\u0430\u0448 ORM:<\/p>\n<pre><code class=\"javascript\">|-- DenoRestJwt     |-- controllers\/     |   |-- models\/     |       |-- User.ts     |-- app.ts<\/code><\/pre>\n<pre><code class=\"javascript\">\/\/ User.ts import { Model, DATA_TYPES } from \"https:\/\/deno.land\/x\/denodb\/mod.ts\"; import nanoid from \"https:\/\/deno.land\/x\/nanoid\/mod.ts\";  export interface IUser {   id?: string;   firstName: string;   lastName: string;   password: string; }  export class User extends Model {   static table = \"users\";   static timestamps = true;      static fields = {     id: {       primaryKey: true,       type: DATA_TYPES.STRING,     },     firstName: {       type: DATA_TYPES.STRING,     },     lastName: {       type: DATA_TYPES.STRING,     },     password: {       type: DATA_TYPES.TEXT,     },   };    \t\/\/ Id will generate a nanoid by default   static defaults = {     id: nanoid(),   }; }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e, \u0442\u0430\u043a \u0447\u0442\u043e \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u044d\u0442\u043e\u043c. (ps: \u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <code>nanoid<\/code> \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0438\u043c UUID, \u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044e \u0432\u0430\u043c \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u044d\u0442\u0443 \u043e\u0447\u0435\u043d\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e \u043e\u0431 \u044d\u0442\u043e\u043c).<\/p>\n<p>\u042f \u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0441\u044c \u044d\u0442\u043e\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u043f\u043e\u0437\u0436\u0435: \u0445\u044d\u0448 \u043f\u0430\u0440\u043e\u043b\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <a href=\"https:\/\/deno.land\/x\/bcrypt\"><u>Bcrypt<\/u><\/a>:<\/p>\n<pre><code class=\"javascript\">\/\/ inside User's class import * as bcrypt from \"https:\/\/deno.land\/x\/bcrypt\/mod.ts\";  \/\/ ... static async hashPassword(password: string) {     const salt = await bcrypt.genSalt(8);     return bcrypt.hash(password, salt); }<\/code><\/pre>\n<p>\u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u0432\u044f\u0436\u0435\u043c \u043d\u0430\u0448\u0443 \u043c\u043e\u0434\u0435\u043b\u044c \u0441 \u043d\u0430\u0448\u0438\u043c ORM :<\/p>\n<pre><code class=\"javascript\">\/\/ Database.ts import { User } from \".\/models\/User.ts\";  export class DatabaseController { \/\/...   initModels() {       \/\/ Add User here       this.client.link([User]);       return this.client.sync({});   } }<\/code><\/pre>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e! \u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u043c\u0435\u0441\u0442\u0435, \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u043e\u0432\u2026&nbsp;<\/p>\n<h2>User controller<\/h2>\n<p>\u041d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u0431\u043e\u043b\u0435\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e, \u0447\u0435\u043c \u0445\u043e\u0440\u043e\u0448\u0438\u0439 CRUD:<\/p>\n<pre><code class=\"javascript\">|-- DenoRestJwt     |-- controllers\/     |   |-- Database.ts     |   |-- UserController.ts<\/code><\/pre>\n<pre><code class=\"javascript\">import * as bcrypt from \"https:\/\/deno.land\/x\/bcrypt\/mod.ts\"; import { IUser, User } from \".\/models\/index.ts\";  export class UserController {   async create(values: IUser) {     \/\/ Call static user method     const password = await User.hashPassword(values.password);      const user: IUser = {       firstName: values.firstName,       lastName: values.lastName,       password,     };      await User.create(user as any);      return values;   }   async delete(id: string) {     await User.deleteById(id);   }    getAll() {     return User.all();   }    getOne(id: string) {     return User.where(\"id\", id).first();   }    async update(id: string, values: IUser) {     await User.where(\"id\", id).update(values as any);     return this.getOne(id);   }    async login(lastName: string, password: string) {     const user = await User.where(\"lastName\", lastName).first();     if (!user || !(await bcrypt.compare(password, user.password))) {       return false;     }      \/\/ TODO generate JWT    } }<\/code><\/pre>\n<p>\u042f \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043c\u0435\u0442\u043e\u0434\u044b, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 ORM. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 JWT.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u0438<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u0438 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u0441\u0432\u0435\u0436\u0435\u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440.<\/p>\n<pre><code class=\"javascript\">|-- DenoRestJwt     |-- routers         |-- UserRoute.ts<\/code><\/pre>\n<pre><code class=\"javascript\">import { Router, Status } from \"https:\/\/deno.land\/x\/oak\/mod.ts\"; import { UserController } from \"..\/controllers\/UserController.ts\"; import { BadRequest } from \"..\/helpers\/BadRequest.ts\"; import { NotFound } from \"..\/helpers\/NotFound.ts\";  \/\/ instantiate our controller const controller = new UserController();  export function UserRoutes(router: Router) {   return router     .get(\"\/users\", async (ctx) =&gt; {       const users = await controller.getAll();        if (users) {         ctx.response.status = Status.OK;         ctx.response.body = users;        } else {         ctx.response.status = Status.NotFound;         ctx.response.body = [];       }        return;     })     .post(\"\/login\", async (ctx) =&gt; {       if (!ctx.request.hasBody) {         return BadRequest(ctx);       }       const { value } = await ctx.request.body();        \/\/ TODO generate JWT        ctx.response.status = Status.OK;       ctx.response.body = { jwt };     })     .get(\"\/user\/:id\", async (ctx) =&gt; {       if (!ctx.params.id) {         return BadRequest(ctx);       }        const user = await<\/code><\/pre>\n<\/hr>\n<\/blockquote>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-314700","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/314700","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=314700"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/314700\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=314700"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=314700"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=314700"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}