このプロジェクトについて
# @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は同じコマンドを実行し、レポートをワークフローアーティファクトとして保持します。
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.