chore: أرشفة باك إند NestJS إلى backend-archive
قرار المالك 2026-07-27: الباك إند المعتمد صار باك إند سيرو PHP، ويُنقل إلى هذا المستودع كنسخة جديدة باسم «انطلق» على api.intaleqapp.com. backend/ → backend-archive/ (305 ملفاً، إعادة تسمية بلا تعديل محتوى) + README-ARCHIVE.md يوضّح سبب الأرشفة وسبب عدم الحذف: scripts/e2e-test.mjs هو أدق توثيق سلوكي لدورة الرحلة كاملة، ويبقى مرجعاً عند بناء الوحدات الناقصة في باك إند PHP (المحفظتان · الاستحقاقات · محرّك التسعير · الوحدات). مسارات backend/ في docs/*.md لم تُعدَّل عمداً — سجلّ تاريخي. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
75b80bd299
commit
fff76c949f
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* إعداد مركزي يقرأ متغيرات البيئة مع افتراضات العزل (راجع docs/14).
|
||||
*/
|
||||
export default () => ({
|
||||
env: process.env.NODE_ENV ?? 'development',
|
||||
apiPort: parseInt(process.env.API_PORT ?? '4010', 10),
|
||||
|
||||
db: {
|
||||
host: process.env.DB_HOST ?? 'postgres',
|
||||
port: parseInt(process.env.DB_PORT ?? '5432', 10),
|
||||
name: process.env.DB_NAME ?? 'tripz',
|
||||
user: process.env.DB_USER ?? 'tripz',
|
||||
password: process.env.DB_PASSWORD ?? 'change_me_strong',
|
||||
// بادئة الجداول لعزل Tripz عن باقي البرامج على نفس السيرفر
|
||||
tablePrefix: process.env.DB_TABLE_PREFIX ?? 'tripz_',
|
||||
synchronize: process.env.DB_SYNC === 'true',
|
||||
},
|
||||
|
||||
redis: {
|
||||
host: process.env.REDIS_HOST ?? 'redis',
|
||||
port: parseInt(process.env.REDIS_PORT ?? '6379', 10),
|
||||
// DB رقم غير الافتراضي 0 لعزل Tripz عن باقي البرامج
|
||||
db: parseInt(process.env.REDIS_DB ?? '3', 10),
|
||||
keyPrefix: process.env.REDIS_KEY_PREFIX ?? 'tripz:',
|
||||
},
|
||||
|
||||
queue: {
|
||||
prefix: process.env.QUEUE_PREFIX ?? 'tripz_',
|
||||
},
|
||||
|
||||
jwt: {
|
||||
secret: process.env.JWT_SECRET ?? 'change_me_jwt_secret',
|
||||
expires: process.env.JWT_EXPIRES ?? '15m',
|
||||
refreshExpires: process.env.JWT_REFRESH_EXPIRES ?? '30d',
|
||||
},
|
||||
|
||||
auth: {
|
||||
/**
|
||||
* وضع تطوير: رمز OTP ثابت `1234` يُطبع باللوغ بلا مناداة مزوّد (docs/07).
|
||||
*
|
||||
* **يفشل مُغلقاً عمداً**: لا يُفتح إلا بـ`OTP_DEV_MODE=true` حرفياً. كان
|
||||
* `!== 'false'` أي أن غياب المتغيّر — أو خطأً مطبعياً فيه، أو `OTP_DEV_MODE=0`
|
||||
* (ونصّ `'0'` ليس `'false'`) — يترك الإنتاج برمز ثابت يفتح **كل حساب في
|
||||
* المنصة**. الافتراض الآمن أن نرسل رسالة حقيقية، لا أن نفتح الباب.
|
||||
*/
|
||||
otpDevMode: process.env.OTP_DEV_MODE === 'true',
|
||||
otpTtl: parseInt(process.env.OTP_TTL ?? '300', 10),
|
||||
otpLength: parseInt(process.env.OTP_LENGTH ?? '4', 10),
|
||||
// ربط الجلسة بالجهاز (docs/17 — D2). مطفأ حتى يرسل فلاتر x-device-id؛
|
||||
// تفعيله قبل ذلك يقطع كل طلب مصادَق (نفس نمط PAYMENTS_REQUIRE_SIGNATURE).
|
||||
requireDeviceBinding: process.env.AUTH_REQUIRE_DEVICE_BINDING === 'true',
|
||||
},
|
||||
|
||||
maps: {
|
||||
// بلاطات انطلق تأتي من خوادم انطلق نفسها — لا نستضيفها (docs/25).
|
||||
tilesUrl: process.env.MAPS_TILES_URL ?? 'https://maps.intaleqapp.com',
|
||||
provider: process.env.MAPS_PROVIDER ?? 'antlaq',
|
||||
// خرائط انطلق (map-saas). مفتاح افتراضي + مفاتيح لكل دولة.
|
||||
baseUrl: process.env.MAPS_BASE_URL ?? 'https://map-saas.intaleqapp.com',
|
||||
apiKey: process.env.MAPS_API_KEY ?? '',
|
||||
apiKeyByCountry: {
|
||||
jo: process.env.MAPS_API_KEY_JO ?? process.env.MAPS_API_KEY ?? '',
|
||||
sy: process.env.MAPS_API_KEY_SY ?? process.env.MAPS_API_KEY ?? '',
|
||||
} as Record<string, string>,
|
||||
placesApiKey: process.env.MAPS_PLACES_API_KEY ?? process.env.MAPS_API_KEY ?? '',
|
||||
},
|
||||
|
||||
// Nabeh — إرسال OTP عبر واتساب.
|
||||
// توجيه OTP متعدد المزوّدين حسب الدولة (docs/17 — D5).
|
||||
otp: {
|
||||
// نصّ رسالة SMS (Kazumi/مصر). {code} يُستبدل بالرمز.
|
||||
smsTemplate: process.env.OTP_SMS_TEMPLATE ?? 'Your Tripz code is {code}',
|
||||
kazumi: {
|
||||
username: process.env.SMS_USERNAME ?? '',
|
||||
password: process.env.SMS_PASSWORD_EGYPT ?? '',
|
||||
sender: process.env.SMS_SENDER ?? '',
|
||||
},
|
||||
},
|
||||
|
||||
// الرحلات: كل كم يفحص كنس الرحلات المجدولة (docs/17 — B5).
|
||||
trips: {
|
||||
scheduleSweepMs: parseInt(process.env.TRIP_SCHEDULE_SWEEP_MS ?? '30000', 10),
|
||||
// R1 — كم يفحص رحلات searching عالقة (10 ثوانٍ كافية: لا ضغط على القاعدة).
|
||||
searchTimeoutSweepMs: parseInt(process.env.TRIP_SEARCH_TIMEOUT_SWEEP_MS ?? '10000', 10),
|
||||
// R1 — المهلة قبل إنهاء رحلة searching كـno_drivers (15 دقيقة كسيرو).
|
||||
searchTimeoutMs: parseInt(process.env.TRIP_SEARCH_TIMEOUT_MS ?? '900000', 10),
|
||||
// L4 — التسعير الديناميكي: كل كم يعيد حساب المضاعفات (3 دقائق افتراضياً).
|
||||
surgeSweepMs: parseInt(process.env.TRIP_SURGE_SWEEP_MS ?? '180000', 10),
|
||||
// L4 — الحدّ الأدنى بين تغييرين متتاليين للمضاعف (5 دقائق).
|
||||
surgeCooldownMs: parseInt(process.env.TRIP_SURGE_COOLDOWN_MS ?? '300000', 10),
|
||||
// L4 — حسّاسية الزيادة: 0.1 خفيفة، 0.3 متوسطة، 0.5 حادة.
|
||||
surgeSensitivity: parseFloat(process.env.TRIP_SURGE_SENSITIVITY ?? '0.3'),
|
||||
},
|
||||
|
||||
// المكافآت: كل كم يمسح الماسح الإحالات المؤهَّلة غير المصروفة (docs/17 — L5).
|
||||
// أبطأ من كنس الرحلات عمداً: هذا شبكة أمان لا مسار أساسي.
|
||||
rewards: {
|
||||
sweepMs: parseInt(process.env.REWARDS_SWEEP_MS ?? '60000', 10),
|
||||
},
|
||||
|
||||
nabeh: {
|
||||
baseUrl: process.env.NABEH_BASE_URL ?? 'https://nabeh.intaleqapp.com',
|
||||
email: process.env.NABEH_EMAIL ?? '',
|
||||
password: process.env.NABEH_PASSWORD ?? '',
|
||||
otpType: process.env.NABEH_OTP_TYPE ?? 'text',
|
||||
},
|
||||
|
||||
// ملاحظة: خرائط الاتصال الدولية صارت في common/phone/phone.service.ts
|
||||
// (docs/17 — D1) — مصدر واحد للحقيقة بدل نسختين قد تتباعدان.
|
||||
|
||||
// Gemini (رؤية) — قراءة الوثائق ومطابقة الوجه.
|
||||
gemini: {
|
||||
apiKey: process.env.GEMINI_API_KEY ?? '',
|
||||
model: process.env.GEMINI_MODEL ?? 'gemini-2.0-flash',
|
||||
},
|
||||
|
||||
// سرّ المنصة (super-admin) — لتعيين أول أدمن قبل وجود أدمن.
|
||||
platform: {
|
||||
secret: process.env.PLATFORM_SECRET ?? '',
|
||||
},
|
||||
|
||||
// تخزين ملفات الوثائق. baseUrl فارغ = محلي؛ يُضبط لسيرفر التوطين لاحقاً (docs/06).
|
||||
storage: {
|
||||
dir: process.env.STORAGE_DIR ?? '/app/storage',
|
||||
baseUrl: process.env.STORAGE_BASE_URL ?? '',
|
||||
},
|
||||
|
||||
// خدمة المواصلات (microservice مستقل)
|
||||
transit: {
|
||||
serviceUrl: process.env.TRANSIT_SERVICE_URL ?? 'http://transit:4020',
|
||||
},
|
||||
|
||||
// المدفوعات: توقيع HMAC على العمليات المالية (docs/17 — I6).
|
||||
// مطفأ حتى يوقّع تطبيق فلاتر؛ تفعيله قبل ذلك يقطع كل سحب.
|
||||
payments: {
|
||||
requireSignature: process.env.PAYMENTS_REQUIRE_SIGNATURE === 'true',
|
||||
},
|
||||
|
||||
// إشعارات FCM (ملف JSON لحزمة firebase-admin).
|
||||
fcm: {
|
||||
credentialsPath: process.env.GOOGLE_APPLICATION_CREDENTIALS ?? '',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
import 'reflect-metadata';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { config as loadEnv } from 'dotenv';
|
||||
|
||||
loadEnv();
|
||||
|
||||
/**
|
||||
* مصدر بيانات TypeORM — يُستخدم للهجرات و runtime.
|
||||
* entityPrefix يضمن أن كل جداول Tripz تبدأ بـ tripz_ لعزلها على السيرفر المشترك.
|
||||
*/
|
||||
export const AppDataSource = new DataSource({
|
||||
type: 'postgres',
|
||||
host: process.env.DB_HOST ?? 'postgres',
|
||||
port: parseInt(process.env.DB_PORT ?? '5432', 10),
|
||||
database: process.env.DB_NAME ?? 'tripz',
|
||||
username: process.env.DB_USER ?? 'tripz',
|
||||
password: process.env.DB_PASSWORD ?? 'change_me_strong',
|
||||
entityPrefix: process.env.DB_TABLE_PREFIX ?? 'tripz_',
|
||||
synchronize: false,
|
||||
entities: [__dirname + '/../database/entities/*.entity.{ts,js}'],
|
||||
migrations: [__dirname + '/../database/migrations/*.{ts,js}'],
|
||||
});
|
||||
Reference in New Issue
Block a user