الهدف الأساسي: السوبر-أدمن ينشئ مستأجراً كاملاً (اسم/لوغو/دولة/دفع/باقة/ ميزات/bundle IDs) ويولّد تطبيقه. الباك إند (خلف PlatformGuard): - POST /admin/tenants/provision — تزويد بضربة واحدة - GET /admin/tenants/:id/summary + /app-manifest (يستهلكه سكربت البناء) - PATCH .../branding + .../payment-methods - POST /admin/tenants/:id/logo (رفع) + GET /tenant/logo/:slug عام **يخدم أصل الهوية فقط لا مجلد التخزين كاملاً** — وإلا سُرّبت صور وثائق الهوية الحساسة بمفاتيحها - كتالوج payment-methods.ts (cash/wallet/cliq/zaincash/paymob/mtn/ syriatel/shamcash حسب الدولة) + تصفية المخترع - GET /admin/features يرجع الميزات ووسائل الدفع للكتالوج الواجهة: dashboards/superadmin-web/index.html — SPA مكتفية ذاتياً (vanilla JS، بلا خطوة بناء)، سرّ المنصة في sessionStorage، RTL. تُخدَم كملف ثابت. سكربت التوليد: scripts/generate-tenant-app.sh — يجلب المانيفست ويضبط الهيكل؛ خطوات فلاتر موسومة [Q] تُوصَل عند بناء مشروع فلاتر. اختبار: provision-test.mjs (يثبت الحارس + التزويد + تصفية الدفع + الاستحقاقات + المانيفست). لا هجرة — settings/branding jsonb موجودان. القرار: اللوحات ويب (لا فلاتر) — تحديث فوري، سطح مكتب، معيار الصناعة. البدء بـN (طبقة الـSaaS) قرار المالك. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
79 lines
5.4 KiB
Bash
Executable File
79 lines
5.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ==========================================================================
|
|
# توليد تطبيق مستأجر واحد من مانيفست الباك إند (docs/22 — N3).
|
|
#
|
|
# سكربت واحد يأخذ slug المستأجر → يجلب مانيفسته → يضبط bundle ID والأيقونات
|
|
# والـsplash من اللوغو، يحقن FCM، يربط إضافات Kotlin/C++ الأصيلة (overlay ·
|
|
# method channels · NDK) المبنية على bundle ID، يبني، ويسجّل/يدفع عبر Shorebird.
|
|
#
|
|
# الاستعمال:
|
|
# PLATFORM_SECRET=xxx API=https://tripz-api.intaleqapp.com/api \
|
|
# ./scripts/generate-tenant-app.sh <slug> <rider|driver>
|
|
#
|
|
# ⚠️ الخطوات الموسومة [Q] تعتمد على مشروع فلاتر (المجموعة Q) الذي لم يُبنَ بعد.
|
|
# البنية والعقد (المانيفست) جاهزان الآن؛ تُوصَل هذه الخطوات عند وصول Q.
|
|
# ==========================================================================
|
|
set -euo pipefail
|
|
|
|
SLUG="${1:?الاستعمال: generate-tenant-app.sh <slug> <rider|driver>}"
|
|
APP_KIND="${2:-rider}" # rider | driver
|
|
API="${API:?اضبط API=https://tripz-api.intaleqapp.com/api}"
|
|
SECRET="${PLATFORM_SECRET:?اضبط PLATFORM_SECRET}"
|
|
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
APP_DIR="$ROOT/apps/$APP_KIND" # [Q] مشروع فلاتر لكل نوع
|
|
WORK="$ROOT/.build/$SLUG-$APP_KIND"
|
|
|
|
echo "▶ توليد تطبيق [$APP_KIND] للمستأجر [$SLUG]"
|
|
|
|
# ── 1. جلب المانيفست من الباك إند (جاهز الآن) ──────────────────────────
|
|
echo " • جلب المانيفست…"
|
|
# نحصل على tenant id من القائمة ثم المانيفست
|
|
TENANT_ID="$(curl -fsSL -H "x-platform-secret: $SECRET" "$API/admin/tenants" \
|
|
| node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{const t=JSON.parse(s).find(x=>x.slug==='$SLUG');if(!t){console.error('مستأجر غير موجود: $SLUG');process.exit(1)}process.stdout.write(t.id)})")"
|
|
|
|
MANIFEST="$(curl -fsSL -H "x-platform-secret: $SECRET" "$API/admin/tenants/$TENANT_ID/app-manifest")"
|
|
echo "$MANIFEST" | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{const m=JSON.parse(s);console.log(' الاسم:',m.app_name,'| bundleAndroid:',m.bundle_id_android,'| دولة:',m.country_pack)})"
|
|
|
|
val() { echo "$MANIFEST" | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{process.stdout.write(String(JSON.parse(s).$1 ?? ''))})"; }
|
|
APP_NAME="$(val app_name)"
|
|
BID_ANDROID="$(val bundle_id_android)"
|
|
BID_IOS="$(val bundle_id_ios)"
|
|
COUNTRY="$(val country_pack)"
|
|
|
|
[ -z "$BID_ANDROID" ] && { echo " ✗ bundle_id_android غير مضبوط في المانيفست — اضبطه من لوحة السوبر-أدمن أولاً"; exit 1; }
|
|
|
|
# ── 2. تحضير نسخة عمل من مشروع فلاتر ───────────────────────────────────
|
|
if [ ! -d "$APP_DIR" ]; then
|
|
echo " ⚠️ [Q] مشروع فلاتر $APP_DIR غير موجود بعد — تخطّي خطوات البناء."
|
|
echo " المانيفست جاهز؛ تُوصَل خطوات فلاتر عند بناء المجموعة Q."
|
|
exit 0
|
|
fi
|
|
rm -rf "$WORK"; mkdir -p "$(dirname "$WORK")"; cp -r "$APP_DIR" "$WORK"
|
|
|
|
# ── 3. ضبط bundle ID (أندرويد + iOS) ───────────────────────────────────
|
|
echo " • ضبط bundle ID…"
|
|
# [Q] applicationId في build.gradle، و PRODUCT_BUNDLE_IDENTIFIER في iOS.
|
|
# الإضافات الأصيلة (overlay/NDK/method-channel) مبنية على bundle ID —
|
|
# تُحدَّث مراجعها هنا. راجع apps/*/android و apps/*/ios.
|
|
# sed -i "s/applicationId \".*\"/applicationId \"$BID_ANDROID\"/" "$WORK/android/app/build.gradle"
|
|
|
|
# ── 4. الأيقونات و splash من اللوغو ────────────────────────────────────
|
|
echo " • توليد الأيقونات و splash من اللوغو…"
|
|
curl -fsSL "$API/tenant/logo/$SLUG" -o "$WORK/assets/logo.png" 2>/dev/null || echo " (لا لوغو مرفوع — يُستعمل الافتراضي)"
|
|
# [Q] flutter_launcher_icons + flutter_native_splash من assets/logo.png
|
|
|
|
# ── 5. حقن FCM + إعداد المستأجر ────────────────────────────────────────
|
|
echo " • حقن إعداد المستأجر ($COUNTRY)…"
|
|
# [Q] نسخ google-services.json / GoogleService-Info.plist الخاص بالمستأجر.
|
|
# BASE_URL و TENANT عبر --dart-define عند البناء.
|
|
|
|
# ── 6. البناء + Shorebird ──────────────────────────────────────────────
|
|
echo " • البناء وتسجيل Shorebird…"
|
|
# [Q] أول مرة: shorebird init (يسجّل app_id لهذا bundle ID في حساب Shorebird).
|
|
# التحديثات: shorebird release / shorebird patch.
|
|
# ( cd "$WORK" && shorebird release android \
|
|
# --dart-define=BASE_URL=${API} --dart-define=TENANT=$SLUG )
|
|
|
|
echo "✅ اكتمل توليد [$APP_KIND] لـ[$SLUG] (الخطوات الموسومة [Q] معلّقة حتى مشروع فلاتر)."
|