Создание эффективного Node.js API, обеспечивающего безопасность данных и типобезопасность, может быть сложной задачей. Это руководство демонстрирует процесс с использованием Prisma, TypeGraphQL и graphql-query-purifier.
Полный пример доступен в репозитории
Настройка проекта Node.js и интеграция с Prisma
Для начала инициализируйте проект Node.js и интегрируйте Prisma для управления базой данных:
mkdir nodejs-api && 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
Определение моделей Prisma
Создайте схему Prisma для представления структуры компании:
// 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]) }
Запустите миграции:
npx prisma migrate dev --name init
Настройка Apollo Server с Express
Интегрируйте Apollo Server с Express:
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();
Тестирование API
Проверьте функциональность API с помощью GraphQL запросов:
Разрешенный запрос:
query { departments { id name employees { id name } } }
Запрос курильщика:
query { departments { id name employees { id name salary { amount } } } }

Заключение
Это руководство представляет метод создания Node.js API с использованием архитектурных решений TypeGraphQL и Prisma. Основные моменты:
TypeGraphQL для схемы и резолверов: Автоматическая генерация из моделей Prisma ускоряет создание API с полными возможностями CRUD. Сильная типизация с TypeScript повышает качество API.
Фильтрация запросов с graphql-query-purifier: Предотвращает чрезмерную выборку и неавторизованный доступ к чувствительным данным, что критично для API с генерацией кода.
Практические результаты: Сочетание этих инструментов приводит к созданию безопасного, масштабируемого API. Это здорово сокращает время разработки.
Метод предлагает эффективный подход к разработке современных веб-приложений, обеспечивая быструю разработку, безопасность и типизацию.
P.S. для тех кому кажется, что этого не будет достаточно для базового набора CRUD. Ниже набор резолверов созданный генератором, каждый резолвер поддерживает бесконечную вложенность и генерируется автоматически на каждое изменение модели данных.

