تخطَّ إلى المحتوى

معمارية Natives

@f5-sales-demo/pi-natives هي حزمة مكونة من ثلاث طبقات:

  1. طبقة الغلاف/API بـ TypeScript تُعرض نقاط دخول مستقرة بـ JS/TS.
  2. طبقة تحميل/التحقق من الإضافة تحل وتُتحقق من الملف الثنائي .node لوقت التشغيل الحالي.
  3. طبقة وحدة Rust N-API تُنفذ العناصر الأولية الحساسة للأداء المُصدَّرة إلى JS.

هذا المستند هو الأساس لمستندات أعمق على مستوى الوحدات.

  • packages/natives/src/index.ts
  • packages/natives/src/native.ts
  • packages/natives/src/bindings.ts
  • packages/natives/src/embedded-addon.ts
  • packages/natives/scripts/build-native.ts
  • packages/natives/scripts/embed-native.ts
  • packages/natives/package.json
  • crates/pi-natives/src/lib.rs

الطبقة الأولى: طبقة الغلاف/API بـ TypeScript

Section titled “الطبقة الأولى: طبقة الغلاف/API بـ TypeScript”

packages/natives/src/index.ts هو الحاوية العامة. يُجمّع الصادرات حسب نطاق القدرات ويُعيد تصدير الأغلفة المُكتَّبة بدلاً من كشف ارتباطات N-API الخام مباشرةً.

المجموعات الرئيسية الحالية:

  • عناصر البحث/النص الأولية: grep، glob، text، highlight
  • عناصر التنفيذ/العمليات/الطرفية الأولية: shell، pty، ps، keys
  • عناصر النظام/الوسائط/التحويل الأولية: image، html، clipboard، system-info، work

يُعرّف packages/natives/src/bindings.ts عقد الواجهة الأساسية:

  • تبدأ NativeBindings بأعضاء مشتركة (cancelWork(id: number))
  • تُضاف ارتباطات خاصة بكل وحدة عن طريق دمج الإعلانات من ملف types.ts الخاص بكل وحدة
  • تُوحّد Cancellable خيارات المهلة الزمنية وإشارة الإلغاء للأغلفة التي تُعرض إمكانية الإلغاء

العقد المضمون (مواجهة API): يستورد المستهلكون من @f5-sales-demo/pi-natives ويستخدمون الأغلفة المُكتَّبة.

تفاصيل التنفيذ (قابلة للتغيير): دمج الإعلانات وتخطيط الغلاف الداخلي (src/<module>/index.ts، src/<module>/types.ts).

الطبقة الثانية: تحميل الإضافة والتحقق منها

Section titled “الطبقة الثانية: تحميل الإضافة والتحقق منها”

يمتلك packages/natives/src/native.ts اختيار الإضافة في وقت التشغيل، والاستخراج الاختياري، والتحقق من صحة الصادرات.

  • علامة المنصة هي "${process.platform}-${process.arch}".
  • العلامات المدعومة حالياً هي:
    • linux-x64
    • linux-arm64
    • darwin-x64
    • darwin-arm64
    • win32-x64
  • يمكن لـ x64 استخدام متغيرات المعالج:
    • modern (يدعم AVX2)
    • baseline (احتياطي)
  • تستخدم المعماريات غير x64 اسم الملف الافتراضي (بدون لاحقة متغير).

استراتيجية تسمية الملفات:

  • الإصدار: pi_natives.<platform>-<arch>.node
  • إصدار متغير x64: pi_natives.<platform>-<arch>-modern.node و/أو ...-baseline.node
  • يُفعّل PI_DEV تشخيصات المُحمّل دون تغيير أسماء ملفات الإضافة

اكتشاف المتغير الخاص بالمنصة

Section titled “اكتشاف المتغير الخاص بالمنصة”

بالنسبة لـ x64، يستخدم اختيار المتغير:

  • Linux: /proc/cpuinfo
  • macOS: sysctl machdep.cpu.leaf7_features / machdep.cpu.features
  • Windows: فحص PowerShell لـ System.Runtime.Intrinsics.X86.Avx2

يمكن لـ PI_NATIVE_VARIANT إجبار اختيار modern أو baseline صراحةً.

نموذج توزيع الملفات الثنائية واستخراجها

Section titled “نموذج توزيع الملفات الثنائية واستخراجها”

يتضمن packages/natives/package.json كلاً من src وnative في الملفات المنشورة. يخزّن دليل native/ القطع الأثرية المُبنية مسبقاً للمنصات المختلفة.

بالنسبة للملفات الثنائية المُجمَّعة (علامات PI_COMPILED أو Bun لوقت التشغيل المدمج)، يكون سلوك المُحمّل كالتالي:

  1. التحقق من مسار ذاكرة التخزين المؤقت للمستخدم ذات الإصدار: <getNativesDir()>/<packageVersion>/...
  2. التحقق من موقع الملف الثنائي المُجمَّع القديم:
    • Windows: %LOCALAPPDATA%/xcsh (احتياطي %USERPROFILE%/AppData/Local/xcsh)
    • غير Windows: ~/.local/bin
  3. الرجوع إلى المرشحين من دليل native/ المُعبَّأ ودليل الملف القابل للتنفيذ

إذا كان بيان الإضافة المدمجة موجوداً (embedded-addon.ts المُنشأ بواسطة scripts/embed-native.ts)، يمكن لـ native.ts تجسيد الملف الثنائي المدمج المطابق في دليل ذاكرة التخزين المؤقت ذات الإصدار قبل التحميل.

بعد require(candidate)، يتحقق validateNative(...) من الصادرات المطلوبة (على سبيل المثال grep، glob، highlightCode، PtySession، Shell، getSystemInfo، getWorkProfile، invalidateFsScanCache).

مسارات الفشل صريحة:

  • علامة منصة غير مدعومة: يرمي خطأً مع قائمة المنصات المدعومة
  • لا يوجد مرشح قابل للتحميل: يرمي خطأً مع جميع المسارات المُجرَّبة وتلميحات المعالجة
  • صادرات مفقودة: يرمي خطأً مع الأسماء المفقودة بالضبط وأمر إعادة البناء
  • أخطاء استخراج الإضافة المدمجة: يسجّل أخطاء الدليل/الكتابة ويُدرجها في تشخيصات التحميل النهائية

العقد المضمون (مواجهة API): إما أن ينجح تحميل الإضافة بمجموعة ارتباطات مُتحقَّق منها، أو يفشل فوراً مع نص خطأ قابل للتنفيذ.

تفاصيل التنفيذ (قابلة للتغيير): ترتيب بحث المرشحين الدقيق وترتيب مسار الاحتياطي للملف الثنائي المُجمَّع.

الطبقة الثالثة: طبقة وحدة Rust N-API

Section titled “الطبقة الثالثة: طبقة وحدة Rust N-API”

crates/pi-natives/src/lib.rs هو وحدة Rust الرئيسية التي تُعلن عن ملكية الوحدة المُصدَّرة:

  • clipboard
  • fd
  • fs_cache
  • glob
  • glob_util
  • grep
  • highlight
  • html
  • image
  • keys
  • prof
  • ps
  • pty
  • shell
  • system_info
  • task
  • text

تُنفّذ هذه الوحدات رموز N-API المُستهلَكة والمُتحقَّق منها بواسطة native.ts. تُعرض الأسماء على مستوى JS من خلال أغلفة TS في packages/natives/src.

العقد المضمون (مواجهة API): يجب أن تتطابق صادرات وحدة Rust مع أسماء الارتباطات المُتوقَّعة بواسطة validateNative ووحدات الغلاف.

تفاصيل التنفيذ (قابلة للتغيير): التحليل الداخلي لوحدة Rust وحدود وحدة المساعد (glob_util، task، إلخ).

على مستوى المعمارية، تُقسَّم الملكية كالتالي:

  • ملكية غلاف/API بـ TypeScript (packages/natives/src)
    • تجميع API العام، وكتابة الخيارات، وبيئة JS المستقرة
    • سطح الإلغاء (timeoutMs، AbortSignal) المُعرَّض للمستدعين
  • ملكية المُحمّل (packages/natives/src/native.ts)
    • اختيار الملف الثنائي في وقت التشغيل
    • اختيار متغير المعالج ومعالجة التجاوز
    • استخراج الملف الثنائي المُجمَّع وفحص المرشحين
    • التحقق الصارم من صادرات الملف الأصلي المطلوبة
  • ملكية Rust (crates/pi-natives/src)
    • التنفيذ الخوارزمي وعلى مستوى النظام
    • السلوك الأصلي للمنصة والمنطق الحساس للأداء
    • تنفيذ رموز N-API التي تستهلكها أغلفة TS

تدفق وقت التشغيل (عالي المستوى)

Section titled “تدفق وقت التشغيل (عالي المستوى)”
  1. يستورد المستهلك من @f5-sales-demo/pi-natives.
  2. تستدعي وحدة الغلاف ارتباط native أحادي النسخة.
  3. يختار native.ts الملف الثنائي المرشح للمنصة/المعمارية/المتغير.
  4. يحدث استخراج الملف الثنائي المدمج الاختياري للتوزيعات المُجمَّعة.
  5. يُحمَّل الإضافة ويُتحقَّق من مجموعة الصادرات.
  6. يُعيد الغلاف نتائج مُكتَّبة إلى المستدعي.
  • الإضافة الأصلية: ملف ثنائي .node يُحمَّل عبر Node-API (N-API).
  • علامة المنصة: زوج وقت التشغيل platform-arch (على سبيل المثال darwin-arm64).
  • المتغير: نكهة بناء خاصة بمعالج x64 (modern بـ AVX2، baseline احتياطي).
  • الغلاف: دالة/فئة TS تُوفر API مُكتَّبة فوق الصادرات الأصلية الخام.
  • دمج الإعلانات: أسلوب TS تستخدمه ملفات types.ts الخاصة بالوحدات لتوسيع NativeBindings.
  • وضع الملف الثنائي المُجمَّع: وضع وقت التشغيل حيث تكون واجهة سطر الأوامر مُجمَّعة ويتم تحليل الإضافات الأصلية من مسارات الاستخراج/ذاكرة التخزين المؤقت بدلاً من المسارات المحلية للحزمة فقط.
  • الإضافة المدمجة: بيانات وصفية للقطعة الأثرية للبناء ومراجع الملفات المُنشأة في embedded-addon.ts حتى تتمكن الملفات الثنائية المُجمَّعة من استخراج حمولات .node المطابقة.
  • بوابة التحقق: فحص validateNative(...) الذي يرفض الملفات الثنائية القديمة/غير المتطابقة التي تفتقر إلى الصادرات المطلوبة.