프로젝트 소개
# @querry-kit/nest
Query Kit API를 위한 통합 NestJS 헬퍼: 필드 프로젝션, Prisma 스타일 쿼리 서비스, CASL 정책, OpenAPI 데코레이터, 파이프, 페이지네이션 DTO, 객체 유틸리티.
## 🌐 Querry Kit 생태계
[Querry Kit 개요](https://querry-kit.github.io/querry-kit/)는 세 가지 핵심 패키지를 연결합니다:
- [`@querry-kit/nest`](https://github.com/querry-kit/nest)는 NestJS API 및 컨트롤러 패턴을 제공합니다.
- [`@querry-kit/nuxt`](https://github.com/querry-kit/nuxt)는 타입이 지정된 API 클라이언트와 헤드리스 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, 워크플로 구성만 포함됩니다.
패키지에 영향을 주는 변경 사항에는 changeset이 포함되어야 합니다:
```sh
pnpm changeset
```
변경 사항이 `main`에 병합되면 `changesets` 워크플로가 릴리스 PR을 생성하거나 업데이트합니다. 해당 PR에는 다음 명령으로 생성된 버전 범프와 변경 로그 업데이트가 포함됩니다:
```sh
pnpm changeset version
```
npm 게시 워크플로는 GitHub Actions OIDC를 통한 npm Trusted Publishing을 사용합니다. npm 패키지는 npm 패키지 게시 설정에서 이 저장소와 워크플로에 연결되어야 합니다:
- 저장소: `querry-kit/nest`
- 워크플로 파일: `release.yml`
- 환경: 설정되지 않음
릴리스 PR이 병합된 후 `npm publish` 워크플로가 버전/변경 로그 변경 사항에 대해 실행됩니다. 이 워크플로는 패키지 검사를 실행하고, CI에서 `dist`를 빌드하고, `@querry-kit/nest`를 npm에 게시하고, 릴리스 커밋에 `vX.Y.Z` 태그를 지정하고, GitHub Release를 생성합니다.
소비자는 npm에서 설치해야 합니다:
```sh
pnpm add @querry-kit/nest
```
## 🧩 사용법
`ResourceQuery`는 일반적인 컨트롤러 흐름을 처리합니다: 선택적 `fields` 파싱, 엔드포인트 필수 include와 클라이언트 `include` 값 병합, 선택된 관계에 대한 Prisma include 생성, `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은 선택 사항입니다. 엔드포인트가 `QueryService`를 통해 권한 인식 `where` 절을 병합해야 하는 경우에만 `ability`를 전달하고, CASL을 사용하지 않는 API에서는 생략합니다.
```ts
import { createCaslAccessibleWhere } from '@querry-kit/nest/casl';
super(prisma.customer, {
subject: 'Customer',
accessibleWhere: createCaslAccessibleWhere({ action: 'read' }),
});
```
`query`에 ability가 전달되면 서비스는 CASL where 절을 사용자 필터와 `{ AND: [accessibleWhere, parsedWhere] }`로 결합합니다.
필드 수준 응답 권한의 경우 완성된 DTO를 변경하지 않고 필터링합니다:
```ts
return filterCaslFields(dto, 'Customer', ability);
```
이 헬퍼는 기본적으로 `read` 액션을 사용합니다. 애플리케이션이 대문자 또는 enum 기반 액션을 사용하는 경우 `{ action: RoleAction.READ }`를 전달합니다. 이는 직렬화된 DTO 필드만 필터링하며, 데이터베이스 읽기를 제한하려면 `QueryService`에 ability를 계속 전달해야 합니다.
## 🎯 Fields
`fields`는 기본적으로 선택 사항입니다. 생략하면 Query Kit은 전체 DTO 응답을 반환합니다. 존재하는 경우 구문과 선택된 필드를 검증하고, 필요한 관계 include를 추가하고, 반환된 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
```
워크스페이스 빌드 허용 목록은 테스트 및 문서 도구 체인에 필요한 네이티브 스크립트(예: Parcel의 파일 감시자)를 허용합니다.
`pnpm test:coverage`는 모든 소스 파일을 수집하고, 커버리지 요약을 출력하고, HTML 및 LCOV 보고서를 `coverage/`에 작성합니다. GitHub Actions는 동일한 명령을 실행하고 보고서를 워크플로 아티팩트로 보관합니다.
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.