Объедините GraphQL с TypeORM в NestJS с помощью Perch Query Builder

Неограниченная глубина нормализации, аргументы, фильтрация, сортировка и разбивка на страницы без специальной логики, настраиваемой для каждой сущности ORM.

Отказ от ответственности: я являюсь автором пакета Perch Query Builder.

В этой статье предполагается, что вы имеете общее представление о NestJS, а также о том, как он реализован с помощью TypeORM и пакета NestJS GraphQL. Если вы ищете, как запустить базовый проект, взгляните на документы, размещенные по ссылкам. В этой статье также используется подход Code-First, если вы не уверены, что это значит, это — хорошее изложение преимуществ и различий по сравнению с подходом Schema-First.

Что, зачем и для кого

GraphQL быстро становится основным продуктом будущего API, он обеспечивает новый и гораздо более динамичный взгляд на то, как уровень данных ваших приложений должен использоваться и развиваться. Используя подход GraphQL-First, каждая функция вращается вокруг схемы GraphQL, что позволяет вашей команде внешнего интерфейса и вашей команде API работать независимо, зная, что эти две части будут работать вместе, когда будут готовы. Вместо простых конечных точек REST API, которые разрешают одну и ту же структуру объекта (и, возможно, просто выполняют поиск других конечных точек вместо фактических дочерних элементов), мы можем предоставить все свойства и отношения, которые нам нужны, в одном запросе.

По моему опыту работы с NestJS и TypeORM, интеграция GraphQL немного странная. Во-первых, структура и глубина запроса предоставляются вашему пользовательскому преобразователю только в полузагадочном объекте (информация @Info(): GraphQLResolveInfo), и не существует четких способов обработки запроса. выбранные атрибуты внутри запроса, что является проблемой, если мы хотим структурировать запрос TypeORM, чтобы он соответствовал требованиям глубины входящего запроса GraphQL.

Цель этого пакета — преодолеть разрыв между вашей реализацией GraphQL и TypeORM. Вместо того, чтобы писать настраиваемый распознаватель, который может работать только на nуровней, или писать собственную сортировку, фильтрацию и обработку разбиения на страницы, PerchQueryBuilder предоставляет все эти функции, не зная буквальной структуры вашей сущности, что позволяет вам легкая и простая интеграция с GraphQL. Поскольку этот пакет является просто попыткой перевести GraphQL в TypeORM, запросы обрабатываются так, как если бы они были прямым переводом свойств и имен отношений сущностей ORM, поскольку он опирается на определения TypeORM ваших сущностей. Например, если у вас есть объект с именем «Книга» с отношением «многие к одному» к объекту «Автор» с именем author, вам нужно будет указать author в качестве выбранного атрибута ( а также любое из свойств под Author) в запрос, чтобы получить его.

Этот пакет предназначен для разработчиков, которые хотят структурировать свой уровень API для извлечения и обслуживания объектов, поскольку их схема определена в ORM. Например, запрос Book с выбранным свойством title извлекает книги и их названия, запрос Author с выбранным отношением books извлекает авторов и лежащие в их основе книги и т. д. Нет вычисляемых свойств, которые назначаются с помощью триггера уровня событий или какой-либо другой формы манипулирования объектами через запрос, хотя этот пакет не добавляет никаких ограничений и не мешает этим типам операций.

Установка

Загрузите пакет Perch Query Builder из npm.

$ npm i --save perch-query-builder@latest

использование

Perch Query Builder — это пакет, который должен быть как можно более легким и ненавязчивым, это означает, что он не требует какой-либо специальной настройки или импорта в модуль. Допустим, для нашей файловой структуры у нас есть следующие преобразователи, сущности и аргументы.

+-- entities
|   +-- book.ts
|   +-- author.ts
+-- resolvers
|   +-- book-resolver.ts
|   +-- author-resolver.ts
+-- arguments
|   +-- book-args.ts
|   +-- author-args.ts
+-- app.module.ts

Это наша книга

А это наша сущность Author:

Вот наш книжный аргумент:

Наконец, в классе BookResolver мы используем Perch Query Builder:

Как видите, для преодоления разрыва между общедоступным слоем GraphQL и слоем ORM требуется только одна строка. Метод PerchQueryBuilder.find‹T› принимает GraphQLResolveInfo и репозиторий объекта и будет использовать их для построения соответствующего возвращаемого запроса. Если мы хотим запросить книги с их названиями и именами авторов, все, что нам нужно, это запрос, структурированный следующим образом:

Если бы мы хотели найти книгу с идентификатором 5 или названием «Моби Дик», мы бы структурировали его следующим образом:

Сортировка

Perch Query Builder предоставляет возможность легко сортировать наши результаты, используя заданное свойство, по возрастанию или по убыванию. Все, что нам нужно сделать, чтобы добавить эту возможность в наш запрос книг, — это добавить класс OrderByArgs в качестве еще одного аргумента в наш преобразователь.

Никаких других действий с точки зрения конфигурации не требуется, так как класс аргументов OrderByArgs присутствует только для предоставления определений этих аргументов для вашей схемы. Отсортируйте книги, возвращенные из нашего запроса Book, следующим образом:

Пагинация

На данный момент нумерация страниц проста и прямолинейна. У нас есть только возможность добавить смещение и ограничение на запрос, чтобы сегментировать ответ. В будущем я надеюсь, что разбиение на страницы на основе курсора будет доступно, как описано на веб-сайте GraphQL. Чтобы добавить возможность разбивки на страницы в наш класс распознавателя книг, нам нужно сделать то же самое, что мы сделали с функцией сортировки.

Дальнейшая настройка не требуется! Теперь у нас есть возможность добавить смещение и ограничение на количество сущностей в нашем запросе.

Окончательный запрос с использованием всех функций Perch Query Builder:

Ссылка на проект и документацию: https://github.com/wesleyyoung/perch-query-builder