Sobre o projeto
# @querry-kit/nest
Helpers NestJS consolidados para APIs Query Kit: projeção de campos, serviços de consulta estilo Prisma, políticas CASL, decoradores OpenAPI, pipes, DTOs de paginação e utilitários de objetos.
## 🌐 Ecossistema Querry Kit
A [visão geral do Querry Kit](https://querry-kit.github.io/querry-kit/) conecta os três pacotes principais:
- [`@querry-kit/nest`](https://github.com/querry-kit/nest) fornece a API NestJS e os padrões de controller.
- [`@querry-kit/nuxt`](https://github.com/querry-kit/nuxt) fornece clientes de API tipados e primitivas de dados headless para Vue/Nuxt.
- [`@querry-kit/nuxt-ui`](https://github.com/querry-kit/nuxt-ui) fornece controles de tabela do Nuxt UI construídos sobre essas primitivas.
## 📦 Instalação
```sh
pnpm add @querry-kit/nest
pnpm add @nestjs/common @nestjs/core @nestjs/swagger class-transformer class-validator reflect-metadata
```
Para o adaptador CASL opcional:
```sh
pnpm add @casl/ability @casl/prisma
```
A versão atual do pacote é publicada no npm. O npm é o canal de distribuição principal.
As tags de release do GitHub permanecem disponíveis como alternativa:
```sh
pnpm add github:querry-kit/nest#v0.0.1
```
## 🚀 Fluxo de Release
Os releases são conduzidos por Changesets e GitHub Actions. A branch `main` não contém arquivos `dist` commitados; contém apenas o código-fonte, o README e a configuração de workflows.
Alterações visíveis no pacote devem incluir um changeset:
```sh
pnpm changeset
```
Quando alterações chegam à `main`, o workflow `changesets` cria ou atualiza um PR de release. Esse PR contém o bump de versão e as atualizações de changelog produzidas por:
```sh
pnpm changeset version
```
O workflow de publicação no npm usa npm Trusted Publishing via GitHub Actions OIDC. O pacote npm deve estar conectado a este repositório e workflow nas configurações de publicação do pacote npm:
- Repositório: `querry-kit/nest`
- Arquivo de workflow: `release.yml`
- Environment: não definido
Após o merge do PR de release, o workflow `npm publish` é executado para as alterações de versão/changelog. Ele executa verificações do pacote, faz build do `dist` na CI, publica `@querry-kit/nest` no npm, marca o commit de release como `vX.Y.Z` e cria um GitHub Release.
Consumidores devem instalar a partir do npm:
```sh
pnpm add @querry-kit/nest
```
## 🧩 Uso
`ResourceQuery` cobre o fluxo comum de controller: faz parsing do `fields` opcional, mescla includes exigidos pelo endpoint com valores de `include` do cliente, gera includes Prisma para relações selecionadas, chama um `QueryService`, mapeia models para DTOs e projeta a resposta.
```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),
});
}
```
Crie serviços de recurso com `QueryService` e um delegate compatível com 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);
}
}
```
Subpaths focados estão disponíveis para imports menores:
```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 é opcional. Passe `ability` apenas quando o endpoint deve mesclar uma cláusula `where` ciente de autorização através do `QueryService`; omita para APIs que não usam CASL.
```ts
import { createCaslAccessibleWhere } from '@querry-kit/nest/casl';
super(prisma.customer, {
subject: 'Customer',
accessibleWhere: createCaslAccessibleWhere({ action: 'read' }),
});
```
Quando uma ability é passada para `query`, o serviço combina a cláusula where do CASL com os filtros do usuário como `{ AND: [accessibleWhere, parsedWhere] }`.
Para permissões de resposta em nível de campo, filtre o DTO completo sem mutá-lo:
```ts
return filterCaslFields(dto, 'Customer', ability);
```
O helper usa a ação `read` por padrão. Passe `{ action: RoleAction.READ }` quando uma aplicação usa ações em maiúsculas ou baseadas em enum. Ele filtra apenas campos de DTO serializados; continue passando a ability para o `QueryService` para restringir também as leituras no banco de dados.
## 🎯 Fields
`fields` é opcional por padrão. Quando omitido, o Query Kit retorna a resposta DTO completa. Quando presente, valida a sintaxe e os campos selecionados, adiciona includes de relação necessários e projeta os DTOs retornados. As chaves externas são opcionais, então `{id,title}` é equivalente a `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}
```
Um valor vazio explícito (`?fields=`) ou seleção externa vazia (`?fields={}`) retorna `{}`. Seleções aninhadas vazias também são válidas: `items{}` produz objetos de item vazios, enquanto `meta{page}` mantém apenas os metadados de página solicitados. Um valor contendo apenas espaços em branco permanece inválido.
Use `prepareFieldsQuery` diretamente quando um controller precisar de orquestração customizada de serviço:
```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),
};
```
## 📖 Documentação
- [Getting Started](https://querry-kit.github.io/querry-kit/docs/nest/guide/getting-started)
- [Complete API Example](https://querry-kit.github.io/querry-kit/docs/nest/guide/example-app)
- [CRUD Controller](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)
- [DTOs and Pagination](https://querry-kit.github.io/querry-kit/docs/nest/api/dtos-pagination)
- [OpenAPI Decorators](https://querry-kit.github.io/querry-kit/docs/nest/api/openapi)
- [CASL](https://querry-kit.github.io/querry-kit/docs/nest/api/casl)
- [API Reference](https://querry-kit.github.io/querry-kit/docs/nest/api/)
## 🛠 Desenvolvimento
```sh
pnpm install
pnpm lint
pnpm check
pnpm test
pnpm test:coverage
pnpm build
```
A allowlist de build do workspace permite os scripts nativos exigidos pela toolchain de testes e documentação, incluindo o file watcher do Parcel.
`pnpm test:coverage` coleta todos os arquivos-fonte, imprime o resumo de cobertura e grava relatórios HTML e LCOV em `coverage/`. O GitHub Actions executa o mesmo comando e retém o relatório como artefato de workflow.
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.