تعرف على NestJS

تم إعداد ترجمة للمقال قبل إطلاق دورة Node.js Developer .




لدى المطورين الحديثين العديد من البدائل عندما يتعلق الأمر بإنشاء خدمات الويب وتطبيقات الخادم الأخرى. أصبحت العقدة خيارًا شائعًا للغاية ، ومع ذلك ، يفضل العديد من المبرمجين لغة أكثر قوة من JavaScript ، خاصة أولئك الذين يأتون من اللغات الحديثة الموجهة للكائنات ، مثل C # أو C ++ أو Java. إذا كان TypeScript مناسبًا تمامًا لـ NodeJS تمامًا ، فإن إطار عمل NestJS يأخذه إلى مستوى جديد تمامًا ، ويوفر أدوات حديثة لمطور الخلفية لإنشاء تطبيقات متينة وعالية الأداء باستخدام المكونات ، والموفرين ، والوحدات ، وغيرها من الملخصات المفيدة عالية المستوى.

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

إنشاء المشروع


للعمل مع Nest ، تحتاج إلى بيئة العقدة. إذا لم يكن لديك حتى الآن ، فانتقل إلى موقع الويب الخاص بهم وقم بتنزيله.

تثبيت الإطار بسيط للغاية:

$ npm i -g @nestjs/cli

تم إنشاء هذا المشروع باستخدام Nest CLI بعد تشغيل الأمر التالي:

$ nest new nest-js-example

سيقوم هذا الفريق بإنشاء مشروع Nest جديد تمامًا مع ملفات التكوين اللازمة وهيكل المجلد ونموذج الخادم.

نقطة دخول التطبيق


الملف الرئيسي الذي يقوم بتكوين وبدء الخادم هو src/main.ts:

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

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

bootstrap();

يستورد هذا الملف فئة NestFactory ، التي يتم استخدامها لإنشاء التطبيق ، وملف AppModule الرئيسي (الذي سنلتقي به قريبًا) ، ثم يقوم بتنزيل التطبيق ، وإنشاءه ، والاستماع إليه على المنفذ 3000.

وحدة التطبيق


الملف الذي تم التصريح عن مكونات التطبيق به src/app.module.ts:

import { Module } from '@nestjs/common';
import { ItemsController } from './items/items.controller';
import { ItemsService } from './items/items.service';

@Module({
    imports: [],
    controllers: [ ItemsController ],
    providers: [ ItemsService ],
})

export class AppModule {}

هذا هو الملف حيث يتم استيراد المكونات الأخرى والإعلان عنها في الوحدة النمطية ، والتي يتم استيرادها في الملف السابق ( main.ts ). في عش CLI والأدوات تلقائيا تحديث هذا الملف حسب الحاجة عندما أوعز إلى إنشاء مكون جديد. هنا ، يتم استيراد وحدة تحكم وخدمة للعناصر وإضافتها إلى الوحدة النمطية.

مراقب البنود


الملف التالي الذي سنراجعه هو src/items/items.controller.ts:

import { Controller, Req, Get, Post, Body } from '@nestjs/common'
import { CreateItemDto } from './dto/create-item.dto'
import { ItemsService } from './items.service'
import { Item } from './items.interface'

@Controller('items')
export class ItemsController {

    constructor(private readonly itemsService: ItemsService) {}

    @Post()
    create(@Body() data: CreateItemDto): Object {
        return this.itemsService.create(data)
    }

    @Get()
    findAll(): Array<Item> {
        return this.itemsService.findAll()
    }
}

يحدد هذا الملف وحدة التحكم لإنشاء العناصر والحصول على قائمة بالعناصر التي تم إنشاؤها مسبقًا. يتم استيراد العديد من المكونات الرئيسية هنا:

  • CreateItemDto : كائن نقل البيانات الذي يحدد كيفية إرسال بيانات العنصر عبر الشبكة (أي بنية بيانات JSON) ؛
  • ItemsService: المزود الذي يعالج معالجة أو تخزين بيانات العنصر ؛
  • البند : واجهة التي تحدد بنية البيانات الداخلية لل بند .

والديكور @Controller('items')يحكي الإطار أن هذه الفئة سيخدم REST / البنود نقطة النهاية ، و ItemsController منشئ يأخذ مثيل ItemsService ، والذي يستخدم داخليا لخدمة الطريقتين HTTP:

  • POST / items (لإنشاء عنصر جديد من طلب JSON) ؛
  • GET / items (الحصول على قائمة بالعناصر التي تم إنشاؤها سابقًا).

تتم معالجة طلبات الحصول على هاتين الطريقتين من إنشاء وأساليب FindAll، والتي لا بد أن أساليب HTTP المقابلة باستخدام @Post()و الديكور @Get(). يمكن أيضًا دعم الأساليب الإضافية من قبل الديكورات بطريقة مماثلة ، على سبيل المثال ، @Put()أو @Delete()، إلخ.

واجهات عنصر العنصر


بعد ذلك ، سنتعامل مع ملفين يحددان واجهات تخزين العنصر ، أحدهما للاستخدام الداخلي ، مثل التحقق من النوع في وقت الترجمة ( العنصر ) ، وواجهة خارجية لتحديد البنية المتوقعة لـ JSON ( CreateItemDto) الوارد :

export interface Item {
	
    name: string,
    description: string,
    price: number
}

export class CreateItemDto {

    @IsNotEmpty()
    readonly name: string;

    @IsNotEmpty()
    readonly description: string;

    @IsNotEmpty()
    readonly price: number;
}

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

فئة CreateItemDto خصائص العنصر ، وتزيين كل خاصية @IsNotEmpty()للتأكد من أن كل هذه الخصائص مطلوبة بواسطة نقطة نهاية REST API.

يتم كتابة جميع خصائص كلا الفئتين بقوة ، وهي واحدة من المزايا الرئيسية لـ TypeScript (ومن هنا جاء الاسم). للوهلة الأولى ، يؤدي ذلك إلى زيادة مستوى فهم السياق ، ويقلل وقت التطوير بشكل كبير عند استخدامه بشكل صحيح مع أدوات تحليل التعليمات البرمجية (مثل IntelliSense في VSCode). هذا ينطبق بشكل خاص على المشاريع الكبيرة التي تحتوي على مئات أو حتى الآلاف من الطبقات والواجهات المختلفة. بالنسبة لأولئك الذين ليس لديهم ذاكرة فوتوغرافية مثالية ذات سعة لا نهائية (على سبيل المثال ، بالنسبة لي) ، فإن الأمر أسهل بكثير من محاولة تذكر آلاف التفاصيل المحددة.

خدمة العناصر


الأحدث هي خدمة لإنشاء واستلام items: items.service.dart:

import { Injectable } from '@nestjs/common'
import { Item } from './items.interface'

@Injectable()
export class ItemsService {

    private items: Array<Item> = []

    create(item: Item): Object {

        this.items.push(item) 
        return { id: this.items.length.toString() }
    }

    findAll(): Array<Item> {

        return this.items;
    }
}

و ItemsService الطبقة تحدد مجموعة بسيطة من البند الأشياء التي من شأنها أن تكون بمثابة مخزن البيانات في الذاكرة لمشروع العينة. هناك طريقتان للكتابة والقراءة من هذا المستودع:

  • إنشاء (حفظ العنصر في القائمة وإرجاع معرفه) ؛
  • findAll (إرجاع قائمة كائنات العنصر التي تم إنشاؤها مسبقًا ).

اختبارات


لبدء الخادم ، استخدم الأمر npm run start القياسي . عند تشغيل التطبيق ، يمكن اختباره عن طريق إرسال طلبات HTTP عبر CURL :

$ curl -X POST localhost:3000/items -d '{"name":"trinket", "description":"whatever", "price": 42.0}'

سيؤدي تنفيذ هذا الأمر إلى إرجاع استجابة JSON بالمعرف الذي تم إنشاؤه بواسطة العنصر . لإظهار قائمة بالعناصر التي تم إنشاؤها بالفعل ، استخدم:

$ curl localhost:3000/items

سيعرض طلب GET إلى / العناصر أعلاه استجابة JSON بمعلومات حول العناصر الموجودة بالفعل في الذاكرة. يجب أن تبدو الإجابة شيئًا مثل هذا:

[{"{\"name\":\"trinket\", \"description\":\"whatever\", \"price\": 42.0}":""}]

استنتاج


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

لمعرفة المزيد ، قم بزيارة موقع NestJS .
شكرا لكم على قراءة مقالتي. الترميز سعيدة!

All Articles