دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام ذكاء بيانات Nest وNode PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام Nest و Node

بصفتك مطورًا للخلفية لـ Node.js ، فإنك توافق على أن Node.js افتراضيًا هو مجرد عظام ، ولا يضع أي افتراضات حول ما تحتاجه أثناء إنشاء التطبيق. نتيجةً لذلك ، فأنت مسؤول عن إعداد كل ما تريد استخدامه عبر التطبيق ، بما في ذلك التعامل مع التوجيه ، وإجراء مكالمات API ، وإعداد TypeScript أو Web Sockets ، أو حتى الأشياء الأساسية مثل تنظيم الكود ، وهيكل الملفات ، واصطلاحات التسمية .

يمكن أن تكون إدارة تطبيق واسع النطاق مهمة صعبة ، خاصة إذا لم يتم تصميمه بهيكل واضح وإرشادات صارمة لتنظيم الكود.

يحاول Nest.js معالجة بعض هذه المشكلات عن طريق إنشاء فكرة تجريدية حول Node.js حتى تتمكن كمطور من التركيز على مشكلة التطبيق بدلاً من تفاصيل التنفيذ الصغيرة الأخرى.

في هذا الدليل ، ستتعرف على الأساسيات الأساسية لـ Nest.js من أعلى إلى أسفل ، والتي تهدف إلى إطلاعك على السرعة حتى تتمكن من إنشاء تطبيقات Node.js على مستوى المؤسسات بمساعدة Nest.js في أي وقت من الأوقات.

كل شيء سنتعلمه من خلال هذا الدليل سيكون تدريجيًا ؛ تغطي الكثير من الأرضية حول المفاهيم التمهيدية. لتحقيق أقصى استفادة من هذا الدليل ، من المفيد كتابة التعليمات البرمجية.

دعونا نتعمق في الأمر ، أيها الناس!

كود المصدر: كالعادة ، يمكنك تفرع شفرة المصدر المستضافة على GitHub جيثب:.

ملحوظة: سنستخدم Postman لاختبار API في العرض التوضيحي الخاص بنا. يمكنك تنزيله على ملف صفحة تنزيل ساعي البريد. بدلاً من ذلك ، يمكنك ببساطة استخدام المتصفح ، سطر الأوامر curl أداة أو أي أداة أخرى قد تكون على دراية بها.

ما هو Nest.js

فكر في Nest.js كمجموعة شاملة من Node.js تلخص المهام الصعبة والأدوات والتعليمات البرمجية المعيارية ، بينما تضيف أيضًا مجموعة أدوات كاملة لتطوير تطبيقك باستخدام JavaScript و TypeScript حديثين.

يوفر Nest.js بنية تطبيقات جاهزة تسمح للمطورين والفرق بإنشاء قابلة للتطوير بدرجة عالية وقابلة للاختبار وقابلة للإختبار وقابلة للإقران بشكل غير محكم ويمكن صيانتها بسهولة ، من خلال الاستفادة من الخيارات والوحدات النمطية المتاحة والبارزة في المجتمع ، مثل تلك المتوفرة في تطبيقات Express.js. يمكنك حتى تبديل Express (الذي يستخدمه تحت الغطاء افتراضيًا) لـ Fastify ، ولكن القيام بذلك قد يعني أنك قد تحتاج إلى استخدام مكتبات مختلفة متوافقة مع Fastify في تطبيقك.

فهو يجمع بين ميزات البرمجة الوظيفية ، والبرمجة الموجهة للكائنات ، والبرمجة التفاعلية الوظيفية ، ومع أكثر من 52.4 ألف نجمة و 6.2 ألف شوكة على GitHub جيثب: وعدد التنزيلات الأسبوعي الذي يصل إلى 1,784,004،XNUMX،XNUMX ، يعد إطار عمل Node.js التدريجي وسيلة شائعة لتصميم تطبيقات من جانب الخادم فعالة وقابلة للتطوير على مستوى المؤسسات.

ميزات Nest.js

فيما يلي أسباب نمو Nest.js ليصبح إطار عمل Node.js شائعًا:

  1. تم إنشاء Nest.js لمساعدة المطورين على بناء تطبيقات متجانسة وخدمات مصغرة أيضًا.
  2. على الرغم من قوتها ، إلا أنها صديقة للمطورين للعمل معها ؛ سهل الاستخدام وسريع التعلم وسهل التطبيق.
  3. إنها تستفيد من TypeScript (مجموعة شاملة من JavaScript) خارج الصندوق وتوفر مجالًا للمطورين لكتابة تعليمات برمجية قابلة للصيانة خالية من أخطاء وقت التشغيل.
  4. يمتلك واجهة سطر الأوامر التي تساعد على زيادة إنتاجية المطورين وسهولة التطوير.
  5. عند الإنشاء باستخدام Nest.js ، يتم تحسين عمليات التطوير ويتم توفير الوقت سواء كنت تقوم بإقلاع منتج قابل للتطبيق أو تعمل على تطبيق لأن Nest يأتي بهيكل مجلد مشروع مذهل بشكل افتراضي.
  6. وهو يدعم مجموعة متنوعة من الوحدات النمطية الخاصة بـ Nest والتي تساعد في تكامل المفاهيم والتقنيات الشائعة بما في ذلك TypeORM و GraphQL والتسجيل والتحقق من الصحة والنمس ومقابس الويب والتخزين المؤقت وما إلى ذلك.
  7. يمكن لـ Nest.js التباهي باحتوائه على بعض من أفضل الوثائق لأي إطار عمل موجود. توثيقه شامل ، وسهل الفهم ، ومفيد في توفير وقت التصحيح ، حيث يأتي دون عناء عندما تكون هناك حاجة لحل مشكلة ما.
  8. يتكامل Nest.js مع Jest ، مما يجعل من السهل كتابة اختبارات الوحدة على تطبيقاتك.
  9. تم تصميمه لتطبيقات المؤسسات الصغيرة والكبيرة الحجم.

إنشاء مشروع Nest.js

لبدء استخدام Nest.js على جهازك المحلي ، عليك أولاً تثبيت واجهة سطر أوامر Nest (CLI) ، والتي من شأنها أن تساعد في سقالة مجلد مشروع Nest.js جديد وملء المجلد بالملفات الأساسية والوحدات اللازمة لـ تطبيق Nest.js.

قم بتشغيل الأمر التالي لتثبيت واجهة سطر أوامر Nest.js:

$ npm i -g @nestjs/cli
// Or
$ yarn global add @nestjs/cli
// Or
$ pnpm add -g @nestjs/cli

بمجرد تثبيت Nest.js CLI عالميًا على جهازك المحلي بنجاح ، يمكنك تشغيل nest في سطر الأوامر لرؤية الأوامر المختلفة التي يمكننا الاستفادة منها:

$ nest

نتائج البحث في

Usage: nest  [options]

Options:
  -v, --version                                   Output the current version.
  -h, --help                                      Output usage information.

Commands:
  new|n [options] [name]                          Generate Nest application.
  build [options] [app]                           Build Nest application.
  start [options] [app]                           Run Nest application.
  info|i                                          Display Nest project details.
  add [options]                          Adds support for an external library to your project.
  generate|g [options]  [name] [path]  Generate a Nest element.
    Schematics available on @nestjs/schematics collection:
      ┌───────────────┬─────────────┬──────────────────────────────────────────────┐
      │ name          │ alias       │ description                                  │
      │ application   │ application │ Generate a new application workspace         │
      │ class         │ cl          │ Generate a new class                         │
      │ configuration │ config      │ Generate a CLI configuration file            │
      │ controller    │ co          │ Generate a controller declaration            │
      │ decorator     │ d           │ Generate a custom decorator                  │
      │ filter        │ f           │ Generate a filter declaration                │
      │ gateway       │ ga          │ Generate a gateway declaration               │
      │ guard         │ gu          │ Generate a guard declaration                 │
      │ interceptor   │ itc         │ Generate an interceptor declaration          │
      │ interface     │ itf         │ Generate an interface                        │
      │ middleware    │ mi          │ Generate a middleware declaration            │
      │ module        │ mo          │ Generate a module declaration                │
      │ pipe          │ pi          │ Generate a pipe declaration                  │
      │ provider      │ pr          │ Generate a provider declaration              │
      │ resolver      │ r           │ Generate a GraphQL resolver declaration      │
      │ service       │ s           │ Generate a service declaration               │
      │ library       │ lib         │ Generate a new library within a monorepo     │
      │ sub-app       │ app         │ Generate a new application within a monorepo │
      │ resource      │ res         │ Generate a new CRUD resource                 │
      └───────────────┴─────────────┴──────────────────────────────────────────────┘

هنا ، تظهر لك كيفية الاستفادة من الأوامر ، ويمكنك الآن النقر على ملف new|n [options] [name] أمر لإنشاء مشروع Nest.js الأول الخاص بك:

$ nest new getting-started-with-nestjs
// Or
$ nest n getting-started-with-nestjs

بعد ذلك ، سيتم سؤالك عن مدير الحزم الذي ترغب في استخدامه:

? Which package manager would you ❤️ to use? (Use arrow keys)
  npm
  yarn
> pnpm

لا تتردد في اختيار مدير الحزم الذي تختاره ، سأذهب معه pnpm. هذا لأنه أكثر كفاءة وأسرع بثلاث مرات من NPM ، ومع نظام ذاكرة التخزين المؤقت السريع ، يعد PNPM أيضًا أسرع من Yarn.

بعد اختيار مدير الحزم ، تستمر عملية التثبيت ، ثم يتم إنشاء تطبيق Nest.js.

الآن انت تستطيع cd في المشروع الذي تم إنشاؤه حديثًا ، وافتحه بمحرر من اختيارك:

$ cd getting-started-with-nestjs

مع إنشاء المشروع الآن ، يمكننا تشغيله بأي من الأمرين التاليين:

$ npm run start
// Or
$ yarn start
// Or
$ pnpm run start

إذا ألقيت نظرة على package.json ملف ، ستلاحظ في مقطع البرنامج النصي ، قيمة pnpm run start is nest start:


    
"start": "nest start",

هذا يعني أنه يمكنك أيضًا تشغيل تطبيق Nest.js من خلال تشغيل:

$ nest start

نظرة على هيكل مشروع Nest.js

دعونا نلقي نظرة فاحصة على كيفية تنظيم تطبيق Nest:

/package.json

package.json الملف هو قلب Node.js ومن خلال extenssion ، مشروع Nest.js. يحتوي على جميع البيانات الوصفية حول المشروع ويحدد الخصائص الوظيفية المختلفة للمشروع اللازمة لتثبيت تبعيات التطبيق أو تشغيل البرامج النصية للمشروع.

لقد رأينا بالفعل قدرة start النصي.

start:dev يتيح ملف التعريف إمكانية مشاهدة التغييرات في التطبيق وإعادة تحميله تلقائيًا ، دون الحاجة إلى إيقاف التطبيق وإعادة تشغيله - وهو مخصص للتطوير. ال start:prod يكون البرنامج النصي مفيدًا عندما تريد اختبار ما إذا كان تطبيقك جاهزًا للإنتاج وكذلك عند نشره في الإنتاج ، جنبًا إلى جنب مع البرامج النصية الأخرى لاختبار تطبيق Nest.js.

@nestjs/platform-express يعرّف express على أنه خادم HTTP الافتراضي في تطبيق Nest.

/tsconfig.json

tsconfig.json الملف عبارة عن ملف مكتوب بلغة JSON (JavaScript Object Notation) يحدد الخيارات المتعلقة بـ TypeScript المطلوبة لتجميع تطبيق Nest.

/nest-cli.json

يتضمن هذا البيانات الوصفية اللازمة لإنشاء تطبيقات Nest أو تنظيمها أو نشرها.

/test

يحتوي هذا الدليل على جميع الملفات المطلوبة لتشغيل اختبارات Nest. يستخدم Nest إطار عمل Jest للاختبار باستخدام تكوين Jest في ملف jest-e2e.json ملف.

/src

src الدليل هو المجلد الرئيسي لجوهر مشروع نيست. يحمل main.ts الملف وهو الملف الذي يبدأ منه تطبيق Nest. وظيفة main.ts يتم تحميل الملف AppModule التي تم استيرادها من /src/app.module.ts.

لاحقًا في هذا الدليل ، سنتعرف على الوحدات النمطية ؛ أحد المكونات الرئيسية لتطبيق Nest.js.

AppModule هي فئة تم إنشاؤها كوحدة نمطية باستخدام امتداد @Module مصمم. في ال app.module.ts ملف، AppService تبدأ من ./app.service و AppController تبدأ من ./app.controller يتم استيرادها أيضًا.

AppController هي أيضًا فئة تم إنشاؤها باستخدام الامتداد @Controller الديكور ، في حين أن AppService هي فئة تم إنشاؤها باستخدام الامتداد @Injectable حاشية. ملاحظة.

الشيء الرائع في Nest هو أنه يحتوي على عدد قليل جدًا من المصممين داخل تلك البيانات الوصفية التي تضيف البيانات الوصفية إلى أي فئة وأن البيانات الوصفية تحدد الغرض من هذه الفئة ، مثل:

  • @Controller()يحول فئة إلى وحدة تحكم.
  • @Module() يحول الفصل إلى وحدة نمطية.
  • @Injectable() يحول فئة إلى مزود.

أيضا في src الدليل هو app.controller.spec.ts ملف ، وهو ملف اختبار لوحدات التحكم.

يمكننا تشغيل التطبيق باستخدام nest start.

يبدأ التطبيق في http://localhost:3000 على متصفحك:

دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام ذكاء بيانات Nest وNode PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

يمكننا تغيير المحتوى الذي يظهر في http://localhost:3000، من خلال التوجه إلى app.service.ts ملف ، حيث تم تعريف موفر مسار الفهرس.

اللبنات الأساسية لتطبيق Nest.js

هناك ثلاثة مكونات رئيسية لتطبيق Nest.js:

  1. الوحدات
  2. التحكم
  3. مقدمي

عند التعرف على اللبنات الأساسية لتطبيق Nest ، دعونا أولاً نقوم بتنظيف مشروع Nest ، عن طريق حذف ملف app.controller.spec.ts, ./app.service, app.module.tsو ./app.controller الملفات. مغادرة فقط main.ts، لمحاكاة دورة حياة التطوير من الصفر.

في هذه المرحلة ، عندما نزيل ملف AppModule ملف من main.ts، تتم مطالبتنا بعدم تقديم وسيطة لـ "وحدة نمطية".

لتوضيح اللبنات الأساسية لتطبيق Nest ، سنلقي نظرة على تنفيذ بسيط لملف تعريف المستخدم ، من خلال إنشاء واجهة برمجة تطبيقات REST للتعامل مع عمليات CRUD على أحد العناصر.

الوحدات

في مجلة src مجلد إنشاء ملف app.module.ts ملف ، ثم أنشئ ملف AppModule الدرجة التي نصدرها.

بعد ذلك ، قم باستيراد ملف AppModule فئة في main.ts، و اهرب nest start.

انتقل إلى http://localhost:3000 في متصفحك وستتلقى خطأ 404:

دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام ذكاء بيانات Nest وNode PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

هذا لأننا لم نحدد بعد مسارًا لعنوان URL الأساسي لتطبيق Nest.

مرة أخرى في app.module.ts، لدينا ال AppModule الفئة التي لدينا ليست وحدة Nest بعد. لجعلها وحدة Nest ، نضيف ملف @Module() الديكور الذي يتم استيراده من @nestjs/commonثم نمرر كائنًا فارغًا.



import { Module } from '@nestjs/common';
@Module({})

export class AppModule {}

الآن ، لدينا وحدة Nest.js!

ملحوظة: الوحدة النمطية هي فئة تم وضع تعليقات توضيحية عليها بامتداد @Module() مصمم.

يحتوي كل تطبيق من تطبيقات Nest على وحدة جذرية ، تعمل كنقطة دخول لحل بنية تطبيق Nest وعلاقاته.

يوصى بشدة باستخدام وحدات متعددة لتنظيم مكونات التطبيق الخاص بك.

@Module() يتيح برنامج decorator للمطورين إمكانية تحديد البيانات الوصفية لفصل ما في تطبيق Nest.

في حالة وجود وحدات متعددة ، مثل وحدة المستخدمين ، ووحدة الطلبات ، ووحدة الدردشة ، وما إلى ذلك ، فإن app.module.ts يجب استخدامه لتسجيل جميع الوحدات الأخرى لتطبيق Nest.

إنشاء طرق تحكم

هناك حاجة إلى وحدات التحكم لإنشاء المسارات في تطبيقات Nest. الغرض من المتحكم هو تلقي طلبات محددة لتطبيق Nest ؛ التحكم في دورة الطلب والاستجابة للطرق المختلفة داخل التطبيق.

عندما يتم إجراء طلب HTTP من العميل إلى تطبيق Nest ، فإن المسار الذي يتطابق مع المسار الذي يتم فيه تقديم الطلب يعالج الطلب ويعيد الاستجابة المناسبة.

لإنشاء وحدة تحكم في تطبيق Nest ، يتعين علينا الاستفادة من @Controller() مصمم.

في مجلة src الدليل ، قم بإنشاء ملف جديد app.contoller.ts، وهنا يمكننا تحديد وحدة تحكم Nest:

import { Controller } from '@nestjs/common';

@Controller({})

export class AppController {}

هذا هو! لدينا وحدة تحكم لطيفة جدًا ، ولكن لإنشاء مسار جديد ، نحتاج أولاً إلى إعلام تطبيق Nest الخاص بنا بوحدة التحكم التي تم إنشاؤها.

لتحقيق ذلك ، نتأكد من الاستيراد AppController في app.module.ts ، وحدد معلومات حول وحدات التحكم في @Module() مصمم - كمجموعة من وحدات التحكم:



import { Module } from '@nestjs/common';
import { AppController } from './app.controller';

@Module({
  controllers: [AppController],
})

export class AppModule {}

معالجة طلبات GET

ثم نحدد بسيط getUser() الطريق (مع @Get() مصمم للتعامل مع طلبات HTTP GET إلى مسار محدد) ليكون بمثابة المسار الأساسي ، ويمكننا الوصول إليه على المتصفح في https://localhost:3000:



import { Controller, Get } from '@nestjs/common';

@Controller({})

export class AppController {
  @Get()
  getUser() {
    return 'I am a great person';
  }
}

وينتج عنه:

دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام ذكاء بيانات Nest وNode PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

حسنًا ، نحن هنا نعيد سلسلة فقط ، لكن ماذا لو أردنا إرجاع كائن؟ بدلاً من السلسلة النصية ، يمكننا تحديد كائن:



import { Controller, Get } from '@nestjs/common';

@Controller({})

export class AppController {
  @Get()
  getUser() {
    return { name: 'Uchechukwu Azubuko', country: 'Nigeria' };
  }
}

انتقل إلى http://localhost:3000 في متصفحك وسترى الكائن:

دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام ذكاء بيانات Nest وNode PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

بعيدًا عن المسار الأساسي ، ماذا عن إنشاء مسار مشابه لـ http://localhost:3000/user لجلب جميع المستخدمين؟

يمكننا إنشاء وحدة تحكم للتعامل مع مثل هذا الطريق بطريقتين.

تتمثل إحدى الطرق في تحديد طريقة جديدة ، باستخدام امتداد @Get() مصمم / معالج.

import { Controller, Get } from '@nestjs/common';

@Controller({})

export class AppController {
  @Get()
  getUser() {
    return { name: 'Uchechukwu Azubuko', country: 'Nigeria' };
  }
}

يوفر Nest.js أدوات تزيين أو معالجات لجميع طرق HTTP المتنوعة بما في ذلك @Get(), @Post(), @Put(), @Delete(), @Patch(), @Options()و @Head().

@All() يحدد decorator نقطة نهاية تتعامل مع جميع الطرق المختلفة.

التعامل مع طلبات POST

يمكننا أيضًا تحديد طلبات POST لتخزين البيانات في قاعدة البيانات ، باستخدام امتداد @Post() مصمم:

import { Controller, Post } from '@nestjs/common';

@Controller({})
export class AppController {
  @Post()
  store() {
    return 'Post request successful';
  }
}

بعد ذلك ، نختبر طلب POST باستخدام Postman ونلاحظ أنه تم إرجاع السلسلة بنجاح كما تم تعريفها.

دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام ذكاء بيانات Nest وNode PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

قد تسأل ، ماذا لو كنت أرغب أيضًا في القيام بأكثر من إعادة البيانات؟ ربما لإرسال البيانات.

لذلك ، تحتاج إلى حقن البيانات داخل طريقة المسار ، كما هو موضح:

import { Controller, Post, Req } from '@nestjs/common';
import { Request } from 'express';

@Controller({})
export class AppController {
  @Post()
  store(@Req() req: Request) {
    return req.body;
  }
}

الآن ، عندما نختبر طلب POST مع Postman ، يمكننا عرض البيانات التي يتم إرسالها. في هذه الحالة ، يكون مجرد كائن فارغ:

تحقق من دليلنا العملي العملي لتعلم Git ، مع أفضل الممارسات ، والمعايير المقبولة في الصناعة ، وورقة الغش المضمنة. توقف عن أوامر Googling Git وفي الواقع تعلم ذلك!

دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام ذكاء بيانات Nest وNode PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

التوجيه الديناميكي مع معلمات المسار

افترض أنك تريد قبول البيانات الديناميكية كجزء من الطلب. أولاً ، نحتاج إلى تحديد الرمز المميز في مسار المسار ، من أجل ملاحظة الموضع الديناميكي على المسار / عنوان URL ، ثم استخدام @Param() مصمم ، يمكن الوصول إلى معلمة المسار على النحو التالي:

import { Controller, Get, Param } from '@nestjs/common';

@Controller({})
export class AppController {
  @Get('/:userId')
  getUser(@Param() userId: number) {
    return userId;
  }
}

userId تم إرجاعه بنجاح:

دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام ذكاء بيانات Nest وNode PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

معالجة الطلبات غير المتزامنة

يمكن لـ Nest.js التعامل مع الطلبات غير المتزامنة التي ترجع الوعد باستخدام طرق مختلفة:

import { Controller, Get} from '@nestjs/common';

@Controller({})
export class AppController {
  @Get()
  async findAll(): Promise {
    return [];
  }
}

في النهج أعلاه ، يتم التعامل مع عدم التزامن باستخدام async كلمة رئيسية. هناك طريقة أخرى تتمثل في إعادة تدفقات RxJS التي يمكن ملاحظتها:

import { Controller, Get} from '@nestjs/common';

@Controller({})
export class AppController {
  @Get()
  findAll(): Observable {
    return of([]);
  }
}

هنا ، سيشترك Nest.js في المصدر تحت الغطاء ، وعندما يكتمل البث ، سيأخذ آخر قيمة منبعثة تلقائيًا.

معالجة عمليات إعادة التوجيه في Nest

@Redirect() يستخدم decorator لإعادة توجيه الرد إلى عنوان URL مختلف. ال @Redirect() يقبل decorator وسيطتين - عنوان URL المراد إعادة التوجيه إليه ورمز الحالة عند إعادة التوجيه ، وكلاهما اختياري:

import { Controller, Get} from '@nestjs/common';

@Controller({})
export class AppController {
  @Get()
  @Redirect('https://www.ucheazubuko.com', 302)
  getSite() {
    return { url: 'https://stackabuse.com' };
  }
}

عودة رمز الحالة

لإرجاع رمز الحالة لأي طلب تمت معالجته على خادم Nest.js ، فإن ملف @HttpCode(…) يأتي بسهولة.

في Nest ، رمز الحالة الافتراضي لطلبات GET هو 200 ، وطلب POST هو 201 ، وطلب الخطأ هو 304

يمكن تحديد رمز الحالة لطلب الخادم كما هو موضح أدناه:

import { Controller, Post, HttpCode } from '@nestjs/common';

@Controller({})
export class AppController {
  @Post()
  @HttpCode(204)
  create() {
    return 'This action adds a new user to the app.';
  }
}

معالجة طلبات الحذف

على غرار إجراء طلب POST ، يمكن معالجة طلب الحذف على النحو التالي:

import { Controller, Delete, Param } from '@nestjs/common';

@Controller({})
export class AppController {
  @Delete('/:userId')
  delete(@Param() params: { userId: number }) {
    return params;
  }
}

معالجة طلبات التحديث

يمكن معالجة طلب تحديث بيانات محددة على الخادم باستخدام @Patch() مصمم:

import { Controller, Patch, Req} from '@nestjs/common';
import { Request } from 'express';

@Controller({})
export class AppController {
  @Patch('/:userId')
  update(@Req() req: Request) {
    return req.body;
  }
}

الآن بعد أن رأينا طرقًا مختلفة لتحديد وحدات التحكم النموذجية التي غالبًا ما نمتلكها على خادم قوي ، من المهم ملاحظة أن وحدة التحكم يجب أن تكون ضعيفة ونظيفة ومحددة لكل حالة استخدام ، بحيث إذا كان هناك وحدة تحكم أخرى لتحديد user مسارات ، ثم يجب إنشاء دليل منفصل وتخصيصه للتعامل مع نفس الشيء - بعيدًا عن ملف AppController.

ثم في user.controller.ts، يمكننا تكوين جميع معالجات المسار الموجودة هنا لتكون مسبوقة بـ /user/ عن طريق كتابة الكود كما هو موضح أدناه:



import { Controller, Get } from '@nestjs/common';

@Controller('/user')
export class UserController {
  @Get()
  getUser() {
    return 'I am from the user controller';
  }
}

بعد ذلك ، قم بالتسجيل UserController في مصفوفات وحدات التحكم في app.modules.ts:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { UserController } from './controllers/user/user.controller';

@Module({
  controllers: [AppController, UserController],
})

export class AppModule {}

عندما ننتقل إلى https:localhost:3000/user، يعود بنجاح:

دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام ذكاء بيانات Nest وNode PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

للحفاظ على مجلد المشروع أكثر إتقانًا مما هو عليه الآن ، يمكننا تحديد ملف user.module.ts ملف حيث سنحدد ملف UserController:

import { Module } from '@nestjs/common';
import { UserController } from './user.controller';

@Module({
  controllers: [UserController],
})

export class UserModule {}

ثم قم بالاستيراد UserModule إلى app.module.ts:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { UserModule } from './user/user.module';

@Module({
  controllers: [AppController],
  imports: [UserModule],
})

export class AppModule {}

مع هذا ، سنتمكن من الحصول على نفس التأثير كما في السابق.

ملحوظة: يجعل Nest من السهل (g) تنشيط (mo) dules و (co) ntrollers باستخدام nest g mo و nest g co أوامر. وحدات محددة ، مثل user يمكن أيضًا إنشاء الوحدة النمطية ووحدات التحكم بسرعة باستخدام Nest CLI ، عن طريق تشغيل الأوامر: nest g mo user - لإنشاء وحدة مستخدم ، و nest g co user - لإنشاء وحدة تحكم المستخدم.

مقدمي

يجب أن يتم التعامل مع جميع عمليات جلب البيانات من قاعدة البيانات من قبل مقدمي الخدمات بدلاً من وحدات التحكم ، لإنشاء طبقة من التجريد بين الكود الذي يواجه المستخدم والرمز الذي يتفاعل مع البيانات التي يحتمل أن تكون حساسة. بين هذه الطبقات - يمكن إعداد التحقق لضمان المعالجة المناسبة لقاعدة البيانات. باستخدام Nest CLI ، يمكننا إنشاء مقدمي الخدمات من خلال إنشاء الخدمات:

$ nest g s user

هذا يخلق UserService حيث نحدد كل منطق الأعمال لـ UserController، بحيث UserController يعالج الطلبات والردود فقط. في user.service.ts، نرى أن @Injectable() يستخدم مصمم الديكور لتعريف الطبقة. في Nest ، يتم استخدام ملف @Injectable() decorator هو تحويل الخدمات أو المستودعات أو فئة المساعدين إلى مزود.

يتم حقن الموفرين في فصل دراسي من خلال مُنشئه. دعنا نلقي نظرة فاحصة على مثال.

في وقت سابق ، في user.controller.ts، لقد حددنا منطق الأعمال للحصول على كائن المستخدم ، ولكن الآن ، يجب أن نحدد نفس الشيء في UserService:



import { Controller, Injectable } from '@nestjs/common';

@Controller({})

export class AppController {
  @Injectable()
  get() {
    return { name: 'Uchechukwu Azubuko', country: 'Nigeria'; };
  }
}

التالي ، في user.controller.ts ملف ، دعونا نحدد منشئ في UserController فصل. في هذا المنشئ ، نقدم ملف userService، وهو نوع من ملفات UserService فصل. من خلال هذا الخصوصية ، يمكننا الاستفادة من منطق الأعمال الذي حددناه سابقًا لجلب المستخدمين:



import { Controller, Get } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('/user')
export class UserController {
  constructor(private userService: UserService) {}
  @Get()
  getUser() {
    return this.userService.get();
  }
}

وهكذا، فإن UserController فئة ، الآن يعتمد على UserService فئة في مفهوم يعرف باسم
حقن التبعية.

بنفس الطريقة ، المنطق في كليهما user.controller.ts و user.service.ts يتم تحديث الملفات وفقًا لذلك:



import {
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Req,
} from '@nestjs/common';
import { Request } from 'express';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private userService: UserService) {}
  @Get()
  getUsers() {
    return this.userService.get();
  }
  @Get('/:userId')
  getUser(@Param() param: { userId: number }) {
    return this.userService.getUser(param);
  }
  @Post()
  store(@Req() req: Request) {
    return this.userService.create(req);
  }
  @Patch('/:userId')
  update(@Req() req: Request, @Param() param: { userId: number }) {
    return this.userService.update(req, param);
  }
  @Delete()
  delete(@Param() param: { userId: number }) {
    return this.userService.delete(param);
  }
}


import { Injectable } from '@nestjs/common';
import { Request } from 'express';

@Injectable()
export class UserService {
  get() {
    return { name: 'Uchechukwu Azubuko', country: 'Nigeria' };
  }
  getUser(param: { userId: number }) {
    return param;
  }
  create(req: Request) {
    return req.body;
  }
  update(req: Request, param: { userId: number }) {
    return { body: req.body, param };
  }
  delete(param: { userId: number }) {
    return param;
  }
}

الآن ، دعنا نتحقق من أن نقاط النهاية تعمل كما ينبغي ، باستخدام Postman.

إزالة الغموض عن حقن التبعية في Nest.js

عند إنشاء مكونات أصغر لتطبيق ما ، مثل فئة أو وحدة نمطية ، قد يعتمد الفصل الدراسي الخاص بك على فئة أخرى أو وظيفة وحدة نمطية أخرى ، على سبيل المثال ، الحاجة إلى الاستفادة من خدمة HTTP التي توفرها فئة مختلفة لإجراء مكالمات API ، أو طبقات الخدمة التي تتفاعل مع طبقة الثبات.

يمكن توفير التبعيات داخل وحدات التحكم من خلال حقن التبعية.

حقن التبعية هو مفهوم ونمط برمجة يعبران عن كيفية تسليم أجزاء من التطبيق إلى أجزاء أخرى من التطبيق تتطلبها ، بطريقة توفر تماسكًا عاليًا ولكن اقترانًا سائبًا.

يدعم Nest إدخال التبعية ويمكنك استخدامه في تطبيقات Nest لتحسين نمطية مشروعك.

يتم تصوير التوضيح العملي على النحو التالي:

لنفترض أن الفئة A تستخدم بعض وظائف الفئة B. ثم يقال إن الفئة A تعتمد على الفئة B. وبالتالي ، من أجل استخدام الفئة B في الفئة A ، نحتاج إلى إنشاء مثيل للفئة B أولاً (أي إنشاء كائن الفئة ب): const b = new B ().
يُعرف نقل مهمة إنشاء مثيل لفئة إلى فئة أخرى واستخدام التبعية مباشرةً في الفئة التي يتم توفيرها لـ (مكون الحاقن) باسم حقن التبعية.

المشورة: يُعد حقن التبعية ، أو DI ، أحد المفاهيم الأساسية في أطر عمل مثل Spring Boot و Nest.js و Angular.js ، إذا كنت ترغب في قراءة المزيد عنها ، يمكنك التحقق من التوثيق الزاوي الرسمي.

عادةً ، يجب أن تركز الفئة فقط على أداء وظائفها بدلاً من استخدامها لإنشاء كائنات مختلفة قد تتطلبها أم لا.

فوائد حقن التبعية.

  1. يساعد في اختبار الوحدة.
  2. مع حقن التبعية ، يتم تقليل الشفرة المعيارية ، حيث يتم تهيئة التبعيات بواسطة مكون الحاقن.
  3. تصبح عملية تمديد التطبيق أسهل.
  4. يساعد حقن التبعية على تمكين الاقتران السائب.

استكشاف حمولات الطلب

تذكر أنه في معالجات الطلبات المختلفة مثل POST و PATCH ، تمكنا من الاستفادة من الطلب الذي أرسله الخادم باستخدام @Req() مصمم. ومع ذلك ، هناك ما هو أكثر من ذلك.

بدلاً من استرداد كائن الطلب بالكامل ، يمكننا فقط النقر على أجزاء معينة من كائن الطلب التي نحتاجها.
وبالتالي ، يوفر Nest أدوات تزيين متنوعة يمكن استخدامها مع معالجات توجيه HTTP للوصول إلى كائنات Express of Fastify:

ديكورات العش Fastify أو Express الذي يتم الوصول إليه
"Request () ،Req ()` مطلوب
"Response () ،Res ()` `re 's`
Next () ` "التالي"
Session () `` "جلسة طلب"
Param (param ؟: string) ` `req.params` /` req.params [param] `
Body (param ؟: string) ` `req.body` /` req.body [param] `
Query (param ؟: string) ` `req.query` /` req.query [param] `
Headers (param ؟: string) ` `req.headers` /` req.headers [param] `
Ip () ` `req.ip`
HostParam () ' "مطلوب المضيفين"

مثال نموذجي سيكون استبدال @Req() الذي استخدمناه سابقًا للوصول إلى جسد النتيجة ، مع @Body() والتي يمكن أن تمنحنا بالفعل وصولاً مباشرًا إلى نص الطلب دون حفر:



@Post()
store(@Body() body: any) {
  return this.userService.create(body);
}

@Patch('/:userId')
update(@Body() body: any, @Param() param: { userId: number }) {
  return this.userService.update(body, param);
}


create(body: any) {
  return body;
}

update(body: any, param: { userId: number }) {
  return { body: body, param };
}

في بعض الحالات ، قد ترغب فقط في استرداد خصائص معينة لحمولة الطلب. في هذه الحالة ، يجب عليك تحديد مخطط كائن نقل البيانات (DTO). مخطط نقل البيانات هو كائن يحدد نسخة من الكائن الذي يتم استرداده ، ولكنه يستخدم بشكل أساسي لنقل البيانات بين الكائن الذي من المفترض حفظه أو استرداده ، وطبقة الثبات. عادةً ، نظرًا لأن هذه العملية أكثر عرضة للهجمات - لا يحتوي DTO على العديد من نقاط البيانات الحساسة. تتيح لك هذه الخاصية أيضًا استرداد حقول معينة فقط من الكائن.

في Nest ، يوصى باستخدام الفئات لتحديد كائن نقل البيانات ، حيث يتم الاحتفاظ بقيمة الفئات أثناء التجميع.

لنفترض أن نص الطلب يحتوي على رمز مميز ، ولا تريد استرداد هذه البيانات أو تحديثها ، فيمكن تحديد DTO كما هو موضح أدناه:



@Patch('/:userId')
update(
  @Body() updateUserDto: { name: string; email: string },
  @Param() param: { userId: number },
) {
  return this.userService.update(updateUserDto, param);
}


update(
  updateUserDto: { name: string; email: string },
  param: { userId: number },
) {
  return { body: updateUserDto, param };
}

ومع ذلك ، ستلاحظ أننا حددنا نوع updateUserDto مرتين؛ في user.service.ts وفي user.controller.ts، لكننا نحتاج إلى الاحتفاظ برموزنا جافة (لا تكرر نفسك) حتى لا نكرر أنفسنا حول قاعدة التعليمات البرمجية.

لهذا ، في مجلد جديد /user/dto في ال /user الدليل ، نحتاج إلى إنشاء ملف /update-user.dto.ts مع الالجائزة .dto.ts التمديد حيث نقوم بتعريف وتصدير ملف UpdateUserDto فئة للاستخدام في user.service.ts و user.controller.ts الملفات:



export class UpdateUserDto {
  name: string;
  email: string;
}

...
import { UpdateUserDto } from './dto/update-user.dto';

@Patch('/:userId')
update(
  @Body() updateUserDto: UpdateUserDto,
  @Param() param: { userId: number },
) {
  return this.userService.update(updateUserDto, param);
}

...
import { UpdateUserDto } from './dto/update-user.dto';

update(updateUserDto: UpdateUserDto, param: { userId: number }) {
  return { body: updateUserDto, param };
}

الأنابيب والتحقق من الصحة

افترض أن هناك حاجة للتحقق من صحة البيانات التي تم الحصول عليها عند تقديم طلب عبر الخادم.

في Nest ، يمكننا اختبار صحة أي بيانات تدخل إلى التطبيق أو تخرج منه باستخدام الأنابيب التي تثبت تبعيتين - class-validator و class-transformer.

الأنبوب هو فئة يتم تعريفها باستخدام @Injectable() decorator (وبالتالي ، الأنابيب مزودون) ، والتي تنفذ PipeTransform واجهه المستخدم. يقومون بتحويل البيانات إلى التنسيق المطلوب وتقييم البيانات بحيث إذا تم العثور على البيانات صالحة ، فإنها تمر دون تغيير ، وإلا ، يتم طرح استثناء. من أجل استخدام أنبوب ، تحتاج إلى ربط مثيل لفئة توجيه التحويل بالسياق المناسب.

class-validator الحزمة تجعل من الممكن التحقق من صحة الديكور وغير المزخرفة ، باستخدام Validator.js داخليا. بينما ال class-transformer تتيح الحزمة إمكانية تحويل الكائنات إلى مثيل لفئة ، وتحويل الفئة إلى كائن ، وتسلسل الكائنات أو إلغاء تسلسلها بناءً على معايير معينة.

الأنابيب الثمانية التي يوفرها Nest هي:

  • ValidationPipe
  • ParseArrayPipe
  • ParseIntPipe
  • ParseUUIDPipe
  • ParseBoolPipe
  • DefaultValuePipe
  • ParseEnumPipe
  • ParseFloatPipe

لإثبات التحقق من الصحة في Nest في هذا الدليل ، سنستخدم المضمنة ValidationPipe يجعل من الممكن فرض التحقق من صحة حمولات الطلب ويتحد جيدًا مع class-validator طَرد؛ يتم الإعلان عن قواعد محددة مع التعليقات التوضيحية البسيطة في كائن نقل البيانات / إعلانات الفئة المحلية في كل وحدة نمطية.

لبدء استخدام ملف ValidationPipe الذي يتم تصديره من @nestjs/common، فلنقم بتثبيت برنامج class-validator و class-transformer حزم:

$ npm i --save class-validator class-transformer
# Or
$ yarn add class-validator class-transformer
# Or
$ pnpm install class-validator class-transformer

بعد ذلك ، انتقل إلى main.ts حيث سنلتزم ValidationPipe على مستوى جذر التطبيق لضمان حماية جميع نقاط النهاية في تطبيقنا من استرداد البيانات غير الصالحة:



import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}

bootstrap();

بعد ذلك ، في إعلانات كائن نقل البيانات لكل وحدة نمطية ، نضيف بعض قواعد التحقق من الصحة من خلال الإعلان عن فحوصات البيانات المناسبة لكل بيانات فردية. في حالتنا ، سنعلن عن قواعد التحقق المناسبة لـ name و email in UpdateUserDto:



import { IsEmail, IsString } from 'class-validator';

export class UpdateUserDto {
  @IsString()
  name: string;

  @IsEmail()
  email: string;
}

@IsString() يفحص مصمم الديكور ما إذا كانت البيانات المعينة عبارة عن سلسلة حقيقية ، أم لا @IsEmail() يتحقق المدقق مما إذا كانت البيانات المعينة بريدًا إلكترونيًا ، وإلا فإنها ترجع خطأ وتلقي استثناءً.

الآن ، إذا حاولنا إنشاء ملف PATCH طلب ملف تعريف مستخدم ، وإدخال رقم بدلاً من بريد إلكتروني صالح ، على سبيل المثال ، سيتم طرح استثناء:

دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام ذكاء بيانات Nest وNode PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

مع هذه ، لدينا عملية تحقق لطيفة للغاية في تطبيق Nest الخاص بنا.

أثناء التحقق باستخدام ValidationPipe، من الممكن أيضًا تصفية خصائصنا التي لا نريد أن يتلقاها معالج الأسلوب الخاص بنا. على سبيل المثال ، إذا كان معالجنا يتوقع فقط name و email الخصائص ، ولكن الطلب يتضمن أيضًا ملف country الخاصية ، يمكننا إزالة country الخاصية من الكائن الناتج عن طريق الإعداد whitelist إلى true عندما نقوم بإنشاء مثيل ValidationPipe:



import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
    }),
  );
  await app.listen(3000);
}

bootstrap();

ربط الأنابيب على مستوى معلمة الطريقة

يمكن أيضًا تحديد الأنابيب على params، أيضًا. لهذا ، سنربط الأنبوب على مستوى معلمة الطريقة.

قبل الآن ، على الرغم من أننا حددنا ملف userId ليكون رقمًا ، ستلاحظ أنه إذا قدمنا ​​طلبًا مع userId كسلسلة ، اتضح أنها ناجحة بغض النظر عن:

دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام ذكاء بيانات Nest وNode PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

للتأكد من أن قيمة userId يجب أن يكون دائمًا رقمًا ، فسنعلن أنه ملزم بربط getUser() معالج الطريقة مع التحقق من الصحة الذي يضمن نفس الشيء:


...
import { ParseIntPipe } from '@nestjs/common';

@Get('/:userId')
getUser(@Param('userId', ParseIntPipe) userId: number) {
  return this.userService.getUser(userId);
}


getUser(userId: number) {
  return { userId };
}

ParseIntPipe يحدد ParseInt Pipe المدمج ويضمن أن البيانات التي يتم تشغيلها مقابلها يجب أن تكون عددًا صحيحًا.

الآن ، عندما نصنع ملف GET طلب غير صالح userId من السلسلة “ab” ، يفشل التحقق من الصحة ويتم طرح استثناء مع a 400 رمز الحالة:

دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام ذكاء بيانات Nest وNode PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

ولكن بقيمة رقمية ، يتم التحقق بنجاح:

دليل Nest.js - إنشاء واجهة برمجة تطبيقات REST باستخدام ذكاء بيانات Nest وNode PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

يمكننا أيضًا تحديث معالجات الطرق الأخرى وفقًا لذلك لضمان التحقق المناسب:



import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  ParseIntPipe,
  Patch,
  Post,
  Req,
} from '@nestjs/common';
import { Request } from 'express';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private userService: UserService) {}
  @Get()
  getUsers() {
    return this.userService.get();
  }
  @Get('/:userId')
  getUser(@Param('userId', ParseIntPipe) userId: number) {
    return this.userService.getUser(userId);
  }
  @Post()
  store(@Req() req: Request) {
    return this.userService.create(req);
  }
  @Patch('/:userId')
  update(
    @Body() updateUserDto: { name: string; email: string },
    @Param('userId', ParseIntPipe) userId: number,
  ) {
    return this.userService.update(updateUserDto, userId);
  }
  @Delete()
  delete(@Param('userId', ParseIntPipe) userId: number) {
    return this.userService.delete(userId);
  }
}


import { Injectable } from '@nestjs/common';
import { Request } from 'express';
import { UpdateUserDto } from './dto/user-update.dto';

@Injectable()
export class UserService {
  get() {
    return { name: 'Uchechukwu Azubuko', country: 'Nigeria' };
  }
  getUser(userId: number) {
    return { userId };
  }
  create(req: Request) {
    return req.body;
  }
  update(updateUserDto: UpdateUserDto, userId: number) {
    return { body: updateUserDto, userId };
  }
  delete(userId: number) {
    return { userId };
  }
}

الآن ، قمنا بتأمين أفضل طريقة لممارسة التحقق من صحة البيانات التي تدخل إلى تطبيقنا ، ربما من مصدر خارجي ، في أي وقت.

وفي الختام

في هذا الدليل ، كنت قادرًا على التعرف على أحدث طفل في كتلة Node.js ؛ Nest.js ، وكل ما هو مطلوب لمساعدتك على البدء إذا كنت ترغب في إنشاء تطبيق به. لقد تعلمت ماهية Nest ، وميزاته ، وكيفية إنشاء مشروع Nest ، وكيفية التعامل مع البيانات الواردة في تطبيق Nest ، وكيفية التحقق من صحة البيانات الواردة. بشكل عام ، لقد تعرفت على اللبنات الأساسية لأي تطبيق من تطبيقات Nest ، والقيمة التي يجلبها كل مكون لتطبيق Nest.js.

من هذه النقطة ، لا يزال هناك الكثير لتتعلمه فيما يتعلق ببناء تطبيق على مستوى المؤسسات باستخدام Nest ، ولكنك تمكنت من تغطية المفاهيم الأساسية بنجاح والتي يمكن أن تجعلك تعمل على تحقيق كل ما ينتظرنا في المستقبل.

احترس من دليل جديد في المستقبل ، حيث نتعلم كيفية إنشاء واجهة برمجة تطبيقات مريحة باستخدام Nest و MySQL.

شكرا للقراءة!

مصادر إضافية

مستندات Nest.js
مستندات الزاوي

الطابع الزمني:

اكثر من ستاكابوز