#!/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 # # ⚠️ الخطوات الموسومة [Q] تعتمد على مشروع فلاتر (المجموعة Q) الذي لم يُبنَ بعد. # البنية والعقد (المانيفست) جاهزان الآن؛ تُوصَل هذه الخطوات عند وصول Q. # ========================================================================== set -euo pipefail SLUG="${1:?الاستعمال: generate-tenant-app.sh }" 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] معلّقة حتى مشروع فلاتر)."