Files
MathApp_frontend/src/api/README.md
AliReza be9f99d52a add a typed API layer for the Tadrisino backend
اپ تا الان هیچ درخواستی به سرور نمی‌زد و همه‌ی داده‌ها داخلِ خودِ کامپوننت‌ها
هاردکد بود. این کامیت لایه‌ی ارتباط را اضافه می‌کند، بدونِ اینکه هیچ صفحه‌ای
را تغییر دهد.

عمداً فقط فایلِ جدید اضافه شده و App.tsx دست نخورده است، چون کارِ در جریانِ
برنچِ updateApp روی همان فایل است و نباید با هم تصادف کنند. وصل کردنِ
صفحه‌ها به این لایه کارِ بعدی‌ست.

هیچ پکیجِ جدیدی اضافه نشد — فقط fetch استاندارد.

چیزهایی که در client.ts هست برای حالتِ خراب‌اند، نه حالتِ خوب:
  • timeout روی هر درخواست — وگرنه بک‌اندِ کند سوکت‌ها را باز نگه می‌دارد تا
    مرورگر به سقفِ ۶ درخواستِ همزمان بخورد و اپ قفل شود.
  • backoff با jitter — بدونِ jitter همه‌ی کلاینت‌ها بعد از یک خطا همزمان
    دوباره می‌زنند و موجِ دوم از موجِ اول بدتر است.
  • تکرارِ خودکار فقط روی GET؛ POST فقط وقتی Idempotency-Key دارد (ثبتِ پاسخ،
    سفارش) تا دابل‌کلیکِ کاربر دو بار XP یا دو سفارش نسازد.
  • refresh تک‌نسخه‌ای — ۲۰ درخواستِ همزمانِ ۴۰۱ نباید ۲۰ بار refresh بزنند.
  • ادغامِ GETهای یکسانِ در جریان.
  • احترام به هدرِ Retry-After که بک‌اند موقعِ throttle می‌فرستد.

credentials: 'omit' عمدی‌ست: احرازِ هویت توکنِ Bearer در هدر است و سمتِ سرور
CORS_ALLOW_CREDENTIALS=False تنظیم شده.

.env هم به .gitignore اضافه شد؛ قبلاً فقط node_modules داخلش بود و آدرس/
تنظیماتِ محلی می‌توانست ناخواسته کامیت شود.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 20:06:28 +03:30

4.2 KiB

اتصال به بک‌اند

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

راه‌اندازی

هیچ تنظیماتی لازم نیست. به‌طورِ پیش‌فرض به بک‌اندِ مشترک (https://api.math.tadrisino2.ir/api) وصل می‌شود:

npm install
npm run dev

فقط اگر بک‌اند را روی ماشینِ خودتان بالا آورده‌اید:

cp .env.example .env      # و خطِ VITE_API_BASE_URL را باز کنید

برای اینکه ببینید اتصال برقرار است، یک خط کافی‌ست (بعداً پاکش کنید):

import { ConnectionCheck } from '@/api/ConnectionCheck';
// داخلِ خروجیِ App:
<ConnectionCheck />

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

استفاده

import { api, ApiError } from '@/api';

const grades  = await api.grades();
const home    = await api.home();                    // پایه‌ی خودِ کاربر
const intro   = await api.lessons.intro(lessonId);
const answer  = await api.ai.ask('این رو نفهمیدم', { lessonId });

ورود

await api.auth.guest(deviceId);                 // «شروع سریع»، بدونِ شماره
// یا
const { devOtp } = await api.auth.requestOtp('09120000000');
await api.auth.login('09120000000', otp);       // نامِ فیلد در سرور otp است

توکن خودش در localStorage ذخیره می‌شود و به هر درخواست اضافه می‌گردد.

خطاها

try {
  await api.ai.ask(text, { lessonId });
} catch (error) {
  if (error instanceof ApiError) {
    if (error.isRateLimited) { /* ۴۲۹ — خیلی سریع پرسیده */ }
    if (error.isProviderDown) { /* ۵۰۳ — سرویسِ AI موقتاً قطع */ }
    if (error.isNetwork) { /* اصلاً نرسید یا timeout */ }
  }
}

چرا این‌قدر ملاحظه در client.ts

هر تکه‌اش برای حالتی‌ست که فقط زیرِ فشار پیش می‌آید:

مسئله اگر نباشد چه می‌شود
timeout روی هر درخواست یک بک‌اندِ کند سوکت‌ها را باز نگه می‌دارد؛ مرورگر به سقفِ ۶ درخواستِ همزمان می‌خورد و کلِ اپ قفل می‌شود
backoff با jitter هزار کلاینت بعد از یک خطا همزمان دوباره می‌زنند و موجِ دوم سرور را می‌خواباند
تکرارِ خودکار فقط روی GET تکرارِ POST یعنی سفارش یا پاسخِ تکراری
Idempotency-Key روی ثبتِ پاسخ و سفارش دابل‌کلیکِ کاربر دو بار XP یا دو سفارش می‌سازد
refresh تک‌نسخه‌ای ۲۰ درخواستِ همزمانِ ۴۰۱ ⇒ ۲۰ بار refresh ⇒ سرور همه را throttle می‌کند
ادغامِ GETهای یکسان دو کامپوننت که با هم یک چیز می‌خواهند، دو برابر بار می‌سازند
احترام به هدرِ Retry-After بک‌اند صریح می‌گوید چقدر صبر کن؛ نادیده گرفتنش throttle را طولانی‌تر می‌کند

credentials: 'omit' هم عمدی‌ست: احرازِ هویت توکنِ Bearer در هدر است و سمتِ سرور CORS_ALLOW_CREDENTIALS=False تنظیم شده. عوضش نکنید.

چیزی که هنوز نیست

  • صفحه‌ی ورود در اپ وجود ندارد؛ api.auth آماده است ولی UI ندارد.
  • api.home() ساختارِ واقعیِ درس‌ها را می‌دهد، ولی وصل کردنش به صفحه‌ها هنوز انجام نشده — این PR عمداً App.tsx را دست نزده تا با کارِ در جریان تصادف نکند.