مكدس تطبيقات TypeScript

مرحبا يا هبر! أقدم إليكم ترجمة المقال "تطبيقات Full-Stack TypeScript - الجزء 1: تطوير واجهات برمجة التطبيقات للواجهة الخلفية مع Nest.js" لآنا ريبيرو .


الجزء 1: تطوير خادم API باستخدام Nest.JS


TL ؛ DR: هذه سلسلة من المقالات حول كيفية إنشاء تطبيق ويب لـ TypeScript باستخدام Angular و Nest.JS. في الجزء الأول ، سنكتب واجهة برمجة تطبيقات خادم بسيط باستخدام Nest.JS. الجزء الثاني من هذه السلسلة مخصص لتطبيق الواجهة الأمامية باستخدام الزاوي. يمكنك العثور على الرمز النهائي الذي تم تطويره في هذه المقالة في مستودع جيثب هذا .


ما هو Nest.Js ولماذا الزاوي؟


Nest.js هو إطار عمل لإنشاء تطبيقات خادم الويب Node.js.


الميزة المميزة هي أنه يحل مشكلة لا يحلها إطار عمل آخر: بنية مشروع node.js. إذا كنت قد تطورت من أي وقت مضى تحت node.js ، فأنت تعلم أنه يمكنك القيام بالكثير باستخدام وحدة واحدة (على سبيل المثال ، يمكن للبرامج الوسيطة Express أن تفعل كل شيء من المصادقة إلى التحقق من الصحة) ، مما قد يؤدي في النهاية إلى "فوضى" غير مدعومة . كما سترى أدناه ، ستساعدنا nest.js في ذلك من خلال توفير فصول متخصصة في العديد من القضايا.


مستوحاة بشدة Nest.js بواسطة الزاوي. على سبيل المثال يستخدم كلا النظامين أدوات حماية للسماح بالوصول إلى بعض أجزاء تطبيقاتك أو تمنع الوصول إليها ، ويوفر كلا النظامين واجهة CanActivate لتنفيذ هذه الأجهزة. ومع ذلك ، من المهم ملاحظة أنه على الرغم من بعض المفاهيم المماثلة ، فإن كلا الهيكلين مستقلان عن بعضهما البعض. هذا هو ، في هذه المقالة ، سنقوم بإنشاء واجهة برمجة تطبيقات مستقلة للواجهة الأمامية لدينا ، والتي يمكن استخدامها مع أي إطار آخر (React ، Vue.JS وما إلى ذلك).


تطبيق الويب للطلبات عبر الإنترنت


في هذا الدليل ، سننشئ تطبيقًا بسيطًا يمكن للمستخدمين من خلاله وضع الطلبات في مطعم. سوف ينفذ هذا المنطق:


  • يمكن لأي مستخدم عرض القائمة ؛
  • المستخدم المصرح له فقط يمكنه إضافة البضائع إلى السلة (إصدار أمر)
  • يمكن للمسؤول فقط إضافة عناصر قائمة جديدة.

للبساطة ، لن نتفاعل مع قاعدة بيانات خارجية ولن نطبق وظائف سلة المتجر الخاصة بنا.


إنشاء بنية ملف المشروع Nest.js


لتثبيت Nest.js ، نحتاج إلى تثبيت Node.js (v.8.9.x أو أعلى) و NPM. قم بتنزيل Node.js وتثبيته لنظام التشغيل الخاص بك من الموقع الرسمي (يتم تضمين NPM). عند تثبيت كل شيء ، تحقق من الإصدارات:


node -v # v12.11.1 npm -v # 6.11.3 

هناك طرق مختلفة لإنشاء مشروع مع Nest.js؛ يمكن العثور عليها في الوثائق . سوف نستخدم nest-cli . تثبيته:


npm i -g @nestjs/cli


بعد ذلك ، قم بإنشاء مشروعنا باستخدام أمر بسيط:


nest new nest-restaurant-api


في هذه العملية ، سيطلب منا العش اختيار مدير الحزم: npm أو yarn


إذا سارت الأمور على ما يرام ، فستقوم nest بإنشاء بنية الملف التالية:


 nest-restaurant-api ├── src │ ├── app.controller.spec.ts │ ├── app.controller.ts │ ├── app.module.ts │ ├── app.service.ts │ └── main.ts ├── test │ ├── app.e2e-spec.ts │ └── jest-e2e.json ├── .gitignore ├── .prettierrc ├── nest-cli.json ├── package.json ├── package-lock.json ├── README.md ├── tsconfig.build.json ├── tsconfig.json └── tslint.json 

انتقل إلى الدليل الذي تم إنشاؤه وابدأ خادم التطوير:


  #    cd nest-restaurant-api #   npm run start:dev 

افتح متصفحًا وأدخل http://localhost:3000 . على الشاشة سوف نرى:


كجزء من هذا البرنامج التعليمي ، لن نختبر واجهة برمجة التطبيقات (على الرغم من أنه يجب عليك كتابة اختبارات لأي تطبيق جاهز للاستخدام). وبهذه الطريقة يمكنك مسح دليل test وحذف src/app.controller.spec.ts (وهو الاختبار الأول). نتيجة لذلك ، يحتوي مجلد المصدر على الملفات التالية:


  • src/app.controller.ts و src/app.module.ts : هذه الملفات مسؤولة عن إنشاء رسالة Hello world على طول / route. لأن نقطة الدخول هذه ليست مهمة لهذا التطبيق نقوم بحذفها. قريبا سوف تتعلم بمزيد من التفاصيل ما هي وحدات التحكم والخدمات .
  • src/app.module.ts : يحتوي على وصف لفئة نوع الوحدة النمطية ، المسؤولة عن الإعلان عن استيراد وتصدير وحدات التحكم والموفرين إلى تطبيق nest.js. يحتوي كل تطبيق على وحدة نمطية واحدة على الأقل ، ولكن يمكنك إنشاء أكثر من وحدة نمطية لتطبيقات أكثر تعقيدًا (المزيد في الوثائق . سيحتوي تطبيقنا على وحدة نمطية واحدة فقط
  • src/main.ts : هذا هو الملف المسؤول عن بدء تشغيل الخادم.

ملاحظة: بعد إزالة src/app.controller.ts و src/app.module.ts لن تتمكن من بدء تطبيقنا. لا تقلق ، سوف نصلحها قريبًا.

إنشاء نقاط دخول (نقاط النهاية)



واجهة برمجة التطبيقات (API) الخاصة بنا ستكون متاحة على مسار /items . من خلال نقطة الإدخال هذه ، يمكن للمستخدمين تلقي البيانات ، ويقوم المسؤولون بإدارة القائمة. لنقم بإنشائه.


للقيام بذلك ، قم بإنشاء دليل يسمى items داخل src . سيتم تخزين جميع الملفات المرتبطة بمسار /items في هذا الدليل الجديد.


إنشاء وحدات تحكم


في nest.js ، كما هو الحال في العديد من الأُطُر الأخرى ، تكون وحدات التحكم مسؤولة عن تعيين المسارات مع الوظائف. لإنشاء وحدة تحكم في nest.js استخدم أداة nest.js كما يلي: @Controller(${ENDPOINT}) . علاوة على ذلك ، من أجل تعيين طرق HTTP المختلفة ، مثل GET و POST ، يتم استخدام الديكورات @Get و @Post و @Delete وما إلى ذلك.


في حالتنا ، نحتاج إلى إنشاء وحدة تحكم تقوم بإرجاع الأطباق المتوفرة في المطعم ، والتي يستخدمها المسؤولون لإدارة محتويات القائمة. لنقم بإنشاء ملف يسمى items.controller.tc في دليل src/items بالمحتويات التالية:


  import { Get, Post, Controller } from '@nestjs/common'; @Controller('items') export class ItemsController { @Get() async findAll(): Promise<string[]> { return ['Pizza', 'Coke']; } @Post() async create() { return 'Not yet implemented'; } } 

من أجل إتاحة وحدة التحكم الجديدة لدينا في تطبيقنا ، قم بتسجيلها في الوحدة:


  import { Module } from '@nestjs/common'; import { ItemsController } from './items/items.controller'; @Module({ imports: [], controllers: [ItemsController], providers: [], }) export class AppModule {} 

قم npm run start:dev : npm run start:dev وفتح في المستعرض http: // localhost: 3000 / عنصر ، إذا فعلت كل شيء بشكل صحيح ، فعلينا أن نرى إجابة طلب الحصول على: ['Pizza', 'Coke'] .


ملاحظة المترجم: لإنشاء وحدات تحكم جديدة ، بالإضافة إلى عناصر أخرى من nest.js : الخدمات ، ومقدمي الخدمات ، وما إلى ذلك ، من الأنسب استخدام الأمر nest-cli . على سبيل المثال ، لإنشاء وحدة التحكم الموضحة أعلاه ، يمكنك استخدام الأمر nest generate controller items ، ونتيجة لذلك ، سيقوم العش بإنشاء src/items/items.controller.tc بالمحتويات التالية:


  import { Get, Post, Controller } from '@nestjs/common'; @Controller('items') export class ItemsController {} 

وتسجيله في app.molule.tc


إضافة خدمة


الآن ، عند الوصول إلى /items تطبيقنا الصفيف نفسه لكل طلب ، وهو ما لا يمكننا تغييره. لا تعد معالجة البيانات وحفظها من أعمال وحدة التحكم ؛ ولهذا الغرض ، فإن الخدمات موجهة إلى nest.js
الخدمات في العش هي @Injectable
يتحدث اسم الديكور عن نفسه ، مضيفًا أن إضافة هذا الديكور إلى الفصل يجعله قابلاً للحقن في مكونات أخرى ، مثل وحدات التحكم.
دعونا إنشاء خدمتنا. قم items.service.ts ملف items.service.ts في المجلد items.service.ts بالمحتويات التالية:


  import { Injectable } from '@nestjs/common'; @Injectable() export class ItemsService { private readonly items: string[] = ['Pizza', 'Coke']; findAll(): string[] { return this.items; } create(item: string) { this.items.push(item); } } 

وتغيير وحدة تحكم ItemsController (المعلنة في items.controller.ts ) لاستخدام خدمتنا:


  import { Get, Post, Body, Controller } from '@nestjs/common'; import { ItemsService } from './items.service'; @Controller('items') export class ItemsController { constructor(private readonly itemsService: ItemsService) {} @Get() async findAll(): Promise<string[]> { return this.itemsService.findAll(); } @Post() async create(@Body() item: string) { this.itemsService.create(item); } } 

في الإصدار الجديد من وحدة التحكم ، قمنا بتطبيق @Body decorator على وسيطة طريقة create . يتم استخدام هذه الوسيطة لمطابقة البيانات التي يتم تمريرها عبر req.body ['item'] تلقائيًا مع الوسيطة نفسها (في هذه الحالة ، item ).
كما تتلقى وحدة التحكم الخاصة بنا ItemsService فئة ItemsService ، يتم حقنه عن طريق المنشئ. التصريح ItemsService private readonly يجعل مثيل ثابت وغير مرئي فقط داخل الفصل.
ولا تنس تسجيل خدمتنا في 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 {} 

بعد كل التغييرات ، دعنا نرسل طلب HTTP POST إلى القائمة:


  curl -X POST -H 'content-type: application/json' -d '{"item": "Salad"}' localhost:3000/items 

بعد ذلك ، سوف نتحقق مما إذا كانت الأطباق الجديدة قد ظهرت في قائمتنا عن طريق تقديم طلب GET (أو عن طريق فتح http: // localhost: 3000 / عناصر في متصفح)


  curl localhost:3000/items 

إنشاء طريق عربة التسوق


الآن بعد أن أصبح لدينا الإصدار الأول من نقطة الدخول /items واجهة برمجة التطبيقات ، دعونا ننفذ وظيفة عربة التسوق. لا تختلف عملية إنشاء هذه الوظيفة عن واجهة برمجة التطبيقات التي تم إنشاؤها بالفعل. لذلك ، من أجل عدم تجميع الدليل ، سنقوم بإنشاء مكون يستجيب بحالة "موافق" عند الوصول.


أولاً ، في المجلد ./src/shopping-cart/ أنشئ shoping-cart.controller.ts :


  import { Post, Controller } from '@nestjs/common'; @Controller('shopping-cart') export class ShoppingCartController { @Post() async addItem() { return 'This is a fake service :D'; } } 

تسجيل وحدة التحكم هذه في الوحدة النمطية لدينا ( app.module.ts ):


  import { Module } from '@nestjs/common'; import { ItemsController } from './items/items.controller'; import { ShoppingCartController } from './shopping-cart/shopping-cart.controller'; import { ItemsService } from './items/items.service'; @Module({ imports: [], controllers: [ItemsController, ShoppingCartController], providers: [ItemsService], }) export class AppModule {} 

للتحقق من نقطة الإدخال هذه ، قم بتشغيل الأمر التالي ، بعد التأكد من تشغيل التطبيق:


  curl -X POST localhost:3000/shopping-cart 

إضافة Typescript واجهة للعناصر


العودة إلى خدمة items . الآن لا نوفر سوى اسم الطبق ، لكن هذا لا يكفي بوضوح ، وسنريد بالتأكيد الحصول على مزيد من المعلومات (على سبيل المثال ، تكلفة الطبق). أعتقد أنك ستوافق على أن تخزين هذه البيانات كمجموعة من السلاسل ليست فكرة جيدة؟
لحل هذه المشكلة ، يمكننا إنشاء مجموعة من الكائنات. لكن كيف تحفظ بنية الأجسام؟ هنا ستساعدنا واجهة TypeScript في تحديد بنية كائن items . قم بإنشاء ملف جديد باسم item.interface.ts في مجلد src/items :


  export interface Items { readonly name: string; readonly price: number; } 

ثم قم items.service.ts ملف items.service.ts :


 import { Injectable } from '@nestjs/common'; import { Item } from './item.interface'; @Injectable() export class ItemsService { private readonly items: Item[] = []; findAll(): Item[] { return this.items; } create(item: Item) { this.items.push(item); } } 

وكذلك في items.controller.ts :


 import { Get, Post, Body, Controller } from '@nestjs/common'; import { ItemsService } from './items.service'; import { Item } from './item.interface'; @Controller('items') export class ItemsController { constructor(private readonly itemsService: ItemsService) {} @Get() async findAll(): Promise<Item[]> { return this.itemsService.findAll(); } @Post() async create(@Body() item: Item) { this.itemsService.create(item); } } 

التحقق من صحة المدخلات في Nest.js


على الرغم من أننا حددنا بنية كائن item ، فلن يُرجع تطبيقنا خطأً إذا أرسلنا طلب POST غير صالح (أي نوع من البيانات غير معرف في الواجهة). على سبيل المثال ، لمثل هذا الطلب:


  curl -H 'Content-Type: application/json' -d '{ "name": 3, "price": "any" }' http://localhost:3000/items 

يجب أن يستجيب الخادم بحالة 400 (طلب غير صحيح) ، ولكن بدلاً من ذلك ، سوف يستجيب تطبيقنا بحالة 200 (موافق).


لحل هذه المشكلة ، قم بإنشاء DTO (كائن نقل البيانات) ومكون توجيه الإخراج (قناة).


DTO هو كائن يحدد كيفية نقل البيانات بين العمليات. وصفنا DTO في ملف src/items/create-item.dto.ts :


  import { IsString, IsInt } from 'class-validator'; export class CreateItemDto { @IsString() readonly name: string; @IsInt() readonly price: number; } 

الأنابيب في Nest.js هي المكونات المستخدمة للتحقق من الصحة. لواجهة برمجة التطبيقات لدينا ، قم بإنشاء قناة تتحقق مما إذا كانت البيانات المرسلة إلى الطريقة تتطابق مع DTO. يمكن استخدام قناة واحدة بواسطة وحدات تحكم مختلفة ، لذا قم بإنشاء src/common/ directory باستخدام validation.pipe.ts للملف:


  import { ArgumentMetadata, BadRequestException, Injectable, PipeTransform, } from '@nestjs/common'; import { validate } from 'class-validator'; import { plainToClass } from 'class-transformer'; @Injectable() export class ValidationPipe implements PipeTransform<any> { async transform(value, metadata: ArgumentMetadata) { const { metatype } = metadata; if (!metatype || !this.toValidate(metatype)) { return value; } const object = plainToClass(metatype, value); const errors = await validate(object); if (errors.length > 0) { throw new BadRequestException('Validation failed'); } return value; } private toValidate(metatype): boolean { const types = [String, Boolean, Number, Array, Object]; return !types.find(type => metatype === type); } } 

ملاحظة: نحتاج إلى تثبيت وحدتين: class-validator class-transformer . للقيام بذلك ، قم بتشغيل npm install class-validator class-transformer في وحدة التحكم وأعد تشغيل الخادم.

التكيف مع items.controller.ts للاستخدام مع أنابيب جديدة لدينا و DTO:


  import { Get, Post, Body, Controller, UsePipes } from '@nestjs/common'; import { CreateItemDto } from './create-item.dto'; import { ItemsService } from './items.service'; import { Item } from './item.interface'; import { ValidationPipe } from '../common/validation.pipe'; @Controller('items') export class ItemsController { constructor(private readonly itemsService: ItemsService) {} @Get() async findAll(): Promise<Item[]> { return this.itemsService.findAll(); } @Post() @UsePipes(new ValidationPipe()) async create(@Body() createItemDto: CreateItemDto) { this.itemsService.create(createItemDto); } } 

دعونا نتحقق من كودنا مرة أخرى ، والآن يقبل الإدخال /items البيانات فقط إذا كانت محددة في DTO. على سبيل المثال:


  curl -H 'Content-Type: application/json' -d '{ "name": "Salad", "price": 3 }' http://localhost:3000/items 

الصق البيانات غير الصالحة (البيانات التي لا يمكن التحقق منها في ValidationPipe ) ، ونتيجة لذلك حصلنا على الإجابة:


  {"statusCode":400,"error":"Bad Request","message":"Validation failed"} 

خلق الوسيطة

وفقًا لصفحة دليل البدء السريع Auth0 ، فإن الطريقة الموصى بها للتحقق من الرمز المميز لـ JWT الصادر عن Auth0 هي استخدام الوسيطة Express التي تقدمها Express express-jwt . هذه الوسيطة بأتمتة جزء كبير من العمل.


دعنا ننشئ ملف src / common داخل الدليل src / common بالشفرة التالية:


  import { NestMiddleware } from '@nestjs/common'; import * as jwt from 'express-jwt'; import { expressJwtSecret } from 'jwks-rsa'; export class AuthenticationMiddleware implements NestMiddleware { use(req, res, next) { jwt({ secret: expressJwtSecret({ cache: true, rateLimit: true, jwksRequestsPerMinute: 5, jwksUri: 'https://${DOMAIN}/.well-known/jwks.json', }), audience: 'http://localhost:3000', issuer: 'https://${DOMAIN}/', algorithm: 'RS256', })(req, res, err => { if (err) { const status = err.status || 500; const message = err.message || 'Sorry, we were unable to process your request.'; return res.status(status).send({ message, }); } next(); }); }; } 

استبدل ${DOMAIN} بقيمة المجال من إعدادات تطبيق Auth0


ملاحظة المترجم: في تطبيق حقيقي ، أخرج DOMAIN إلى ثابت ، وحدد قيمته عبر env (بيئة افتراضية)

قم بتثبيت express-jwt و jwks-rsa :


  npm install express-jwt jwks-rsa 

من الضروري توصيل الوسيطة التي تم إنشاؤها (معالج) بتطبيقنا. للقيام بذلك ، في ملف ./src/app.module.ts :


  import { Module, MiddlewareConsumer, RequestMethod } from '@nestjs/common'; import { AuthenticationMiddleware } from './common/authentication.middleware'; import { ItemsController } from './items/items.controller'; import { ShoppingCartController } from './shopping-cart/shopping-cart.controller'; import { ItemsService } from './items/items.service'; @Module({ imports: [], controllers: [ItemsController, ShoppingCartController], providers: [ItemsService], }) export class AppModule { public configure(consumer: MiddlewareConsumer) { consumer .apply(AuthenticationMiddleware) .forRoutes( { path: '/items', method: RequestMethod.POST }, { path: '/shopping-cart', method: RequestMethod.POST }, ); } } 

يشير الرمز أعلاه إلى أن طلبات POST إلى /items و /shopping-cart طرق محمية بواسطة الوسيطة Express التي تتحقق من رمز الوصول المميز في الطلب.


أعد تشغيل خادم التطوير ( npm run start:dev ) واتصل بـ Nest.js API:


  #     curl -X POST http://localhost:3000/shopping-cart #      TOKEN="eyJ0eXAiO...Mh0dpeNpg" # and issue a POST request with it curl -X POST -H 'authorization: Bearer '$TOKEN http://localhost:3000/shopping-cart 

إدارة الدور مع Auth0

في الوقت الحالي ، يمكن لأي مستخدم يحمل رمزًا تم التحقق منه نشر عنصر في API الخاصة بنا. ومع ذلك ، نود أن يتمكن المستخدمون الذين لديهم حقوق المسؤول فقط من القيام بذلك. لتنفيذ هذه الوظيفة ، نستخدم القواعد (القواعد) Auth0 .


لذا ، انتقل إلى لوحة التحكم Auth0 ، في قسم القواعد . هناك ، انقر فوق + CREATE RULE وحدد "تعيين الأدوار إلى مستخدم" كنموذج القاعدة.



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


في الوقت الحالي ، يتم تخزين هذه المعلومات في رمز تعريف (يستخدم لتوفير معلومات حول المستخدم) ، ولكن يجب استخدام رمز وصول للوصول إلى الموارد في واجهة برمجة التطبيقات. يجب أن يبدو الرمز بعد التغييرات كما يلي:


  function (user, context, callback) { user.app_metadata = user.app_metadata || {}; if (user.email && user.email === '${YOUR_EMAIL}') { user.app_metadata.roles = ['admin']; } else { user.app_metadata.roles = ['user']; } auth0.users .updateAppMetadata(user.user_id, user.app_metadata) .then(function() { context.accessToken['http://localhost:3000/roles'] = user.app_metadata.roles; callback(null, user, context); }) .catch(function(err) { callback(err); }); } 

ملاحظة: ${YOUR_EMAIL} بعنوان بريدك الإلكتروني. من المهم الإشارة إلى أنه ، كقاعدة عامة ، عندما تتعامل مع البريد الإلكتروني في قواعد Auth0 ، فمن المثالي فرض التحقق من البريد الإلكتروني . في هذه الحالة ، هذا غير مطلوب لأننا نستخدم عنوان البريد الإلكتروني الخاص بنا.

ملاحظة المترجم: يتم إدخال جزء الشفرة أعلاه في المستعرض في صفحة تكوين قاعدة Auth0

للتحقق مما إذا كان الرمز المميز الذي تم تمريره إلى API هو رمز المسؤول ، نحتاج إلى إنشاء حارس Nest.js. في المجلد src/common ، قم بإنشاء ملف admin.guard.ts


  import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; @Injectable() export class AdminGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const user = context.getArgs()[0].user['http://localhost:3000/roles'] || ''; return user.indexOf('admin') > -1; } } 

الآن ، إذا access_token عملية تسجيل الدخول الموضحة أعلاه access_token عنوان البريد الإلكتروني المحدد في القاعدة ، access_token جديد. للتحقق من محتويات هذا access_token ، انسخ والصق الرمز المميز في الحقل Encoded للموقع https://jwt.io/ . سنرى أن قسم الحمولة النافعة لهذا الرمز المميز يحتوي على الصفيف التالي:


  "http://localhost:3000/roles": [ "admin" ] 

إذا كان رمزنا يتضمن هذه المعلومات حقًا ، فإننا نواصل التكامل مع Auth0. لذلك ، افتح items.controller.ts وأضف الحارس الجديد إلى هناك:


  import { Get, Post, Body, Controller, UsePipes, UseGuards, } from '@nestjs/common'; import { CreateItemDto } from './create-item.dto'; import { ItemsService } from './items.service'; import { Item } from './item.interface'; import { ValidationPipe } from '../common/validation.pipe'; import { AdminGuard } from '../common/admin.guard'; @Controller('items') export class ItemsController { constructor(private readonly itemsService: ItemsService) {} @Get() async findAll(): Promise<Item[]> { return this.itemsService.findAll(); } @Post() @UseGuards(new AdminGuard()) @UsePipes(new ValidationPipe()) async create(@Body() createItemDto: CreateItemDto) { this.itemsService.create(createItemDto); } } 

الآن ، مع الرمز المميز الجديد ، يمكننا إضافة عناصر جديدة من خلال واجهة برمجة التطبيقات:


  #    npm run start:dev #  POST       curl -X POST -H 'Content-Type: application/json' \ -H 'authorization: Bearer '$TOKEN -d '{ "name": "Salad", "price": 3 }' http://localhost:3000/items 

ملاحظة المترجم: للتحقق ، يمكنك أن ترى ما لدينا في العناصر:
 curl -X GET http://localhost:3000/items 


النتائج


تهانينا! لقد انتهينا للتو من بناء واجهة برمجة تطبيقات Nest.JS الخاصة بنا والآن يمكننا التركيز على تطوير الجزء الأمامي من تطبيقنا! تأكد من إطلاعك على الجزء الثاني من هذه السلسلة: تطبيقات Full-Stack TypeScript - الجزء 2: تطوير تطبيقات Frontend Angular.


ملاحظة المترجم: ترجمة الجزء الثاني قيد التقدم.

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

Source: https://habr.com/ru/post/ar471348/


All Articles