Об этом проекте
# @querry-kit/nest
Консолидированные помощники NestJS для API Query Kit: проекция полей, Prisma-подобные query-сервисы, политики CASL, декораторы OpenAPI, пайпы, DTO пагинации и утилиты объектов.
## 🌐 Экосистема Querry Kit
[Обзор Querry Kit](https://querry-kit.github.io/querry-kit/) связывает три основных пакета:
- [`@querry-kit/nest`](https://github.com/querry-kit/nest) предоставляет API NestJS и паттерны контроллеров.
- [`@querry-kit/nuxt`](https://github.com/querry-kit/nuxt) предоставляет типизированные API-клиенты и headless-примитивы данных Vue/Nuxt.
- [`@querry-kit/nuxt-ui`](https://github.com/querry-kit/nuxt-ui) предоставляет элементы управления таблицами Nuxt UI, построенные на этих примитивах.
## 📦 Установка
```sh
pnpm add @querry-kit/nest
pnpm add @nestjs/common @nestjs/core @nestjs/swagger class-transformer class-validator reflect-metadata
```
Для опционального адаптера CASL:
```sh
pnpm add @casl/ability @casl/prisma
```
Текущая версия пакета опубликована на npm. npm является основным каналом распространения.
Теги релизов GitHub остаются доступны как запасной вариант:
```sh
pnpm add github:querry-kit/nest#v0.0.1
```
## 🚀 Процесс релиза
Релизы управляются через Changesets и GitHub Actions. Ветка `main` не содержит закоммиченных файлов `dist`; она содержит только исходный код, README и конфигурацию workflow.
Изменения, видимые в пакете, должны включать changeset:
```sh
pnpm changeset
```
Когда изменения попадают в `main`, workflow `changesets` создаёт или обновляет release PR. Этот PR содержит обновление версии и изменения changelog, созданные командой:
```sh
pnpm changeset version
```
Workflow публикации в npm использует npm Trusted Publishing через GitHub Actions OIDC. Пакет npm должен быть подключён к этому репозиторию и workflow в настройках публикации пакета npm:
- Репозиторий: `querry-kit/nest`
- Файл workflow: `release.yml`
- Environment: не задан
После слияния release PR workflow `npm publish` запускается для изменений версии/changelog. Он выполняет проверки пакета, собирает `dist` в CI, публикует `@querry-kit/nest` в npm, помечает релизный коммит тегом `vX.Y.Z` и создаёт GitHub Release.
Потребителям следует устанавливать из npm:
```sh
pnpm add @querry-kit/nest
```
## 🧩 Использование
`ResourceQuery` покрывает типичный поток контроллера: парсит опциональные `fields`, объединяет обязательные для эндпоинта includes со значениями `include` от клиента, генерирует Prisma includes для выбранных связей, вызывает `QueryService`, преобразует модели в DTO и проецирует ответ.
```ts
import { Get, Query, Req } from '@nestjs/common';
import { ApiErrorResponses, ApiPaginatedResponse, ApiResourceQuery, QueryDTO, ResourceQuery } from '@querry-kit/nest';
@Get()
@ApiResourceQuery()
@ApiPaginatedResponse({ model: CustomerDTO })
@ApiErrorResponses({ badRequestDescription: 'Invalid query parameter.' })
async query(@Req() req: AuthRequest, @Query() query: QueryDTO<CustomerTypeMap>) {
return ResourceQuery.query({
service: this.customersService,
query,
schema: CustomerDTO,
ability: req.ability,
map: (customer, ability) => CustomerDTO.fromModel(customer, ability),
});
}
```
Создавайте ресурсные сервисы с `QueryService` и Prisma-совместимым делегатом:
```ts
import { Injectable } from '@nestjs/common';
import { QueryService, type BaseDelegateTypeMap } from '@querry-kit/nest';
import { Prisma, PrismaService } from '../prisma';
interface CustomerTypeMap extends BaseDelegateTypeMap {
select: Prisma.CustomerSelect;
include: Prisma.CustomerInclude;
whereInput: Prisma.CustomerWhereInput;
orderByWithRelationInput: Prisma.CustomerOrderByWithRelationInput;
whereUniqueInput: Prisma.CustomerWhereUniqueInput;
scalarFieldEnum: Prisma.CustomerScalarFieldEnum;
}
@Injectable()
export class CustomersService extends QueryService<typeof PrismaService.prototype.customer, CustomerTypeMap> {
constructor(prisma: PrismaService) {
super(prisma.customer);
}
}
```
Для меньших импортов доступны специализированные подпути:
```ts
import { createCaslAccessibleWhere, filterCaslFields } from '@querry-kit/nest/casl';
import { ApiResourceQuery } from '@querry-kit/nest/decorators';
import { Fields } from '@querry-kit/nest/fields';
import { parseObject } from '@querry-kit/nest/object';
import { QueryService } from '@querry-kit/nest/query-service';
```
## 🔐 CASL
CASL опционален. Передавайте `ability` только когда эндпоинт должен объединить `where`-условие с учётом авторизации через `QueryService`; опускайте его для API, которые не используют CASL.
```ts
import { createCaslAccessibleWhere } from '@querry-kit/nest/casl';
super(prisma.customer, {
subject: 'Customer',
accessibleWhere: createCaslAccessibleWhere({ action: 'read' }),
});
```
Когда ability передаётся в `query`, сервис объединяет CASL where-условие с пользовательскими фильтрами как `{ AND: [accessibleWhere, parsedWhere] }`.
Для разрешений на уровне полей ответа фильтруйте готовый DTO без его мутации:
```ts
return filterCaslFields(dto, 'Customer', ability);
```
Помощник по умолчанию использует действие `read`. Передавайте `{ action: RoleAction.READ }`, когда приложение использует действия в верхнем регистре или на основе enum. Он фильтрует только сериализованные поля DTO; продолжайте передавать ability в `QueryService`, чтобы также ограничивать чтение из базы данных.
## 🎯 Fields
`fields` по умолчанию опционален. Если он опущен, Query Kit возвращает полный DTO-ответ. Если он присутствует, он валидирует синтаксис и выбранные поля, добавляет необходимые includes для связей и проецирует возвращённые DTO. Внешние фигурные скобки опциональны, поэтому `{id,title}` эквивалентно `id,title`.
```txt
GET /books?fields=id,title
GET /books?fields={id,title}
GET /books?fields=items{id,title},meta{page,perPage,itemCount,pageCount}
GET /books?fields=items{},meta{page}
```
Явное пустое значение (`?fields=`) или пустая внешняя выборка (`?fields={}`) возвращает `{}`. Пустые вложенные выборки также допустимы: `items{}` создаёт пустые объекты элементов, а `meta{page}` сохраняет только запрошенные метаданные страницы. Значение, содержащее только пробелы, остаётся недопустимым.
Используйте `prepareFieldsQuery` напрямую, когда контроллеру нужна кастомная оркестрация сервиса:
```ts
import { Fields, prepareFieldsQuery } from '@querry-kit/nest/fields';
const prepared = prepareFieldsQuery({
fields: query.fields,
include: query.include,
schema: BookDTO,
requiredInclude: { author: true },
});
const { items, pageMeta } = await booksService.query({ ...query, include: prepared.include });
return {
items: Fields.project(items.map(BookDTO.fromModel), prepared.projection),
meta: Fields.project(pageMeta, prepared.metaProjection),
};
```
## 📖 Документация
- [Начало работы](https://querry-kit.github.io/querry-kit/docs/nest/guide/getting-started)
- [Полный пример API](https://querry-kit.github.io/querry-kit/docs/nest/guide/example-app)
- [CRUD-контроллер](https://querry-kit.github.io/querry-kit/docs/nest/guide/crud-controller)
- [Fields](https://querry-kit.github.io/querry-kit/docs/nest/api/fields/)
- [Query Service](https://querry-kit.github.io/querry-kit/docs/nest/api/query-service)
- [DTO и пагинация](https://querry-kit.github.io/querry-kit/docs/nest/api/dtos-pagination)
- [Декораторы OpenAPI](https://querry-kit.github.io/querry-kit/docs/nest/api/openapi)
- [CASL](https://querry-kit.github.io/querry-kit/docs/nest/api/casl)
- [Справочник API](https://querry-kit.github.io/querry-kit/docs/nest/api/)
## 🛠 Разработка
```sh
pnpm install
pnpm lint
pnpm check
pnpm test
pnpm test:coverage
pnpm build
```
Allowlist сборки workspace разрешает нативные скрипты, необходимые для тестовой и документационной цепочки инструментов, включая файловый watcher Parcel.
`pnpm test:coverage` собирает все исходные файлы, выводит сводку покрытия и записывает HTML- и LCOV-отчёты в `coverage/`. GitHub Actions запускает ту же команду и сохраняет отчёт как артефакт workflow.
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.