معماری سیستم
Monorepo
پروژه یک monorepo بر پایهٔ Turbo است، با سه بخشِ اصلی:
apps/
api/ ← بکاند: Express + TypeScript + Prisma
calendar-web/ ← فرانتاند: React + Vite (feature-sliced)
packages/
contracts/ ← @taghvimam/contracts — Zod schemaها (منبع واحد)
جزئیاتِ بیشترِ ساختار و دستورهای پرکاربرد در Monorepo آمده است.
جریان یک درخواست
هر درخواست از یک مسیر ثابت عبور میکند:
client → Caddy (TLS) → Express API
├─ auth middleware (JWT)
├─ route → service → Prisma → PostgreSQL
└─ پاسخ با envelope { success, data?, error? }
نکتهای دربارهٔ رویدادها: منشأ هر رویداد با فیلدهای source و sourceId ردیابی
میشود — source یکی از LOCAL، GOOGLE، ANDROID_PROVIDER یا SERVER است.
یک منبع واحد (Single Source of Truth)
تمام DTOها یکبار بهصورت Zod schema در packages/contracts تعریف میشوند؛
API همان schemaها را برای اعتبارسنجیِ runtime وارد میکند و OpenAPI هم از همانجا
تولید میشود. spec با npm run openapi:generate بازتولید میشود، و اگر
openapi.json قدیمی باشد یا یک route فاقد @swagger باشد، CI build را رد میکند.
مدل داده (هسته)
| Model | نقش |
|---|---|
User | احراز هویت، fcm token، تلفن/ایمیل، ردیابی sync |
Calendar | تقویمهای هر کاربر (جلالی/میلادی) و اشتراکگذاری |
Event | رویدادها با تکرار (RRULE)، متادیتای iCal، ردیابی منشأ |
Task | وظایف سلسلهمراتبی (subtaskهای خودارجاع) |
Reminder | یادآورهای متصل به یک event یا task |
Device | احراز هویت مبتنی بر دستگاه (refresh token جداگانه + تشخیص replay) |
SyncConflict | تعارضهای ذخیرهشده حین حل LWW |
برای ارتباطات دقیق بین جداول به schema پایگاه داده مراجعه کنید.
وضعیت پیادهسازی
| مؤلفه | وضعیت |
|---|---|
سرورِ همگامسازی (apps/api) | ✅ کامل |
کلاینت وب (apps/calendar-web) | ✅ کامل (آفلایناول، با موتورِ همگامسازی) |
کلاینت اندروید (apps/mobile) | ❌ فقط دادهٔ محلی — موتورِ همگامسازی هنوز ساخته نشده (جزئیات) |
| زنجیرهٔ تولید (contracts → OpenAPI → کلاینت Kotlin) | ✅ در CI گارد میشود |