برنامه نویسی

توسعه API حرفه ای با Azure Function Typescript + Boilerplate

هدف مقاله در اینجا ارائه جزئیات در مورد چارچوب، گردش کار و کتابخانه های پیاده سازی شده برای مخزن github است Azure Function Node.js Typescript Starter and Boilerplate در https://github.com/safwanmasarik/Azure-Function-Boilerplate-Api.

نکات مهم این دیگ بخار:

  • ⚡️ پشتیبانی از تایپ اسکریپت تابع Azure
  • ♨️ قابلیت بارگذاری مجدد داغ – کامپایل خودکار در ذخیره و راه اندازی مجدد سرور
  • 🃏 Jest — برای تست واحد + پاسخ db تمسخر آمیز پیکربندی شده است
  • ✨ بسته Linq – جایگزینی برای lodash، پشتیبانی از Typescript برای شمارش مجموعه ها
  • 📏 بسته Mssql – پشتیبانی از پایگاه داده محلی
  • 💨 بسته Json2Typescript – مدل سازی شی json به شی Typescript
  • 🤣 بسته شاد – Joi برای Typescript، اعتبارسنجی پارامترهای api با class & @decorators.
  • 📈 عیب‌یابی پروژه تایپ اسکریپت فعال شد – با کامپایل کردن در پس‌زمینه و نمایش خطا در نوار مشکلات، به سرعت خطا را دریافت کنید.
  • فرمت خودکار در ذخیره
  • 🌈 رنگ‌کننده جفت براکت فعال است
  • 🤖 پشتیبانی کامل و هوشمندانه کد ویژوال استودیو.
  • 🦠 معماری میکروسرویس – مخزن جداگانه api و پایگاه داده، بدون ORM.

فناوری Back-end API

  • توابع لاجوردی
  • Node.js
  • TypeScript
  • مایکروسافت SQL Server

فایل README در مخزن حاوی اطلاعات کافی برای اجرای موفقیت آمیز پروژه است.


بیا شروع کنیم.

ساختار پوشه

ساختار پوشه

  • .vscode شامل توصیه های برنامه افزودنی، تنظیمات راه اندازی اشکال زدایی، وظایف ساخت و تنظیمات پیش فرض IDE است. توجه داشته باشید که تنظیمات IDE در workspace.code-workspace لغو خواهد شد .vscode/settings.
  • ساختار پوشه پیش‌فرض برای Azure Function Node.js حفظ می‌شود، بنابراین توابع API باید در فهرست اصلی قرار داشته باشند. نام گذاری برای توابع API با پیشوند است az_* برای مرتب کردن همه توابع API در بالا.
  • نمونه هایی از نامگذاری API بر اساس نوع تابع مانند http،timerTrigger یا queueTrigger.
    api-nameing-example
  • پوشه اشتراکی شامل لایه های اصلی مانند خدمات (منطق تجاری)، لایه داده، مدل سازی و کمک کننده است.

چارچوب و گردش کار

پوشه به اشتراک گذاشته شده

  1. چارچوب اتخاذ شده به شرح زیر است domain-driven approach، با لایه های جداگانه برای API، service، و data.
  2. اولین نقطه ورود است API لایه ای که با آن تماس می گیرد service لایه برداری کنید و پاسخ api را دریافت کنید تا برگردانده شود.
  3. این service لایه منطق تجاری مانند calculations و data formatting. همچنین تماس با data لایه.
  4. این data لایه تنها وظیفه بازیابی داده ها را بر عهده دارد. بازیابی داده ها از پایگاه داده یا API شخص ثالث باید در اینجا انجام شود.
  5. بیشتر اشیاء JSON به شی کلاس Typescript تبدیل می شوند و کلاس ها، رابط ها و enum ها در پوشه models ذخیره می شوند.
  6. همه کلاس ها و توابعی که به عنوان در نظر گرفته می شوند helpers در پوشه helpers ذخیره می شود.
  7. برای unit testing، فقط service لایه و لازم helpers مورد آزمایش قرار خواهد گرفت. Unit testing نباید تماس واقعی با لایه داده انجام شود، بنابراین پاسخ های داده باید مسخره شوند.
  8. Data تست لایه تحت پوشش قرار خواهد گرفت integration test که تماس واقعی api و بازیابی واقعی داده ها را از منبع انجام می دهد. نمونه تست ادغام با مجموعه پستچی برای عملیات CRUDE در پوشه موجود است postman/AzFuncBoilerplate-IntegrationTest.postman_collection.json. در این پست به این مطالب نمی پردازیم.

پشتیبانی کتابخانه ها و ابزار

شادی آور

پرس و جو درخواست یا ورودی پارامترهای بدنه دارای محدودیت‌هایی هستند، بنابراین باید اعتبارسنجی شوند. در اینجا نحوه انجام آن آمده است.

اجرای اعتبارسنجی

import * as jf from 'joiful';

// Get the request body
const params = new ReqCreateUpdateDeleteShip();
params.ship_name = req?.body?.ship_name ?? null;
params.ship_code = req?.body?.ship_code ?? null;

// Validate request body
const joiValidation = jf.validate(params);

if (joiValidation.error) {
  return {
    is_valid: false,
    message: joiValidation.error.message,
    data: null
  };
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اعلام محدودیت های اعتبار سنجی در کلاس.

import 'reflect-metadata';
import * as jf from 'joiful';

export class ReqCreateUpdateDeleteShip {

  @jf.number().optional().allow(null)
  ship_id: number;

  @jf.boolean().optional()
  is_permanent_delete: boolean;

  @jf.string().required()
  ship_name: string;

  @jf.string()
    .regex(/^[a-z0-9]+(-[a-z0-9]+)*$/, "kebab case ('kebab-case', 'going-12-merry', 'jackson')")
    .required()
  ship_code: string;

  @jf.string().email()
  email: string;

  @jf.string().creditCard()
  credit_card_number: string;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

json2typescript

  • پاسخ ها از لایه داده به شکل شی JSON می آیند. json2typescript اشیاء JSON را به نمونه ای از کلاس TypeScript با نام مستعار نگاشت می کند Deserialization.
  • لایه سرویس از مدل‌سازی پاسخ لایه داده سود می‌برد زیرا کلاس و ویژگی ثابتی را برای منطق و قالب‌بندی کسب‌وکار فراهم می‌کند.
  • پشتیبانی هوشمندانه
  • آسان برای تغییر -> اگر نام ویژگی های پاسخ داده تغییر کند، کلاس نیازی به تغییر نخواهد داشت زیرا کتابخانه تزئین کننده JsonProperty را ارائه می دهد که امکان تنظیم آسان نقشه داده های JSON را فراهم می کند.

سریال زدایی

import { JsonConvert } from "json2typescript";
let jsonConvert: JsonConvert = new JsonConvert();
const queryData: object[] = await data.getShip(params);
let modelledDbData: DbShip[] = jsonConvert.deserializeArray(queryData, DbShip);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

دکوراتورهای کلاس و املاک.

  • برای اینکه ویژگی‌های کلاس برای نقشه‌بردار قابل مشاهده باشند، باید مقداردهی اولیه شوند، در غیر این صورت نادیده گرفته می‌شوند.
  • آنها را می توان با استفاده از هر مقدار (معتبر)، تعریف نشده یا تهی مقداردهی اولیه کرد.
import { JsonObject, JsonProperty } from "json2typescript";
import { DateConverter } from "../../helpers/json-converter";

@JsonObject("DbShip")
export class DbShip {
  @JsonProperty("id", Number, true)
  ship_id: number = null;

  @JsonProperty("name", String, true)
  ship_name: string = null;

  @JsonProperty("code", String, true)
  ship_code: string = null;

  @JsonProperty("is_active", Boolean, true)
  is_active: boolean = null;

  @JsonProperty("updated_date", DateConverter, true)
  updated_date: Date = null;
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مبدل سفارشی

import { JsonConvert, JsonConverter, JsonCustomConvert } from "json2typescript";

let jsonConvert: JsonConvert = new JsonConvert();

@JsonConverter
export class DateConverter implements JsonCustomConvert<Date> {
    serialize(date: Date): any {
        return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
    }

    deserialize(date: any): Date {
        return new Date(date);
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

داده های JSON را به کلاس Typescript تبدیل کنید

سریع تایپ

مشاهده و اعتبارسنجی داده های JSON

  • از نمایشگر و اعتبارسنجی آنلاین داده JSON مانند JSONGrid استفاده کنید

jsongrid

نحوه افزودن نقطه پایانی API جدید

  1. یک کپی از یک پوشه api تهیه کنید.
    api-01
  2. برای آسان کردن زندگی، آن را حذف کنید __test__ پوشه داخل پوشه جدید
  3. نام پوشه جدید را تغییر دهید و نام پوشه را کپی کنید.
    api-02
  4. را به روز کنید function.json، scriptFile مقدار نام پوشه جدید
    api-03
  5. حالا برو index.ts و نام تابع را به نام پوشه به روز کنید.
    api-04
  6. نقطه پایانی API جدید شما آماده است. مطبوعات F5 برای دویدن debug حالت دهید و آن را تست کنید.
    api-05
  7. درحالیکه در debug حالت می‌توانید لایه سرویسی را که می‌خواهید لایه api شما فراخوانی کند، تنظیم کنید. تغییرات مشاهده می شود و در ذخیره به طور خودکار کامپایل می شود و راه اندازی مجدد سرور به طور خودکار انجام می شود.
  8. لطفا توجه داشته باشید که تغییر محیط ها به گونه ای که تغییر مقادیر در local.settings.json از شما می خواهد که سرور را به صورت دستی راه اندازی مجدد کنید.

از اینکه وقت گذاشتید و اولین مقاله فنی عمومی من را خواندید متشکرم. من از جامعه توسعه‌دهنده فوق‌العاده برای پرورش من سپاسگزارم، و اکنون نوبت من است که به من کمک کنم. من از یادگیری و به اشتراک گذاری تجربیاتم لذت بردم و امیدوارم برای شما مفید باشد.

اگر این مقاله را دوست داشتید و فکر می کنید این به دیگران کمک می کند، آن را به اشتراک بگذارید. اگر احساس می کنید چیزی می تواند بهبود یابد یا اضافه شود، کامنت کنید.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا