{"id":360573,"date":"2024-05-21T00:55:54","date_gmt":"2024-05-21T00:55:54","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=360573"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-05-21T00:55:54","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=360573","title":{"rendered":"<span>\u041a\u0430\u043a \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439, \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 Node.js API \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Prisma, TypeGraphQL \u0438 graphql-query-purifier<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e Node.js API, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0449\u0435\u0433\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442\u0438\u043f\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439. \u042d\u0442\u043e \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Prisma, <a href=\"https:\/\/prisma.typegraphql.com\/\" rel=\"noopener noreferrer nofollow\">TypeGraphQL <\/a>\u0438 <a href=\"https:\/\/www.npmjs.com\/package\/graphql-query-purifier\" rel=\"noopener noreferrer nofollow\">graphql-query-purifier<\/a>.<\/p>\n<blockquote>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 <a href=\"https:\/\/github.com\/multipliedtwice\/graphql-query-purifier-example\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a><\/p>\n<\/blockquote>\n<h4>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Node.js \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Prisma<\/h4>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u043f\u0440\u043e\u0435\u043a\u0442 Node.js \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0439\u0442\u0435 Prisma \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"javascript\">mkdir nodejs-api &amp;&amp; cd nodejs-api npm init -y npm i --save-dev @types\/cors@2.8.16 @types\/graphql-fields@1.3.9 @types\/node@20.9.2 body-parser@1.20.2 cors@2.8.5 express@4.18.2 graphql-query-purifier prisma@5.6.0 ts-node@10.9.1 type-graphql@2.0.0-beta.1 typegraphql-prisma@0.27.1 typescript@5.2.2 npm i @apollo\/server@4.9.5 @prisma\/client@5.6.0 graphql@16.8.1 graphql-fields@2.0.3 graphql-scalars@1.22.4 reflect-metadata@0.1.13 npx tsc --init npx prisma init --datasource-provider sqlite<\/code><\/pre>\n<h4>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 Prisma<\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0441\u0445\u0435\u043c\u0443 Prisma \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438:<\/p>\n<pre><code class=\"javascript\">\/\/ schema.prisma  datasource db {   provider = \"sqlite\"   url      = \"file:.\/dev.db\" }  generator client {   provider = \"prisma-client-js\" }  generator typegraphql {   provider = \"typegraphql-prisma\"   output   = \"generated\" }  model Employee {   id           Int        @id @default(autoincrement())   name         String   departmentId Int   department   Department @relation(fields: [departmentId], references: [id])   salary       Salary?   salaryId     Int? }  model Department {   id        Int        @id @default(autoincrement())   name      String   employees Employee[] }  model Salary {   id         Int      @id @default(autoincrement())   amount     Float   employeeId Int      @unique   employee   Employee @relation(fields: [employeeId], references: [id]) }<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"javascript\">npx prisma migrate dev --name init<\/code><\/pre>\n<h4>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Apollo Server \u0441 Express<\/h4>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0439\u0442\u0435 Apollo Server \u0441 Express:<\/p>\n<pre><code class=\"javascript\">import \"reflect-metadata\"; import express from \"express\"; import { ApolloServer } from \"@apollo\/server\"; import { GraphQLQueryPurifier } from \"graphql-query-purifier\"; import { resolvers } from \"..\/prisma\/generated\"; import { PrismaClient } from \"@prisma\/client\";  import cors from \"cors\"; import path from \"path\"; import { json, urlencoded } from \"body-parser\"; import { expressMiddleware } from \"@apollo\/server\/express4\"; import { buildSchema } from \"type-graphql\";  const startServer = async () => {   const app = express();   const prisma = new PrismaClient();    app.use(cors(), json(), urlencoded({ extended: true }));    const gqlPath = path.resolve(__dirname, \"..\/frontend\");   const queryPurifier = new GraphQLQueryPurifier({     gqlPath,     allowStudio: true,     \/\/ allowAll: false,   });   app.use(queryPurifier.filter);    const server = new ApolloServer({     schema: await buildSchema({       resolvers,       validate: false,     }),   });    await server.start();    const context = expressMiddleware(server, {     context: async (_ctx) => ({       prisma,     }),   });    app.use(\"\/graphql\", context);    const PORT = process.env.PORT || 3000;   app.listen(PORT, () => {     console.log(`Server running on http:\/\/localhost:${PORT}\/graphql`);   }); };  startServer();<\/code><\/pre>\n<h4>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 API<\/h4>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c API \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e GraphQL \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<h3>\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441:<\/h3>\n<pre><code class=\"javascript\">query {   departments {     id     name     employees {       id       name     }   } }<\/code><\/pre>\n<h3>\u0417\u0430\u043f\u0440\u043e\u0441 \u043a\u0443\u0440\u0438\u043b\u044c\u0449\u0438\u043a\u0430:<\/h3>\n<pre><code class=\"javascript\">query {   departments {     id     name     employees {       id       name       salary {         amount       }     }   } }<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5db\/fca\/a57\/5dbfcaa5714fce7dbe8f803e5164022e.png\" width=\"1918\" height=\"960\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5db\/fca\/a57\/5dbfcaa5714fce7dbe8f803e5164022e.png\"\/><\/figure>\n<h4>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h4>\n<p>\u042d\u0442\u043e \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u043e\u0434 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f Node.js API \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 TypeGraphQL \u0438 Prisma. \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\n<p><strong>TypeGraphQL \u0434\u043b\u044f \u0441\u0445\u0435\u043c\u044b \u0438 \u0440\u0435\u0437\u043e\u043b\u0432\u0435\u0440\u043e\u0432<\/strong>: \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0438\u0437 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 Prisma \u0443\u0441\u043a\u043e\u0440\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 API \u0441 \u043f\u043e\u043b\u043d\u044b\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 CRUD. \u0421\u0438\u043b\u044c\u043d\u0430\u044f \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044f \u0441 TypeScript \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e API.<\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0441 graphql-query-purifier<\/strong>: \u041f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0447\u0440\u0435\u0437\u043c\u0435\u0440\u043d\u0443\u044e \u0432\u044b\u0431\u043e\u0440\u043a\u0443 \u0438 \u043d\u0435\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0434\u0430\u043d\u043d\u044b\u043c, \u0447\u0442\u043e \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e \u0434\u043b\u044f API \u0441 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u043a\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b<\/strong>: \u0421\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e API. \u042d\u0442\u043e \u0437\u0434\u043e\u0440\u043e\u0432\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u0435\u0442\u043e\u0434 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044f \u0431\u044b\u0441\u0442\u0440\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443, \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0438 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044e.<\/p>\n<p>P.S. \u0434\u043b\u044f \u0442\u0435\u0445 \u043a\u043e\u043c\u0443 \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 CRUD. \u041d\u0438\u0436\u0435 \u043d\u0430\u0431\u043e\u0440 \u0440\u0435\u0437\u043e\u043b\u0432\u0435\u0440\u043e\u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u043c, \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0435\u0437\u043e\u043b\u0432\u0435\u0440 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e72\/424\/bfd\/e72424bfd2c72aa136ea23835fe4298f.png\" width=\"1183\" height=\"882\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e72\/424\/bfd\/e72424bfd2c72aa136ea23835fe4298f.png\"\/><\/figure>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \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\/articles\/774874\/\"> https:\/\/habr.com\/ru\/articles\/774874\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e Node.js API, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0449\u0435\u0433\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442\u0438\u043f\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439. \u042d\u0442\u043e \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Prisma, <a href=\"https:\/\/prisma.typegraphql.com\/\" rel=\"noopener noreferrer nofollow\">TypeGraphQL <\/a>\u0438 <a href=\"https:\/\/www.npmjs.com\/package\/graphql-query-purifier\" rel=\"noopener noreferrer nofollow\">graphql-query-purifier<\/a>.<\/p>\n<blockquote>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 <a href=\"https:\/\/github.com\/multipliedtwice\/graphql-query-purifier-example\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a><\/p>\n<\/blockquote>\n<h4>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Node.js \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Prisma<\/h4>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u043f\u0440\u043e\u0435\u043a\u0442 Node.js \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0439\u0442\u0435 Prisma \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"javascript\">mkdir nodejs-api &amp;&amp; cd nodejs-api npm init -y npm i --save-dev @types\/cors@2.8.16 @types\/graphql-fields@1.3.9 @types\/node@20.9.2 body-parser@1.20.2 cors@2.8.5 express@4.18.2 graphql-query-purifier prisma@5.6.0 ts-node@10.9.1 type-graphql@2.0.0-beta.1 typegraphql-prisma@0.27.1 typescript@5.2.2 npm i @apollo\/server@4.9.5 @prisma\/client@5.6.0 graphql@16.8.1 graphql-fields@2.0.3 graphql-scalars@1.22.4 reflect-metadata@0.1.13 npx tsc --init npx prisma init --datasource-provider sqlite<\/code><\/pre>\n<h4>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 Prisma<\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0441\u0445\u0435\u043c\u0443 Prisma \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438:<\/p>\n<pre><code class=\"javascript\">\/\/ schema.prisma  datasource db {   provider = \"sqlite\"   url      = \"file:.\/dev.db\" }  generator client {   provider = \"prisma-client-js\" }  generator typegraphql {   provider = \"typegraphql-prisma\"   output   = \"generated\" }  model Employee {   id           Int        @id @default(autoincrement())   name         String   departmentId Int   department   Department @relation(fields: [departmentId], references: [id])   salary       Salary?   salaryId     Int? }  model Department {   id        Int        @id @default(autoincrement())   name      String   employees Employee[] }  model Salary {   id         Int      @id @default(autoincrement())   amount     Float   employeeId Int      @unique   employee   Employee @relation(fields: [employeeId], references: [id]) }<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"javascript\">npx prisma migrate dev --name init<\/code><\/pre>\n<h4>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Apollo Server \u0441 Express<\/h4>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0439\u0442\u0435 Apollo Server \u0441 Express:<\/p>\n<pre><code class=\"javascript\">import \"reflect-metadata\"; import express from \"express\"; import { ApolloServer } from \"@apollo\/server\"; import { GraphQLQueryPurifier } from \"graphql-query-purifier\"; import { resolvers } from \"..\/prisma\/generated\"; import { PrismaClient } from \"@prisma\/client\";  import cors from \"cors\"; import path from \"path\"; import { json, urlencoded } from \"body-parser\"; import { expressMiddleware } from \"@apollo\/server\/express4\"; import { buildSchema } from \"type-graphql\";  const startServer = async () => {   const app = express();   const prisma = new PrismaClient();    app.use(cors(), json(), urlencoded({ extended: true }));    const gqlPath = path.resolve(__dirname, \"..\/frontend\");   const queryPurifier = new GraphQLQueryPurifier({     gqlPath,     allowStudio: true,     \/\/ allowAll: false,   });   app.use(queryPurifier.filter);    const server = new ApolloServer({     schema: await buildSchema({       resolvers,       validate: false,     }),   });    await server.start();    const context = expressMiddleware(server, {     context: async (_ctx) => ({       prisma,     }),   });    app.use(\"\/graphql\", context);    const PORT = process.env.PORT || 3000;   app.listen(PORT, () => {     console.log(`Server running on http:\/\/localhost:${PORT}\/graphql`);   }); };  startServer();<\/code><\/pre>\n<h4>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 API<\/h4>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c API \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e GraphQL \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<h3>\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441:<\/h3>\n<pre><code class=\"javascript\">query {   departments {     id     name     employees {       id       name     }   } }<\/code><\/pre>\n<h3>\u0417\u0430\u043f\u0440\u043e\u0441 \u043a\u0443\u0440\u0438\u043b\u044c\u0449\u0438\u043a\u0430:<\/h3>\n<pre><code class=\"javascript\">query {   departments {     id     name     employees {       id       name       salary {         amount       }     }   } }<\/code><\/pre>\n<figure class=\"full-width\"><\/figure>\n<h4>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h4>\n<p>\u042d\u0442\u043e \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u043e\u0434 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f Node.js API \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 TypeGraphQL \u0438 Prisma. \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\n<p><strong>TypeGraphQL \u0434\u043b\u044f \u0441\u0445\u0435\u043c\u044b \u0438 \u0440\u0435\u0437\u043e\u043b\u0432\u0435\u0440\u043e\u0432<\/strong>: \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0438\u0437 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 Prisma \u0443\u0441\u043a\u043e\u0440\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 API \u0441 \u043f\u043e\u043b\u043d\u044b\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 CRUD. \u0421\u0438\u043b\u044c\u043d\u0430\u044f \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044f \u0441 TypeScript \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e API.<\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0441 graphql-query-purifier<\/strong>: \u041f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0447\u0440\u0435\u0437\u043c\u0435\u0440\u043d\u0443\u044e \u0432\u044b\u0431\u043e\u0440\u043a\u0443 \u0438 \u043d\u0435\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0434\u0430\u043d\u043d\u044b\u043c, \u0447\u0442\u043e \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e \u0434\u043b\u044f API \u0441 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u043a\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b<\/strong>: \u0421\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e API. \u042d\u0442\u043e \u0437\u0434\u043e\u0440\u043e\u0432\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u0435\u0442\u043e\u0434 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044f \u0431\u044b\u0441\u0442\u0440\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443, \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0438 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044e.<\/p>\n<p>P.S. \u0434\u043b\u044f \u0442\u0435\u0445 \u043a\u043e\u043c\u0443 \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 CRUD. \u041d\u0438\u0436\u0435 \u043d\u0430\u0431\u043e\u0440 \u0440\u0435\u0437\u043e\u043b\u0432\u0435\u0440\u043e\u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u043c, \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0435\u0437\u043e\u043b\u0432\u0435\u0440 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<figure class=\"full-width\"><\/figure>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \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\/articles\/774874\/\"> https:\/\/habr.com\/ru\/articles\/774874\/<\/a><br \/><\/br><\/br><\/p>\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-360573","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/360573","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=360573"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/360573\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=360573"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=360573"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=360573"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}