اموزش قدم به قدم ساخت پروژه فرانت و بکند

ایجاد حساب کاربری و مینی اپ

ایجاد حساب کاربری و مینی اپ

ثبت نام در اپسان

ورود به سامانه

Screenshot 2025-05-14 110628

مرحله اول توسعه نرم‌افزار با ورود و ثبت‌نام در پنل اپسان شروع می‌شود. برای ثبت‌نام شما می‌توانید از روش‌های کد ملی و ایمیل یا ورود از طریق سامانه مربوطه اقدام کنید.

باتوجه به اينكه سامانه اپسان در چند سازمان و چند محيط در حال استفاده است بايد اطلاعات دقيق سامانه و محل نصب ان را از مديرپروژه دريافت كنيد. صفحه ورود به سامانه

ورود از طریق کد ملی

برای ورود از طریق کد ملی نیاز است که شما کد ملی و شماره تلفن و تاریخ تولد خود را وارد کنید و بعد از آن ثبت‌نام شما تکمیل می‌شود.

فرم ورود با کد ملی

ایجاد حساب کاربری و مینی اپ

ایجاد مینی اپ

برای اضافه کردن مینی اپ و ساخت مینی اپ جدید باید مراحل زیر را طی کنید.

Screenshot 2025-05-14 111101

صفحه داشبورد

وقتی وارد حساب کاربری خود می‌شوید، به داشبورد اپ وارد می‌شوید و در اینجا اطلاعاتی مانند تعداد اپ‌هایی که در حال اجرا دارید، اپ‌هایی که منتظر تأیید هستند و … را مشاهده می‌کنید.

Screenshot 2025-05-11 151240

ایجاد مینی اپ جدید در اپسان

برای ایجاد یک مینی‌اپ جدید در اپسان، ابتدا باید وارد پنل کاربری خود شوید و اطلاعات مورد نیاز را وارد کنید. برای شروع، روی اپ‌های من کلیک کنید، همانطور که در تصویر زیر نشان داده شده است:

Screenshot 2025-05-11 151326

پس از کلیک روی اپ‌های من، به صفحه‌ای هدایت می‌شوید که اپ‌های شما و وضعیت هر یک نمایش داده می‌شود، همانطور که در شکل زیر مشخص است. برای ایجاد اپ جدید، روی اپ جدید کلیک کنید:

Screenshot 2025-05-11 152641

با کلیک روی اپ جدید، وارد صفحه ساخت اپ می‌شوید. این صفحه مطابق شکل زیر است:

Screenshot 2025-05-11 152956

برای ساخت اپلیکیشن در این پنل، باید تمام فیلدهای نمایش‌داده‌شده را پر کنید:

  1. در فیلد Client گزینه PWA را انتخاب کنید.
  2. برای لوگوی اپلیکیشن، روی فیلد انتخاب تصویر در سمت چپ فرم کلیک کرده و لوگوی موردنظر را آپلود کنید.

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

نکته : در محیط های تستی تایید مینی اپ توسط توسعه دهنده انجام می‌شود.

نصب نیازمندی ها

نصب نیازمندی ها

نصب نیازمندی های پروژه Appsan

در این بخش راهنمایی نصب نیازمندی ها برای یک پروژه در اپسان رو قدم به قدم جلو میرویم.

Screenshot 2025-05-14 111315

1)نصب IntelliJ IDEA نسخه 2025 از سایت های داخلی

در مرحله اول از سایت های داخلی اخرین ورژن IntelliJ IDEA  را نصب کنید .

2)فعال سازی و نصب appsan-intelij-plugin روی آن (روش پیشنهادی)

با رفتن به این نشانی  آخرین نسخه پلاگین را دانلود و ان را از حالت فشرده خالی کنید.

3)ایجاد پروژه جدید در intellij 

4) تنظیمات SDK اپسان

5)خطا های احتمالی

در این قسمت به احتمال زیاد به این خطای رایج میخورید Project has no JDK configuration برای این مشکل نیاز هست که در بخش Project در پنجره باز شده SDK را انتخاب کنید ورژن 11 یا بالاتر از JAVAرا انتخاب کرده یا در صورت عدم وجود ورژن Add را بزنید تا به صورت خودکار دانلود شود.

6)اضافه کردن پروژه یا ایجاد پروژه در فایل web و ساخت build آن در webdist

برای اینکه پروژه خود را در اپسان قرار دهید نیاز هست که ساختار ارائه شده اپسان را اجرا کنید . در این ساختار شما نیاز دارید که دو فایل web , web dist را اضافه کنید .

توضیحات بیشتر این بخش در ادامه امده است.

7)استفاده از عنصر webpage در پروژه Appsan

در مرحله اخر شما نیاز دارید که از webpage در پروژه خود استفاده کنید. برای این کار در ادامه توضیح داده شده است.

8)بیلد و رآن پروژه.

در قسمت اخر به صورت کامل و با تصویر توضیح مربوطه داده شده است

 

 

 

نصب نیازمندی ها

توسعه مینی اپ در اپسان

 

Screenshot 2025-05-14 112043

هدف این بخش ارائه ساختار نمونه برای توسعه یک مینی‌اپلیکیشن برای سرویس اپسان است. واضح است روش‌های مختلفی برای توسعه مینی‌اپ وجود دارد که یکی از آن‌ها در ادامه بررسی شده است.

ایجاد پروژه

  1. برنامه IntelliJ IDE را باز کنید.
    از منوی باز شده، روی Create New Project کلیک کنید.

    Screenshot 2025-05-11 154019

    یا از طریق File > New > Project یک پروژه جدید ایجاد کنید.
  2. از میان گزینه‌های ساخت پروژه جدید، appsan را انتخاب کرده و روی Next کلیک کنید.

    Screenshot 2025-05-11 153941

  3. برای پروژه جدید، نام مناسب انتخاب کرده و روی Finish کلیک کنید.

    Screenshot 2025-05-11 154332

  4. پروژه‌ای مشابه ساختار زیر ساخته خواهد شد:

    Screenshot 2025-05-11 154448

نصب نیازمندی ها

نصب نیازمندی های پروژه

در این بخش راهنمای قدم‌به‌قدم نصب نیازمندی‌ها برای یک پروژه در اپسان ارائه شده است.

با رفتن به این نشانی، آخرین نسخه پلاگین را دانلود و از حالت فشرده خارج کنید:
مشاهده لینک دانلود پلاگین

Screenshot 2025-05-14 114341

 

فعال سازی پلاگین(روش پیشنهادی)


ابتدا باید پلاگین اینتلیجی اپسان را فعال کنید. برای این کار نرم افزار intelij Idea را باز کنید و به بخش settings بروید یا کلید Ctrl + Alt + S را بزنید. در این بخش قسمت plugins بروید. روی کلید چرخ دنده کلیک کرده و Install Plugin from Disk را بزنید.

image-1669852609780.png

در پنجره ی باز شده فایل zip پلاگین اپسان دانلود شده را انتخاب کنید. این فایل با نام appsan-intelij-*.zip داخل فابل زیپ sdk است .

image-1669852635086.png

 

در صورت نیاز نرم افزار را بسته و دوباره باز کنید یا کلید Restart IDE را بزنید.

image-1669852729611.png

.

 

 

 

نصب نیازمندی ها

اضافه کردن اپسان

 

Screenshot 2025-05-14 114515

از منو فایل، Settings را انتخاب کنید:

انتخاب Settings از منوی File

در پنجره باز شده، به Languages & Frameworks > Appsan مراجعه کرده و آدرس پوشه SDK دانلود شده را در قسمت Path to SDK وارد نمایید:

تنظیم Path to SDK در Appsan

نصب نیازمندی ها

تنظیم و اجرای مینی‌اپ در IntelliJ IDEA

Screenshot 2025-05-14 114515

برای اجرای مینی‌اپ، در قسمت Run Config در بالا سمت راست IntelliJ روی Add Configuration یا Edit Configuration کلیک کنید. در پنجره باز شده، روی + زده و Appsan را انتخاب نمایید.

اضافه کردن Run Configuration

سپس نام موردنظر برای اجرا و فایل اجرایی را انتخاب کنید. Run type را روی Web قرار دهید.

انتخاب Run Type Web

پس از اجرای پروژه، آدرس وب نمایش داده شده در کنسول را کپی کرده و در مرورگر باز کنید.

برای ارتباط با دستگاه‌های اندرویدی، Android Platform Tools را دانلود کرده و پوشه platform-tools را در مسیر libs/bin/ جایگزین نمایید.

نصب Android Platform Tools

توجه: نمای وب پیش‌نمایش مینی‌اپ شما را نمایش می‌دهد و ممکن است خروجی با بسته‌بندی نهایی متفاوت باشد. همچنین امکانات سوپر اپ مانند اطلاعات کاربر یا توکن ورود در این روش در دسترس نیستند و باید به صورت دستی در کد اضافه شوند.

۵) خطاهای احتمالی

در این قسمت به احتمال زیاد با این خطای رایج مواجه می‌شوید: Project has no JDK configuration

برای رفع این مشکل، در پنجره تنظیمات بخش Project باید نسخه SDK را انتخاب کنید. نسخه Java 11 یا بالاتر را برگزینید و در صورت عدم وجود، روی Add کلیک کنید تا به‌صورت خودکار دانلود شود.

نصب نیازمندی ها

نمایش لاگ‌ها در Appsan

اپسان برخی از رخدادها و خطاها را به صورت log نمایش می‌دهد. یکی از این موارد، درخواست‌های وب است که متن ارسالی و پاسخ دریافتی آن داخل لاگ قابل مشاهده است.

Screenshot 2025-05-14 120210

دسترسی به لاگ‌ها از طریق CLI

برای دسترسی به لاگ‌ها، دستور زیر را اجرا کنید (به جای <device-id>، شناسه دستگاه خود را قرار دهید):

java -jar libs/Appsan-CLI-1.0-SNAPSHOT.jar logs -d <device-id>

برای به‌دست آوردن شناسه دستگاه اندرویدی خود، ابتدا این دستور را اجرا کنید:

java -jar libs/Appsan-CLI-1.0-SNAPSHOT.jar devices

لیست دستگاه‌ها در CLI

پس از اجرای دستور logs، می‌توانید لاگ‌ها را در آدرس http://localhost:12982/logs/ در مرورگر دلخواه خود مشاهده کنید:

مشاهده لاگ‌ها در مرورگر

دسترسی به لاگ‌ها در IntelliJ IDEA

برای تنظیم اجرای لاگ‌ها در IntelliJ، از منوی اجرا Edit Configurations را باز کنید:

ویرایش تنظیمات اجرا

روی دکمه + کلیک کرده و JAR Application را انتخاب کنید:

افزودن پیکربندی JAR

در قسمت Name نام موردنظر را وارد کنید و در Path to JAR مسیر فایل Appsan-CLI-1.0-SNAPSHOT.jar را انتخاب نمایید. سپس در بخش Program arguments دستور زیر را وارد کنید:

logs -d <device-serial>

که <device-serial> همان شناسه دستگاه است که پیش‌تر از CLI دریافت کردید.

پنجره پیکربندی Logs

حالا با اجرای پیکربندی logs در IntelliJ، لاگ‌ها در مرورگر نمایش داده می‌شوند.

نصب نیازمندی ها

نحوه افزودن پروژه به اپسان

در این راهنما، نحوه افزودن یک پروژه وب به پروژه Appsan به صورت گام‌به‌گام توضیح داده می‌شود. با استفاده از این راهنما، شما می‌توانید پروژه‌های وب خود را به‌طور مؤثری درون Appsan ادغام کرده و از قابلیت‌های جدید عنصر web-page بهره‌مند شوید.

Screenshot 2025-05-14 120521

۱. ایجاد پوشه‌های مورد نیاز

  1. ایجاد پوشه web:
    • در مسیر اصلی پروژه Appsan، پوشه‌ای به نام web ایجاد کنید.
    • این پوشه حاوی کد منبع پروژه‌های وب شما خواهد بود.
  2. ایجاد پوشه webdist:
    • در کنار پوشه web، پوشه‌ای به نام webdist ایجاد کنید.
    • این پوشه فایل‌های ساخته‌شده (build) پروژه‌های وب شما را نگهداری می‌کند.

۲. اضافه کردن پروژه وب به پوشه web

  1. ایجاد پوشه برای پروژه وب:
    • درون پوشه web، پوشه‌ای به نام پروژه وب خود بسازید (مثلاً MyWebProject).
  2. افزودن کد منبع:
    • تمام فایل‌های HTML، CSS، JavaScript و سایر فایل‌های پروژه وب را در این پوشه کپی کنید.

۳. ساخت پروژه وب

  1. ساخت پروژه:
    • با ابزار ساخت مناسب (مثل Webpack یا Parcel) پروژه وب خود را بسازید.
    • خروجی (build) شامل فایل‌های HTML، CSS و JavaScript بهینه شده خواهد بود.
  2. کپی خروجی به webdist:
    • پس از ساخت، فایل‌های خروجی را در پوشه‌ای با همان نام پروژه در webdist قرار دهید.
    • مثلاً webdist/MyWebProject.

۴. استفاده از عنصر webpage در پروژه Appsan

  1. افزودن عنصر webpage به فایل XML:
    • در فایل XML پروژه Appsan خود، تگ زیر را اضافه کنید:
    <webpage src="MyWebProject" title="پروژه وب من"/>
  2. تست و اشکال‌زدایی:
    • پروژه Appsan را اجرا کرده و از بارگذاری صحیح صفحه وب اطمینان حاصل کنید.
    • در صورت بروز مشکل، تنظیمات پوشه‌های web، webdist و ساخت پروژه وب را بررسی کنید.

نکات مهم

این راهنما به شما کمک می‌کند پروژه‌های وب خود را به‌طور مؤثر در Appsan ادغام کرده و از قابلیت‌های جدید بهره‌مند شوید.

نصب نیازمندی ها

راهنمای تنظیم پروژه Angular برای استفاده در Appsan

در این راهنما، نحوه تنظیم پروژه Angular به گونه‌ای که فایل‌های ساخته شده (build) آن به پوشه webdist در پروژه Appsan منتقل شوند و همچنین پروژه Angular در پوشه web مدیریت شود، توضیح داده می‌شود. این تنظیمات به شما امکان می‌دهند که به راحتی از پروژه Angular خود در Appsan استفاده کنید.

Screenshot 2025-05-14 120747

۱. ایجاد پوشه‌های مورد نیاز

  1. ایجاد پوشه web:
    • در مسیر اصلی پروژه Appsan، یک پوشه به نام web ایجاد کنید.
    • این پوشه حاوی کد منبع پروژه‌های وب شما خواهد بود.
  2. ایجاد پوشه برای پروژه Angular:
    • درون پوشه web، پوشه‌ای به نام پروژه Angular خود بسازید (مثلاً MyAngularProject).

۲. ایجاد پروژه Angular در پوشه web

  1. ایجاد پروژه Angular در مسیر مناسب:
    ng new MyAngularProject --directory web/MyAngularProject
  2. تست پروژه:

    با دستور زیر پروژه را به صورت محلی اجرا کنید و از صحت عملکرد آن مطمئن شوید:

    ng serve

۳. تنظیم مسیر خروجی (outputPath) در angular.json

  1. باز کردن فایل angular.json:

    در ریشه پروژه Angular، فایل angular.json را باز کنید.

  2. یافتن تنظیمات outputPath:

    در بخش architect → build مقدار outputPath را پیدا کنید.

  3. تغییر مسیر خروجی:

    مقدار outputPath را به مسیر زیر تغییر دهید:

    "outputPath": "../../webdist/MyAngularProject"

۴. تنظیم baseHref برای پروژه Angular

برای اطمینان از بارگذاری صحیح منابع، baseHref را به ./ تنظیم کنید:

۵. ساخت پروژه Angular

  1. ساخت پروژه:
    ng build
  2. بررسی فایل‌های ساخته شده:

    اطمینان حاصل کنید که فایل‌های خروجی در پوشه webdist/MyAngularProject قرار گرفته باشند.

۶. استفاده از پروژه Angular در Appsan

  1. افزودن عنصر webpage در فایل XML:
    <webpage src="MyAngularProject" title="پروژه Angular من"/>
  2. اجرای پروژه Appsan:

    پروژه Appsan را اجرا کرده و از بارگذاری صحیح پروژه Angular مطمئن شوید.

نکات مهم

نصب نیازمندی ها

راهنمای تنظیم پروژه React برای استفاده در Appsan

در این راهنما، نحوه تنظیم یک پروژه React به‌گونه‌ای که فایل‌های build آن به پوشه webdist در پروژه Appsan منتقل شوند و همچنین پروژه در پوشه web مدیریت شود، آموزش داده می‌شود. این مراحل مشابه با تنظیمات پروژه Angular بوده ولی با در نظر گرفتن تفاوت‌های React و Vite تهیه شده است.

۱. ایجاد پوشه‌های مورد نیاز

ایجاد پوشه web:
در مسیر اصلی پروژه Appsan خود، یک پوشه به نام web ایجاد کنید. این پوشه محل قرارگیری پروژه‌های وب شماست.

ایجاد پوشه برای پروژه React:
در داخل پوشه web، یک پوشه به نام دلخواه برای پروژه React ایجاد کنید. مثلاً:

web/MyReactProject

۲. ایجاد پروژه React در مسیر مناسب

با استفاده از Vite و دستور زیر پروژه React را در مسیر دلخواه ایجاد کنید:

npm create vite@latest web/MyReactProject -- --template react

سپس وارد پوشه پروژه شده و پکیج‌ها را نصب کنید:

cd web/MyReactProject  
npm install

۳. تنظیم مسیر خروجی (build output)

برای ذخیره فایل‌های build در پوشه webdist، فایل vite.config.js را باز کرده و تنظیمات زیر را اضافه کنید:

export default defineConfig({
  base: './',
  build: {
    outDir: '../../webdist/MyReactProject',
    emptyOutDir: true,
  },
});

توجه: به جای MyReactProject در مسیر outDir نام پوشه‌ای که می‌خواهید در webdist بسازید را قرار دهید.

۴. تنظیم مسیر (Routing) برای استفاده از مسیرهای داینامیک

در صورتی که اپلیکیشن شما از مسیر داینامیک استفاده می‌کند، باید از HashRouter به جای BrowserRouter استفاده کنید.

مراحل:

  1. نصب React Router:
    npm install react-router-dom
  2. در فایل App.jsx به صورت زیر تغییر دهید:
    import { HashRouter, Routes, Route } from 'react-router-dom';
    

    function App() { return ( <HashRouter> <Routes> <Route path="/" element={} /> <Route path="/results" element={} /> {/* مسیرهای دیگر */} </Routes> </HashRouter> ); }

۵. ساخت پروژه

پس از اعمال تغییرات بالا، دستور زیر را برای ساخت پروژه اجرا کنید:

npm run build

با اجرای این دستور، فایل‌های نهایی در مسیر webdist/MyReactProject قرار می‌گیرند.

۶. استفاده از پروژه React در Appsan

در فایل XML مربوط به Appsan، عنصر <webpage> را به شکل زیر اضافه کنید:

<webpage src="MyReactProject" title="پروژه React من"/>

مطمئن شوید که src با نام پوشه‌ای که در webdist ساختید مطابقت داشته باشد.

نکات مهم

نصب نیازمندی ها

کتابخانه JavaScript اپسان وب

کتابخانه JavaScript اپسان وب با هدف تسهیل ارتباط بین صفحات وب و پلتفرم اپسان طراحی شده است. این مستند به شما کمک می‌کند تا از این کتابخانه در وب‌سایت‌های خود استفاده کنید.

نصب کتابخانه

برای نصب کتابخانه اپسان، کافی است از npm استفاده کنید:

npm i @appsan-web/mini-web-sdk

لینک کتابخانه

راه‌اندازی کتابخانه

در ابتدا نیاز است که کتابخانه را در پروژه خود وارد کنید:

import { AppsanWeb } from '@appsan-web/mini-web-sdk';

استفاده از کلاس AppsanWeb

کلاس اصلی برای تعامل با اپسان، AppsanWeb است. این کلاس مسئول مدیریت ارتباطات بین وب‌سایت شما و صفحه اپسان است.

1. راه‌اندازی اولیه

برای راه‌اندازی کتابخانه کافی است تابع initialize را فراخوانی کنید. این تابع به صورت خودکار بعد از بارگذاری کامل صفحه وب شما فعال می‌شود:

AppsanWeb.initialize();

2. وضعیت آماده بودن اپسان

می‌توانید با استفاده از getStatus() وضعیت آماده بودن اپسان را بررسی کنید. این تابع یک BehaviorSubject از نوع رشته بازمی‌گرداند که می‌توانید به تغییرات آن گوش دهید:

const status$ = AppsanWeb.getStatus();  
status$.subscribe(status => {  
  console.log("Appsan Status:", status);  
});

وضعیت می‌تواند یکی از مقادیر زیر باشد:

3. اجرای اکشن در اپسان

تابع runAction برای اجرای اکشن در اپسان استفاده می‌شود:

AppsanWeb.runAction('myAction').subscribe();

4. مدیریت دکمه بازگشت

برای کنترل رفتار دکمه بازگشت از متد setCustomBackHandler استفاده کنید. در حالت پیش‌فرض اپسان هیستوری مینی‌وب شما را مدیریت می‌کند و این تابع تنها برای مدیریت پیشرفته بازگشت کاربرد دارد:

AppsanWeb.setCustomBackHandler(() => {  
  // Custom back behavior  
});

5. ارسال درخواست HTTP

برای ارسال درخواست HTTP می‌توانید از متد httpCall استفاده کنید:

AppsanWeb.httpCall('https://api.example.com', 'GET', {}, {}).subscribe(response => {  
  console.log('HTTP Response:', response);  
});

6. دریافت اطلاعات بایند (Bind)

متد getBind برای دریافت اطلاعات یک بایند خاص استفاده می‌شود. این متد یک Subject برمی‌گرداند که می‌توانید به آن subscribe کنید تا اطلاعات بایند را دریافت کنید:

AppsanWeb.getBind('myBind').subscribe(data => {  
  console.log('Bind data:', data);  
});

7. تنظیم مقدار متغیر

با استفاده از متد setVariable می‌توانید مقدار یک متغیر را در اپسان تنظیم کنید:

AppsanWeb.setVariable('variableId', 'newValue').subscribe();

8. دریافت مقدار متغیر

برای دریافت مقدار یک متغیر از اپسان از متد getVariable استفاده کنید. این متد نیز یک Subject برمی‌گرداند که می‌توانید مقدار متغیر را دریافت نمایید:

AppsanWeb.getVariable('variableId').subscribe(variable => {  
  console.log('Variable:', variable);  
});
نصب نیازمندی ها

تنظیم امکان بازگشت و رفتار دکمه بازگشت در اپسان

مقدمه

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


استفاده از رفتار پیش‌فرض

رفتار پیش‌فرض اپسان بر اساس تعداد صفحات موجود در تاریخچه عمل می‌کند:

  1. بسته شدن اپلیکیشن: اگر تعداد صفحات موجود در تاریخچه ≤ 1 باشد، اپلیکیشن بسته می‌شود.
  2. بازگشت به صفحه قبلی: اگر تاریخچه بیشتر از 1 صفحه داشته باشد، به صفحه قبلی بازمی‌گردد. در صورت تعریف customBackHandler، این تابع به جای رفتار پیش‌فرض اجرا می‌شود.

پاک کردن تاریخچه

برای پاک کردن تاریخچه و تنظیم تعداد صفحات موجود، می‌توانید از تابع پیش‌فرض clearBackStack استفاده کنید:

AppsanWeb.getAvailableHistoryCountProvider()?.clearBackStack();

قابلیت customBackHandler در AppsanWeb

این متد تنها در صورتی صدا می شود که availableBackCount بزرگ تر از 1 باشد.

  1. تعریف customBackHandler: این متغیر می‌تواند تابع شما را ذخیره کند که هنگام فشار دادن دکمه بازگشت اجرا می‌شود.
  2. متد setCustomBackHandler: برای تنظیم تابع سفارشی استفاده می‌شود:
    AppsanWeb.setCustomBackHandler(() => {
      // handle back here your way
    });

توجه: هنگام استفاده از تابع سفارشی، رفتار پیش‌فرض اجرا نمی‌شود و می‌توانید با اکشن app/forceback بازگشت انجام دهید.


تنظیم availableBackCount

برای تغییر availableBackCount در سوپر اپ از روش زیر استفاده کنید

(AppsanWeb as any).instance.post((AppsanWeb as any).MESSAGE_TYPE_AVAILABLE_HISTORY_COUNT, <back_count>);

سفارشی‌سازی امکان بازگشت

برای تعریف رفتار خاص بازگشت، یک کلاس جدید از رابط AvailableBackCountProvider پیاده‌سازی کنید. این رابط شامل متدهای زیر است:

  • getAvailableHistoryCount(): تعداد صفحات موجود را برمی‌گرداند.
  • clearBackStack(): تاریخچه را پاک و بازنشانی می‌کند.

نمونه: غیرفعال کردن بازگشت و بستن مینی‌اپ

import { AppsanWeb, AvailableBackCountProvider } from "./AppsanWeb";

export class DisableBackAndCloseProvider implements AvailableBackCountProvider {
  getAvailableHistoryCount(): number {
    return 1;
  }

  clearBackStack(): void {
    // No-op: back is effectively disabled
  }
}

با بازگرداندن ۱ در getAvailableHistoryCount()، بازگشت غیرفعال و مینی‌اپ بسته می‌شود.

نمونه پیاده‌سازی ارائه‌دهنده سفارشی تأیید قبل از بازگشت

import { AppsanWeb, AvailableBackCountProvider } from "./AppsanWeb";

export class ConfirmableBackCountProvider implements AvailableBackCountProvider {
private availableHistoryCount = 1;

constructor() {
// Patch history.pushState so we can track forward navigation
const h = window.history as any;
const originalPushState = h.pushState;
h.pushState = (...args: any[]) => {
this.onPushState();
return originalPushState.apply(h, args);
};

// Track browser back/forward via popstate
window.addEventListener("popstate", () => this.onPopState());

// Hook custom back handler to show a confirmation dialog
AppsanWeb.setCustomBackHandler(() => this.showConfirmationDialog());
}

private onPushState(): void {
this.availableHistoryCount++;
(AppsanWeb as any).instance.post(
(AppsanWeb as any).MESSAGE_TYPE_AVAILABLE_HISTORY_COUNT,
this.availableHistoryCount
);
}

private onPopState(): void {
this.availableHistoryCount = Math.max(0, this.availableHistoryCount - 1);
(AppsanWeb as any).instance.post(
(AppsanWeb as any).MESSAGE_TYPE_AVAILABLE_HISTORY_COUNT,
this.availableHistoryCount
);
}

getAvailableHistoryCount(): number {
return this.availableHistoryCount;
}

clearBackStack(): void {
this.availableHistoryCount = 1;
(AppsanWeb as any).instance.post(
(AppsanWeb as any).MESSAGE_TYPE_AVAILABLE_HISTORY_COUNT,
1
);
}

private showConfirmationDialog(): void {
if (confirm("آیا مطمئن هستید می‌خواهید بازگشت کنید؟")) {
history.back();
}
}
}

نحوه استفاده

  1. نمونه سازنده را بسازید:
    const backHandler = new ConfirmableBackCountProvider();
  2. کلاس ساخته شده را به setAppsanBackCountProvider بدهید
نصب نیازمندی ها

appsanHttpClient

کلاس AppsanHTTPClient

کلاس AppsanHTTPClient یک واسط ساده برای ارسال درخواست‌های HTTP در مینی‌وب‌ها (Mini-Webs) متصل به سوپر‌اپ Appsan است. این کلاس از قابلیت‌های داخلی Appsan (احراز هویت، تنظیمات پیش‌فرض و ارسال درخواست از طریق AppsanWeb) استفاده می‌کند تا ارسال درخواست‌ها به APIها ساده و ایمن باشد.

وارد کردن کلاس

import { AppsanHTTPClient } from '@appsan-web/mini-web-sdk';

تنظیمات Timeout

در تنظیمات HttpOptions می‌توان زمان‌های انتظار مربوط به اتصال، خواندن پاسخ و ارسال داده را مشخص کرد. مقدار تمامی Timeoutها بر حسب میلی‌ثانیه (ms) است.

  • connectTimeout: حداکثر زمان مجاز برای برقراری اتصال با سرور، بر حسب میلی‌ثانیه.
  • readTimeout: حداکثر زمان انتظار برای دریافت داده یا پاسخ از سرور، بر حسب میلی‌ثانیه.
  • writeTimeout: حداکثر زمان مجاز برای ارسال داده درخواست به سرور، بر حسب میلی‌ثانیه.

مثال:

AppsanHTTPClient.setDefaultOptions({
  connectTimeout: 10000,
  readTimeout: 30000,
  writeTimeout: 30000
});

در مثال بالا، زمان اتصال برابر با ۱۰ ثانیه و زمان خواندن و نوشتن هر کدام برابر با ۳۰ ثانیه تنظیم شده است.


متدها

setDefaultOptions(options: HttpOptions): void

تنظیم گزینه‌های پیش‌فرض برای تمامی درخواست‌ها.

  • ورودی‌ها: options: یک شیء از نوع HttpOptions که شامل هدرها، Timeoutها و سایر تنظیمات سفارشی است.

گزینه‌های Timeout قابل استفاده عبارت‌اند از connectTimeout، readTimeout و writeTimeout. مقدار هر سه گزینه بر حسب میلی‌ثانیه است.

get(url: string, options?: any): Observable

ارسال درخواست GET.

  • ورودی‌ها: url: آدرس API. options (اختیاری): تنظیمات سفارشی برای این درخواست که می‌تواند شامل connectTimeout، readTimeout و writeTimeout باشد.
  • خروجی: یک Observable که نتیجه پاسخ API را بازمی‌گرداند.

post(url: string, body: any, options?: any): Observable

ارسال درخواست POST.

  • ورودی‌ها: url: آدرس API. body: داده‌ای که باید در بدنه درخواست ارسال شود. options (اختیاری): تنظیمات اضافی، از جمله تنظیمات Timeout.

put(url: string, body: any, options?: any): Observable

ارسال درخواست PUT برای به‌روزرسانی داده‌ها.

  • ورودی‌ها: url: آدرس API. body: داده‌ای که باید به‌روزرسانی شود. options (اختیاری): تنظیمات اضافی، از جمله تنظیمات Timeout.

delete(url: string, options?: any): Observable

ارسال درخواست DELETE برای حذف داده‌ها.

  • ورودی‌ها: url: آدرس API. options (اختیاری): تنظیمات اضافی، از جمله تنظیمات Timeout.

patch(url: string, body: any, options?: any): Observable

ارسال درخواست PATCH برای تغییر جزئی داده‌ها.

  • ورودی‌ها: url: آدرس API. body: داده‌ای که باید تغییر کند. options (اختیاری): تنظیمات اضافی، از جمله تنظیمات Timeout.

مثال تنظیم Timeout برای یک درخواست

Timeoutها علاوه بر تنظیم به‌صورت پیش‌فرض، می‌توانند برای هر درخواست به‌صورت جداگانه مشخص شوند.

AppsanHTTPClient.get('/api/example', {
  connectTimeout: 5000,
  readTimeout: 15000,
  writeTimeout: 15000
});

تمام مقادیر Timeout در این مثال بر حسب میلی‌ثانیه هستند.


نکات مهم

انتشار

انتشار

مرحله انتشار

مرحله نهایی: بیلد و انتشار مینی‌اپ

در این مرحله شما باید پروژه خود را بیلد کنید و باندل بگیرید. برای اتمام این مرحله، مراحل زیر را طی کنید:

Screenshot 2025-05-14 120941

مرحله 1

Screenshot 2025-05-12 111630

پس از ساخت فایل‌های build در پوشه webdist، از بالای سمت چپ روی گزینه بیلد کلیک کرده و سپس بیلد در اپسان را انتخاب کنید.

مرحله 2

Screenshot 2025-05-12 111731

فایل ساخته‌شده در پوشه dist را بردارید و در سامانه اپسان، در بخش نسخه‌ها آپلود کنید و درخواست بررسی دهید.

مرحله 3

Screenshot 2025-05-12 111853

پس از تأیید بررسی، مینی‌اپ شما منتشر شده است.

نکات مهم انتشار مینی‌اپ:

  1. استفاده از AppsanHTTPClient:
    در بخش فرانت‌اند، تمامی درخواست‌های HTTP باید با کتابخانه AppsanHTTPClient ارسال شوند.
  2. تغییر شناسه پروژه:
    شناسه مینی‌اپ (Bundle ID) که در بخش اطلاعات پنل Appsan نمایش داده می‌شود را در فایل appsan.json پروژه اضافه کنید.
  3. ساخت و بسته‌بندی مینی‌اپ:
    از قسمت بالا سمت چپ مسیر Build > Build Appsan Bundle را انتخاب کنید. خروجی در پوشه dist به صورت یک فایل ZIP قرار می‌گیرد. این فایل را در پنل Appsan، بخش «نسخه‌ها» آپلود کنید.
  4. پیکربندی Base URL:
    قبل از بسته‌بندی، مقدار baseUrl را از تنظیمات حذف کنید (چرا که توسط سوپر‌اپ مدیریت می‌شود). پس از آپلود ZIP، در بخش پیکربندی پنل Appsan، baseUrl موردنظر خود را وارد کرده و درخواست بررسی دهید.
  5. تأیید بررسی:
    پس از اینکه درخواست بررسی تأیید شد، می‌توانید مینی‌اپ خود را از طریق URL مربوطه مشاهده و تست کنید.

ساختار بندی پروژه بکند

در این بخش مرحله به مرحله توسعه بکند پروژه را شرح میدهم.

ساختار بندی پروژه بکند

مراحل توسعه بک‌اند

در این قسمت به‌صورت کامل مراحل توسعه بک‌اند با ساختار پروژه مورد نظر شرکت ماورا توضیح داده می‌شود.

فهرست مراحل

Screenshot 2025-05-14 094931
  1. ایجاد Repository در گیت‌لب شرکت
    - ورود به https://git.mavaratech.com و لاگین با حساب کاربری شرکت
    - کلیک روی New Project و انتخاب Create blank project
    - وارد کردن نام، توضیحات و تنظیم سطح دسترسی
  2. تنظیم کانفیگ پروژه بر اساس ساختار تعریف‌شده
    - ایجاد پوشه config/ و فایل‌های default.json و production.json
    - ست کردن پارامترهایی مثل database.url، baseUrl و تنظیمات SSO
    - بارگذاری متغیرهای محیطی (Environment Variables)
  3. طراحی و پیاده‌سازی دیتابیس
    - مدل‌سازی ER-Diagram و تعریف جداول، ستون‌ها، PK و FK
    - نوشتن اسکریپت‌های DDL و اجرای آن‌ها در محیط توسعه
    - اضافه کردن seed data برای جداول پایه مثل کاربران و نقش‌ها
  4. ایجاد Routeها، API و کنترلرها
    - تعریف نقشه مسیرها (routes) در src/routes
    - پیاده‌سازی کنترلرها (Controllers) برای هر endpoint در src/controllers
    - مستندسازی APIها با OpenAPI/Swagger
  5. اطلاع‌رسانی به PMO درباره اتمام پروژه
    - ارسال ایمیل یا تیکت در سیستم PMO مبنی بر پایان کار
    - ارائه گزارش نهایی و لینک به مخزن کد و مستندات تکمیلی
ساختار بندی پروژه بکند

ساخت Repository

مراحل گام‌به‌گام «ساخت Repository» در گیت‌لب شرکت

Screenshot 2025-05-14 095714
  1. ورود به گیت‌لب
    ابتدا مرورگر خود را باز کنید و به آدرس زیر مراجعه کنید:
    https://git.mavaratech.com/
    سپس با حساب کاربری شرکت (نام کاربری و رمز عبور) وارد شوید. Screenshot 2025-05-13 110843
  2. ایجاد پروژه جدید Screenshot 2025-05-13 111042
    • پس از ورود، از منوی سمت چپ یا بالای صفحه روی دکمه‌ی New project کلیک کنید.
    • گزینه‌ی Create blank project را انتخاب کنید.
  3. وارد کردن اطلاعات پروژه
    • Project name: نام پروژه را به صورت انگلیسی و بدون فاصله (مثلاً my-awesome-app) وارد کنید.
    • Project slug: معمولاً خودکار پر می‌شود اما در صورت نیاز ویرایش کنید.
    • Project description (اختیاری): توضیح کوتاهی درباره‌ی هدف پروژه بنویسید.
    • Visibility Level: سطح دسترسی پروژه را مشخص کنید (Private، Internal یا Public).
  4. ساخت ریپازیتوری
    پس از تکمیل اطلاعات، روی دکمه‌ی Create project کلیک کنید. گیت‌لب به طور خودکار مخزن خالی را برای شما ایجاد کرده و وارد صفحه‌ی پروژه می‌شوید.
  5. پیکربندی اولیه (اختیاری)
    • در صورت نیاز، یک فایل README.md، .gitignore یا لایسنس (LICENSE) اضافه کنید.
    • با فعال کردن Initialize repository with a README یک فایل README به مخزن اضافه می‌شود.

اکنون ریپازیتوری شما آماده‌ی کار است و می‌توانید آن را کلون کرده، کدها را پوش کنید و توسعه را ادامه دهید.

ساختار بندی پروژه بکند

ساختار بندی پروژه

مقدمه

در این راهنما، گام‌به‌گام نحوهٔ شروع یک پروژه فول‌استک با React و Node.js و ساختار پیشنهادی پوشه‌ها و فایل‌ها تشریح شده است. این مستند مناسب تیم‌های توسعه است تا استاندارد یکپارچه‌ای برای ایجاد پروژه‌های جدید داشته باشند.

Screenshot 2025-05-14 095936

راه‌اندازی پروژه بک‌اند (Node.js + Express)

mkdir backend
cd backend
npm init -y
npm install express dotenv sequelize jsonwebtoken bcryptjs
npm install --save-dev nodemon

ساختار پوشه‌ها

backend/
├── config/
│   ├── db.js
│   ├── config.js
│   ├── development.js
│   ├── production.js
│   └── .dev.js
├── controller/
│   └── userController.js
├── routes/
│   └── userRoutes.js
├── service/
│   └── userService.js
├── utils/
│   └── generateToken.js
├── auth/
│   └── authMiddleware.js
├── .env
├── server.js
└── package.json

در server.js حتماً باید پورت پروژه را با مسئول DevOps تیم هماهنگ کنید.

پیکربندی اتصال به دیتابیس (config)

فایل db.js

این کلاس مسئول ایجاد اتصال Sequelize به PostgreSQL است:

import { Sequelize } from 'sequelize';
import configs from './config.js';

class DBConnection { constructor() { this.db_url = configs.db.url; const options = { dialect: "postgres", timezone: "+03:30", schema: 'schema', }; if (configs.db.useSSL === "true") { options.dialectOptions = { ssl: { require: true, rejectUnauthorized: false } }; } this.db = new Sequelize(this.db_url, options); }

getSequelizeInstance() { return this.db; } }

const sequelize = new DBConnection().getSequelizeInstance(); export default sequelize;

فایل config.js

براساس مقدار NODE_ENV یکی از فایل‌های محیطی (development، production، .dev) وارد می‌شود:

const env = process.env.NODE_ENV || 'development';
const configs = await import(`./.${env}.js`).then(m => m.default);
export default configs;

پیکربندی اتصال به دیتابیس (config)

فایل db.js

این کلاس مسئول ایجاد اتصال Sequelize به PostgreSQL است:


import { Sequelize } from 'sequelize';
import configs from './config.js';

class DBConnection { constructor() { this.db_url = configs.db.url; const options = { dialect: "postgres", timezone: "+03:30", schema: 'schema Name', }; if (configs.db.useSSL === "true") { options.dialectOptions = { ssl: { require: true, rejectUnauthorized: false } }; } this.db = new Sequelize(this.db_url, options); }

getSequelizeInstance() { return this.db; } }

const sequelize = new DBConnection().getSequelizeInstance(); export default sequelize;

فایل config.js

براساس مقدار NODE_ENV یکی از فایل‌های محیطی (development، production، .dev) وارد می‌شود:


const env = process.env.NODE_ENV || 'development';
const configs = await import(`./.${env}.js`).then(m => m.default);
export default configs;
    

فایل‌های محیطی

در این فایل‌ها تنظیمات مربوط به هر محیط (production، development، .dev) قرار دارد:

production.js


export default {
  app: {
    port: 3000,
    apiBaseUrl: process.env.API_BASE_URL || 'url',
    ssoBaseUrl: 'url',
    paymentBaseUrl: process.env.PAYMENT_BASE_URL || 'url',
    useMockUsername: process.env.USE_MOCK_USERNAME || 'false',
    mockUsername: process.env.MOCK_USERNAME || '',
  },
  db: {
    url: process.env.DB_URL || 'postgresql://postgreess',
    useSSL: process.env.DB_USE_SSL || 'false',
  },
  redis: {
    host: process.env.REDIS_HOST || 'host url',
    port: process.env.REDIS_PORT || port,
    sentinelNodes: process.env.REDIS_SENTINEL_NODES || '',
    sentinelName: process.env.REDIS_SENTINEL_MASTER || 'mymaster',
    password: process.env.REDIS_PASSWORD || 'password',
    dbNo: process.env.REDIS_DB_NO || 0,
    prefix: process.env.REDIS_PREFIX || 'integropia:'
  }
};
  

development.js


export default {
  app: {
    port: 3001,
    apiBaseUrl: 'BaseUrl that you recive',
    useMockUsername: 'true',
    mockUsername: process.env.MOCK_USERNAME || '',
  },
  db: {
    url: process.env.DB_URL || 'postgresql:postgressName',
    useSSL: 'false',
  },
  redis: {
    host: process.env.REDIS_HOST || '87.248.137.22',
    port: process.env.REDIS_PORT || 6379,
    sentinelNodes: process.env.REDIS_SENTINEL_NODES || '',
    sentinelName: process.env.REDIS_SENTINEL_MASTER || 'mymaster',
    password: process.env.REDIS_PASSWORD || 'password',
    dbNo: process.env.REDIS_DB_NO || 0,
    prefix: process.env.REDIS_PREFIX || 'integropia:',
  },
};
  

.dev.js


export default {
  app: {
    port: 3000,
    apiBaseUrl: process.env.API_BASE_URL || 'url',
    ssoBaseUrl: 'url,
    paymentBaseUrl: process.env.PAYMENT_BASE_URL || 'url',
    useMockUsername: process.env.USE_MOCK_USERNAME || 'false',
    mockUsername: process.env.MOCK_USERNAME || '',
  },
  db: {
    url: process.env.DB_URL || 'postgresql:postgress',
    useSSL: process.env.DB_USE_SSL || 'false',
  },
  redis: {
    host: process.env.REDIS_HOST || 'host',
    port: process.env.REDIS_PORT || port,
    sentinelNodes: process.env.REDIS_SENTINEL_NODES || '',
    sentinelName: process.env.REDIS_SENTINEL_MASTER || 'mymaster',
    password: process.env.REDIS_PASSWORD || 'password',
    dbNo: process.env.REDIS_DB_NO || 0,
    prefix: process.env.REDIS_PREFIX || 'integropia:'
  }
};
  

نکته بسیار مهم: در این بخش باید secret_key مینی‌اپ فرانت خود را در فایل‌های production.js یا development.js قرار دهید و نام مینی‌اپ در تمام پیکربندی‌ها یکسان باشد.

ساختار بندی پروژه بکند

طراحی ساختار دیتابیس (ER-Diagram)

در ادامه یک مثال از بخش طراحی دیتابیس آورده شده است

Screenshot 2025-05-14 102836
  1. طراحی ساختار دیتابیس (ER-Diagram)
    - مشخص کردن موجودیت‌ها (Entities): User، Request و RequestStatus
    - تعریف روابط: هر User می‌تواند چند Request داشته باشد؛ هر Request چند RequestStatus
    - تعیین کلیدهای اصلی (PK) و خارجی (FK) در هر جدول
  2. تنظیم کانفیگ Sequelize برای PostgreSQL
    - نصب پکیج‌ها:
    npm install sequelize pg pg-hstore
    - ایجاد فایل کانفیگ src/configs/database.js:
    import { Sequelize } from 'sequelize';
    const sequelize = new Sequelize(
      process.env.DB_NAME,
      process.env.DB_USER,
      process.env.DB_PASS,
      {
        host: process.env.DB_HOST,
        dialect: 'postgres',
        logging: false,
      }
    );
    

    export default sequelize;

  3. ایجاد مدل User
    - تعریف فیلدهای پایه مثل userId، name، email و role
    import { DataTypes } from 'sequelize';
    import sequelize from '../configs/database.js';
    

    const User = sequelize.define('User', { userId: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true, }, name: { type: DataTypes.STRING(100), allowNull: false, }, email: { type: DataTypes.STRING(150), allowNull: false, unique: true, }, role: { type: DataTypes.ENUM('user', 'expert', 'admin'), defaultValue: 'user', }, }, { tableName: 'users', timestamps: true, });

    export default User;

  4. ایجاد مدل Request
    - فیلدهای requestId، userId، expertId، text و trackingCode
    import { DataTypes } from 'sequelize';
    import sequelize from '../configs/database.js';
    import User from './user.js';
    import { v4 as uuidv4 } from 'uuid';
    

    const Request = sequelize.define('Request', { requestId: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true, }, userId: { type: DataTypes.INTEGER, references: { model: User, key: 'userId' }, allowNull: true, }, expertId: { type: DataTypes.INTEGER, references: { model: User, key: 'userId' }, allowNull: true, }, text: { type: DataTypes.TEXT, allowNull: false, }, trackingCode: { type: DataTypes.STRING(20), allowNull: false, unique: true, defaultValue: () => uuidv4().slice(0, 20), }, }, { tableName: 'requests', timestamps: true, });

    export default Request;

  5. ایجاد مدل RequestStatus
    - ENUM وضعیت‌ها، ارجاع به requestId و نگهداری previous_state
    import { DataTypes } from 'sequelize';
    import sequelize from '../configs/database.js';
    import Request from './request.js';
    

    const RequestStatus = sequelize.define('RequestStatus', { statusId: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true, }, requestId: { type: DataTypes.INTEGER, references: { model: Request, key: 'requestId' }, allowNull: false, }, statusType: { type: DataTypes.ENUM('started','pending','accepted','rejected','done'), defaultValue: 'started', }, expertComment: { type: DataTypes.TEXT, defaultValue: '', }, userComment: { type: DataTypes.TEXT, defaultValue: '', }, files: { type: DataTypes.JSONB, allowNull: true, }, previous_state: { type: DataTypes.INTEGER, references: { model: 'request_statuses', key: 'statusId' }, allowNull: true, }, }, { tableName: 'request_statuses', timestamps: true, hooks: { beforeCreate: async (status) => { const last = await RequestStatus.findOne({ where: { requestId: status.requestId }, order: [['statusId','DESC']], }); if (last) status.previous_state = last.statusId; } } }); export default RequestStatus;

  6. تنظیم ارتباطات (Associations)
    - در فایل src/models/index.js یا انتهای هر مدل:
    import User from './user.js';
    import Request from './request.js';
    import RequestStatus from './requestStatus.js';
    // User ↔ Request
    User.hasMany(Request, { foreignKey: 'userId', as: 'Requests' });
    Request.belongsTo(User, { foreignKey: 'userId', as: 'Customer' });
    User.hasMany(Request, { foreignKey: 'expertId', as: 'ExpertRequests' });
    Request.belongsTo(User, { foreignKey: 'expertId', as: 'Expert' });
    // Request ↔ RequestStatus
    Request.hasMany(RequestStatus, { foreignKey: 'requestId', as: 'Statuses' });
    RequestStatus.belongsTo(Request, { foreignKey: 'requestId', as: 'Request' });
    export { User, Request, RequestStatus };
  7. پیاده‌سازی الگوی وضعیت (State Pattern)
    - ساخت پوشه src/models/state/ و ایجاد کلاس‌های وضعیت:
    import { handleReqRejected } from '../../utils/status.utils.js';
    class AcceptedState {
    constructor(context) { this.context = context; }
    async transitionTo(statusType) {
    if (!statusType) throw new Error('Invalid statusType');
    if (statusType === 'rejected') {
    return await handleReqRejected(this.context);
    }
    throw new Error(`Cannot transition from accepted to ${statusType}`);
    }
    }
    

    export default AcceptedState;

    - در سرویس Request فراخوانی وضعیت:
    import AcceptedState from './state/acceptedState.js';
    import PendingState from './state/pendingState.js';
    // …
    class RequestService {
    constructor(request) {
    this.request = request;
    this.state = this._getStateInstance(request.currentStatus);
    }
    _getStateInstance(type) {
    switch(type) {
    case 'accepted': return new AcceptedState(this.request);
    // …
    }
    }
    async changeStatus(toType) {
    return this.state.transitionTo(toType);
    }
    }
ساختار بندی پروژه بکند

نوشتن APi, Route , Controller

در ادامه یک مثال از طراحی route , controller اورده شده است

Screenshot 2025-05-14 104259
  1. ایجاد ساختار پوشه‌ها برای Route و Controller
    - در ریشه پروژه پوشه‌های src/routes/ و src/controllers/ را بسازید
    - هر موجودیت (مثلاً requests و users) یک فایل Route و یک فایل Controller دارد
    - ساختار نهایی:
    src/
    ├─ controllers/
    │  ├─ requestController.js
    │  └─ userController.js
    └─ routes/
       ├─ requestRoutes.js
       └─ userRoutes.js
    
  2. تعریف Routeها با استفاده از Express
    - در src/routes/requestRoutes.js مسیرهای CRUD را تعریف کنید:
    import { Router } from 'express';
    import {
      createRequest,
      getAllRequests,
      getRequestById,
      updateRequest,
      deleteRequest
    } from '../controllers/requestController.js';
    

    const router = Router();

    router.post('/', createRequest); router.get('/', getAllRequests); router.get('/:id', getRequestById); router.put('/:id', updateRequest); router.delete('/:id', deleteRequest);

    export default router;

  3. ایجاد Controllerها با منطق کاری
    - در src/controllers/requestController.js توابع CRUD را پیاده کنید:
    import Request from '../models/request.js';
    

    export const createRequest = async (req, res, next) => { try { const newReq = await Request.create({ userId: req.body.userId, expertId: req.body.expertId, text: req.body.text }); res.status(201).json(newReq); } catch (err) { next(err); } };

    export const getAllRequests = async (_req, res, next) => { try { const list = await Request.findAll(); res.json(list); } catch (err) { next(err); } };

    export const getRequestById = async (req, res, next) => { try { const item = await Request.findByPk(req.params.id); if (!item) return res.status(404).json({ message: 'Not found' }); res.json(item); } catch (err) { next(err); } };

    export const updateRequest = async (req, res, next) => { try { const [updated] = await Request.update(req.body, { where: { requestId: req.params.id } }); if (!updated) return res.status(404).json({ message: 'Not found' }); res.json({ message: 'Updated' }); } catch (err) { next(err); } };

    export const deleteRequest = async (req, res, next) => { try { const deleted = await Request.destroy({ where: { requestId: req.params.id } }); if (!deleted) return res.status(404).json({ message: 'Not found' }); res.status(204).end(); } catch (err) { next(err); } };

  4. وصل کردن Routeها به اپلیکیشن اصلی
    - در src/app.js یا index.js این کار را انجام دهید:
    import express from 'express';
    import bodyParser from 'body-parser';
    import requestRoutes from './routes/requestRoutes.js';
    import userRoutes    from './routes/userRoutes.js';
    

    const app = express(); app.use(bodyParser.json());

    app.use('/api/requests', requestRoutes); app.use('/api/users', userRoutes);

    // هندلینگ خطا app.use((err, _req, res, _next) => { console.error(err); res.status(500).json({ error: err.message }); });

    export default app;

ساختار بندی پروژه بکند

نکات مهم پایانی

Screenshot 2025-05-14 094752

نکات مهم