بدأت
** ما سنتحدث عنه:**
المرجع ذو الصلة بالطلب: Controller.. @Route.. @Get.. @Path.. @Query.. @Post.. @Bodyو @SuccessResponse.
مذكرة الامتثال
أهداف هذا الدليل express ويفترض tsoa-nextسياسة الدعم الحالية: Node.js 22 أو أكثر. نحن نتحقق من الدعم في جميع أنحاء LTS السابقة، و LTS الحالية، و Node (في سي آي) الأمثلة الواردة أدناه: npm.. pnpmو yarn متغيرات حيث تختلف القيادة
بدء مشروعنا
# Create a new folder for our project
mkdir tsoa-project
cd tsoa-project
# Initialize git
git initإنشاء package.json و tsconfig.json مع مدير الطرد الخاص بك،
npm init -y
npm exec tsc -- --initpnpm init
pnpm exec tsc --inityarn init -y
yarn exec tsc --initوضع التطبيق TypeScript تعول مع مدير الطرد الذي تختاره
npm i tsoa-next express
npm i -D typescript @types/node @types/expresspnpm add tsoa-next express
pnpm add -D typescript @types/node @types/expressyarn add tsoa-next express
yarn add -D typescript @types/node @types/expressاستيراد الطرق المولدة من tsoa-nextإذاً الطرد الذي وضعته هو أيضاً الرزمة التي يستخدمها المتحكمون RegisterRoutes الملفات يمكنك أيضا أن تجد الطرد المنشور على npm.
الثقة tsoa والآلات
// tsoa.json
{
"entryFile": "src/app.ts",
"noImplicitAdditionalProperties": "throw-on-extras",
"controllerPathGlobs": ["src/**/*Controller.ts"],
"spec": {
"outputDirectory": "build",
"specVersion": 3
},
"routes": {
"routesDir": "build"
}
}لنلقي نظرة على ما نقوله tsoa هنا: أولا، نحدد المكان الذي سيدخل فيه تطبيقنا. على الأرجح، هذا الملف سيسمى index.ts أو app.ts. سنصنع هذا الملف في ثانية
بعد ذلك، أعلى مستوى controllerPathGlobs إعداد الأخبار tsoa حيث يمكن أن تبحث عن المتحكمين حتى لا يكون لدينا يدويا لاستيرادهم.
التالي، نقول tsoa مدى صرامة فحص الممتلكات (لأستخدام) TypeScript مدة العضوية أو فترة إضافية التحقق من الممتلكات (للاستعمال) OpenAPI () ينبغي أن تكون. نحن يُمْكِنُ أَنْ نَختارَ "مَنْ يَكُونُ" الإختبار الإضافي OpenAPI default), remove them during validation (silently-remove-extras) or throw an Error back to the Client (throw-on-extras)). بعد ذلك، وضعنا دليل النواتج OpenAPI المواصفات (منظمة الدول الأمريكية) routes.ts الملف الذي سنتحدث عنه لاحقاً
لقد وضعنا specVersion إلى 3 هكذا tsoa سوف يولد OpenAPI مواصفات ضد 3 يمكنك أيضا استخدام 3.1 عندما تريد OpenAPI 3-1 الناتج
لقائمة كاملة من كل الوصية الممكنة، إلقاء نظرة على مرجع API
TIP
في حين أن الوصية الخاطفة سوف تعمل من أجل هذا الدليل سيبدو (جيسون) شيئاً كهذا
Details
{
"compilerOptions": {
/* Basic Options */
"incremental": true,
"target": "es6",
"module": "commonjs",
"outDir": "build",
/* Strict Type-Checking Options */
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true,
/* Additional Checks */
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
/* Module Resolution Options */
"moduleResolution": "node",
"baseUrl": ".",
"esModuleInterop": true,
/* Experimental Options */
"experimentalDecorators": true,
// emitDecoratorMetadata is not needed by tsoa-next itself
/* Advanced Options */
"forceConsistentCasingInFileNames": true,
},
}تحديد نموذجنا الأول
إذا كان لديك بالفعل OpenAPI المواصفات، يمكنك استخدام القائمة OpenAPI أداة لتوليد نماذجك أو الأوجه وإلا لنحدد User Interface in src/users/user.ts.
export interface User {
id: number
email: string
name: string
status?: 'Happy' | 'Sad'
phoneNumbers: string[]
}قبل أن نبدأ بتعريف المراقب المالي، عادة ما تكون فكرة جيدة أن ننشئ دائرة تتعامل مع نماذجنا بدلا من أن ننقل كل هذا المنطق إلى طبقة التحكم.
// src/users/usersService.ts
import { User } from './user'
// A post request should not contain an id.
export type UserCreationParams = Pick<User, 'email' | 'name' | 'phoneNumbers'>
export class UsersService {
public get(id: number, name?: string): User {
return {
id,
email: 'jane@doe.com',
name: name ?? 'Jane Doe',
status: 'Happy',
phoneNumbers: [],
}
}
public create(userCreationParams: UserCreationParams): User {
return {
id: Math.floor(Math.random() * 10000), // Random
status: 'Happy',
...userCreationParams,
}
}
}تحديد متحكم بسيط
// src/users/usersController.ts
import { Body, Controller, Get, Path, Post, Query, Route, SuccessResponse } from 'tsoa-next'
import { User } from './user'
import { UsersService, UserCreationParams } from './usersService'
@Route('users')
export class UsersController extends Controller {
@Get('{userId}')
public async getUser(@Path() userId: number, @Query() name?: string): Promise<User> {
return new UsersService().get(userId, name)
}
@SuccessResponse('201', 'Created') // Custom success response
@Post()
public async createUser(@Body() requestBody: UserCreationParams): Promise<void> {
this.setStatus(201) // set return status 201
new UsersService().create(requestBody)
return
}
}لنتراجع ونتحدث عما يجري هنا كما يُمكنُك أن تُخبرَ، نحن نَعْرفُ /users/ استخدام الطريق @Route() مصممة على درجة المتحكمين
وبالإضافة إلى ذلك، نحدد طريقتين: getUser و createUser. The @Get() مصممة مع ممر القاعدة /users/ سيخبرنا tsoa للتذرع بهذه الطريقة لكل طلب /users/حيث إنه نموذج
المعبد
اركب tsoa مرآة عن قرب OpenAPIطريق مغري لأسباب التوافق ويشير إغراء المسار إلى استخدام تعبيرات نموذجية، محددة بواسطة حمالات العجلات ({})، لتحديد جزء من مسار URL على أنه يمكن استبداله باستخدام معايير المسار.
تحت القلنسوة، هذا سيكون مثل تحديد app.get('users/:userId'). في حين أن التعبير يسمح لك باستخدام تعاريف المسارات المتكررة، نفضّل تقسيم المسارات والتحقق بشكل أوضح. لأنّك تطلبين أن يكون الـ... رقماً بإستخدامه @Path() مصمم مع userId من النوع tsoa سيرفض المرور هنا وبالمثل، إذا كنت ترغب في قبول الـ... ... مع نمط معين، يمكنك أن تفعل ذلك باستخدام الشروح المشتركة Schema. يمكنك تعلم المزيد عن ذلك here.
tsoa-next :: دعم المسارات المعتادة، والاستفسارات، والرائدين، وأجهزة تشفير الجسم، كما أنها تدعم أيضاً مصممي البيانات المتعددة الجوانب مثل @FormField().. @UploadedFile()و @UploadedFiles()زائداً بارامترات الحقن غير المتكررة مثل @Request() و @Res().
TIP
إذا كان اسم البارامترات مساوياً لمباراة الرسالة على الموقع، يمكنك حذف الحجة إلى مصممي الديكور، وإلا جاز لك أن تقدم حجة:
@Query('my-query') myQuery: string;يمكن العثور على قائمة كاملة بجميع المصممين here.
مقهى
دائماً ما تستخدم تصديراً مسمّىexport class Cفي صف المراقب tsoa لتلتقطها بشكل صحيح الصادرات غير المباشرةexport default class C() غير مدعوم حاليا.
إنشاء خادمنا السريع
لنخلق الآن app.ts )أ( server.ts ملف في دليل المصدر مثل هذا:
// src/app.ts
import express, { json, urlencoded } from 'express'
import { RegisterRoutes } from '../build/routes'
export const app = express()
// Use body parser to read sent json payloads
app.use(
urlencoded({
extended: true,
}),
)
app.use(json())
RegisterRoutes(app)// src/server.ts
import { app } from './app'
const port = process.env.PORT || 3000
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))بناء الملفات المتولدة
في هذه المرحلة ربما لاحظت TypeScript لن يجدوا RegisterRoutes الواردات build/routes. هذا لأننا لم نطلب tsoa لتوليد الملف والطرق OpenAPI بالتأكيد دعونا نفعل ذلك الآن:
mkdir -p build # Create the build directory if it doesn't existnpm exec tsoa -- spec-and-routespnpm exec tsoa spec-and-routesyarn exec tsoa spec-and-routesالآن ملفاتك المُولّدة كان يجب أن تُخلق ويمكنك تجميعها TypeScript وأبدأ خادمك
npm exec tsc -- --outDir build --experimentalDecoratorspnpm exec tsc --outDir build --experimentalDecoratorsyarn exec tsc --outDir build --experimentalDecoratorsnode build/src/server.jsTIP
قد ترغب في إضافة هذه النصوص إلى package.json في هذه المرحلة:
"main": "build/src/server.js",
"scripts": {
"build": "tsoa spec-and-routes && tsc",
"start": "node build/src/server.js"
},ما التالي؟
- الاستشهاد اليدوي
tscوtsoa routesإن التنمية غير ملائمة جدا. - فحص أول OpenAPI مواصفات ونسخة محدثة SwaggerUI أثناء التنمية.
يمكننا تحسين استخدام live reloading.
- تحسين ردنا على أخطاء المصادقة باستخدام الحق error handling- استخدام Descriptions.. أمثلة و Annotations المصادقة المسبقة والتوثيق الأفضل
