عن المشروع

# @querry-kit/nest أدوات NestJS الموحّدة لواجهات Query Kit البرمجية: إسقاط الحقول، وخدمات استعلام بنمط Prisma، وسياسات CASL، ومزخرفات OpenAPI، وأنابيب، وكائنات نقل البيانات للترقيم، وأدوات مساعدة للكائنات. ## 🌐 منظومة Querry Kit يربط [نظرة عامة على Querry Kit](https://querry-kit.github.io/querry-kit/) الحزم الأساسية الثلاث: - [`@querry-kit/nest`](https://github.com/querry-kit/nest) توفر واجهة NestJS وأنماط المتحكمات. - [`@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` أو يحدّث طلب سحب للإصدار. يحتوي ذلك الطلب على رفع الإصدار وتحديثات سجل التغييرات الناتجة عن: ```sh pnpm changeset version ``` يستخدم سير عمل النشر إلى npm خاصية Trusted Publishing عبر GitHub Actions OIDC. يجب ربط حزمة npm بهذا المستودع وسير العمل في إعدادات نشر حزمة npm: - المستودع: `querry-kit/nest` - ملف سير العمل: `release.yml` - البيئة: غير محددة بعد دمج طلب سحب الإصدار، يعمل سير عمل `npm publish` لتغييرات الإصدار/سجل التغييرات. يشغّل فحوصات الحزمة، ويبني `dist` في CI، وينشر `@querry-kit/nest` إلى npm، ويضع وسم `vX.Y.Z` على التزام الإصدار، وينشئ إصدار GitHub. ينبغي للمستهلكين التثبيت من npm: ```sh pnpm add @querry-kit/nest ``` ## 🧩 الاستخدام يغطي `ResourceQuery` تدفق المتحكم الشائع: تحليل `fields` الاختيارية، ودمج التضمينات المطلوبة من نقطة النهاية مع قيم `include` من العميل، وإنشاء تضمينات Prisma للعلاقات المحددة، واستدعاء `QueryService`، وتحويل النماذج إلى DTOs، وإسقاط الاستجابة. ```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` اختيارية افتراضيًا. عند حذفها، تُرجع Query Kit استجابة DTO الكاملة. عند وجودها، تتحقق من الصياغة والحقول المحددة، وتضيف تضمينات العلاقات المطلوبة، وتُسقط DTOs المُرجَعة. الأقواس الخارجية اختيارية، لذا `{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) - [الحقول](https://querry-kit.github.io/querry-kit/docs/nest/api/fields/) - [خدمة الاستعلام](https://querry-kit.github.io/querry-kit/docs/nest/api/query-service) - [DTOs والترقيم](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 الأمر نفسه ويحتفظ بالتقرير كأثر لسير العمل.