このプロジェクトについて

# @querry-kit/nest Query Kit API向けのNestJSヘルパーを統合したパッケージです。フィールド投影、Prismaスタイルのクエリサービス、CASLポリシー、OpenAPIデコレータ、パイプ、ページネーションDTO、オブジェクトユーティリティを提供します。 ## 🌐 Querry Kitエコシステム [Querry Kitの概要](https://querry-kit.github.io/querry-kit/)では、3つのコアパッケージを結び付けています。 - [`@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{}`は空のitemオブジェクトを生成し、`meta{page}`は要求された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), }; ``` ## 📖 ドキュメント - [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/) ## 🛠 開発 ```sh pnpm install pnpm lint pnpm check pnpm test pnpm test:coverage pnpm build ``` ワークスペースのビルド許可リストは、Parcelのファイルウォッチャーを含む、テストおよびドキュメントツールチェーンに必要なネイティブスクリプトを許可します。 `pnpm test:coverage`はすべてのソースファイルを収集し、カバレッジサマリーを出力し、HTMLおよびLCOVレポートを`coverage/`に書き込みます。GitHub Actionsは同じコマンドを実行し、レポートをワークフローアーティファクトとして保持します。