🚀 Initialize Musadaq SaaS: Full Backend + AI + React Dashboard + Docker Setup
This commit is contained in:
136
backend/src/config/env.validation.ts
Normal file
136
backend/src/config/env.validation.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* ════════════════════════════════════════════════════════════
|
||||
* مُصادَق — Environment Validation Schema (Joi)
|
||||
* ════════════════════════════════════════════════════════════
|
||||
* يتحقق من وجود وصحة جميع متغيرات البيئة عند بدء التطبيق.
|
||||
* أي متغير مفقود أو غير صالح = فشل فوري في التشغيل.
|
||||
* ════════════════════════════════════════════════════════════
|
||||
*/
|
||||
|
||||
import * as Joi from 'joi';
|
||||
|
||||
export const envValidationSchema = Joi.object({
|
||||
// ── Application ────────────────────────────────────────
|
||||
NODE_ENV: Joi.string()
|
||||
.valid('development', 'production', 'test')
|
||||
.required()
|
||||
.description('بيئة التشغيل'),
|
||||
|
||||
PORT: Joi.number()
|
||||
.port()
|
||||
.default(3300)
|
||||
.description('منفذ الخادم'),
|
||||
|
||||
APP_URL: Joi.string()
|
||||
.uri()
|
||||
.required()
|
||||
.description('رابط التطبيق الكامل'),
|
||||
|
||||
ALLOWED_ORIGINS: Joi.string()
|
||||
.required()
|
||||
.description('النطاقات المسموح بها للـ CORS (مفصولة بفاصلة)'),
|
||||
|
||||
// ── Database ───────────────────────────────────────────
|
||||
DB_HOST: Joi.string()
|
||||
.required()
|
||||
.description('مضيف قاعدة البيانات'),
|
||||
|
||||
DB_PORT: Joi.number()
|
||||
.port()
|
||||
.default(5300)
|
||||
.description('منفذ قاعدة البيانات'),
|
||||
|
||||
DB_USER: Joi.string()
|
||||
.required()
|
||||
.description('مستخدم قاعدة البيانات'),
|
||||
|
||||
DB_PASS: Joi.string()
|
||||
.min(32)
|
||||
.required()
|
||||
.description('كلمة مرور قاعدة البيانات (32 حرف كحد أدنى)'),
|
||||
|
||||
DB_NAME: Joi.string()
|
||||
.required()
|
||||
.description('اسم قاعدة البيانات'),
|
||||
|
||||
// ── Redis ──────────────────────────────────────────────
|
||||
REDIS_HOST: Joi.string()
|
||||
.required()
|
||||
.description('مضيف Redis'),
|
||||
|
||||
REDIS_PORT: Joi.number()
|
||||
.port()
|
||||
.default(6400)
|
||||
.description('منفذ Redis'),
|
||||
|
||||
// ── JWT ────────────────────────────────────────────────
|
||||
JWT_SECRET: Joi.string()
|
||||
.min(64)
|
||||
.required()
|
||||
.description('مفتاح JWT الرئيسي (64 حرف كحد أدنى)'),
|
||||
|
||||
JWT_EXPIRY: Joi.string()
|
||||
.default('15m')
|
||||
.description('مدة صلاحية Access Token'),
|
||||
|
||||
JWT_REFRESH_SECRET: Joi.string()
|
||||
.min(64)
|
||||
.required()
|
||||
.description('مفتاح JWT للتجديد (مختلف عن الرئيسي)'),
|
||||
|
||||
JWT_REFRESH_EXPIRY: Joi.string()
|
||||
.default('7d')
|
||||
.description('مدة صلاحية Refresh Token'),
|
||||
|
||||
// ── Encryption ─────────────────────────────────────────
|
||||
ENCRYPTION_KEY: Joi.string()
|
||||
.length(64)
|
||||
.hex()
|
||||
.required()
|
||||
.description('مفتاح التشفير AES-256 (32 بايت = 64 حرف hex)'),
|
||||
|
||||
// ── JoFotara ───────────────────────────────────────────
|
||||
JOFOTARA_SANDBOX_URL: Joi.string()
|
||||
.uri()
|
||||
.required()
|
||||
.description('رابط بيئة الاختبار لجو فوترة'),
|
||||
|
||||
JOFOTARA_PROD_URL: Joi.string()
|
||||
.uri()
|
||||
.required()
|
||||
.description('رابط بيئة الإنتاج لجو فوترة'),
|
||||
|
||||
JOFOTARA_ENV: Joi.string()
|
||||
.valid('sandbox', 'production')
|
||||
.default('sandbox')
|
||||
.description('بيئة جو فوترة المستخدمة'),
|
||||
|
||||
// ── Gemini AI ──────────────────────────────────────────
|
||||
GEMINI_API_KEY: Joi.string()
|
||||
.required()
|
||||
.description('مفتاح Google Gemini API'),
|
||||
|
||||
GEMINI_MODEL: Joi.string()
|
||||
.default('gemini-2.0-flash-lite')
|
||||
.description('نموذج Gemini المستخدم'),
|
||||
|
||||
// ── File Storage ───────────────────────────────────────
|
||||
STORAGE_PATH: Joi.string()
|
||||
.default('./uploads')
|
||||
.description('مسار تخزين الملفات'),
|
||||
|
||||
// ── Email ──────────────────────────────────────────────
|
||||
RESEND_API_KEY: Joi.string()
|
||||
.required()
|
||||
.description('مفتاح Resend API للبريد الإلكتروني'),
|
||||
|
||||
EMAIL_FROM: Joi.string()
|
||||
.email()
|
||||
.required()
|
||||
.description('عنوان المرسل للبريد الإلكتروني'),
|
||||
|
||||
// ── Domain ─────────────────────────────────────────────
|
||||
DOMAIN: Joi.string()
|
||||
.required()
|
||||
.description('اسم النطاق الرئيسي'),
|
||||
});
|
||||
Reference in New Issue
Block a user