توفر حزمةDocumentation Index
Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
Use this file to discover all available pages before exploring further.
twenty-sdk لبنات بناء مضبوطة الأنواع لإنشاء تطبيقك. تغطي هذه الصفحة كل نوع كيان وكل عميل واجهة برمجة تطبيقات متاح في SDK.
دوال DefineEntity
يوفّر SDK دوالًا لتعريف كيانات تطبيقك. يجب عليك استخدامexport default defineEntity({...}) لكي يكتشف SDK الكيانات الخاصة بك. تتحقق هذه الدوال من تكوينك وقت البناء وتوفّر إكمالًا تلقائيًا في بيئة التطوير وأمان الأنواع.
export default defineEntity(...) بغض النظر عن مكان وجود الملف. تجميع الملفات حسب النوع (مثلًا، logic-functions/ وroles/) هو مجرّد عرف، وليس متطلبًا.defineRole
تهيئة صلاحيات الدور والوصول إلى الكائنات
defineRole
تهيئة صلاحيات الدور والوصول إلى الكائنات
defineApplication
تهيئة بيانات التعريف للتطبيق (مطلوب، واحد لكل تطبيق)
defineApplication
تهيئة بيانات التعريف للتطبيق (مطلوب، واحد لكل تطبيق)
defineApplication يصف:- الهوية: المعرّفات، اسم العرض، والوصف.
- الأذونات: أيُّ دورٍ تستخدمه وظائفه ومكوّناته الأمامية.
- (اختياري) المتغيرات: أزواج مفتاح-قيمة تُعرض لوظائفك كمتغيرات بيئة.
- (اختياري) دوال ما قبل التثبيت/ما بعد التثبيت: دوال منطقية تعمل قبل التثبيت أو بعده.
- حقول
universalIdentifierهي معرّفات حتمية تملكها أنت. أنشِئها مرة واحدة واحتفظ بها ثابتة عبر عمليات المزامنة. applicationVariablesتصبح متغيرات بيئة لوظائفك ومكوّناتك الأمامية (على سبيل المثال،DEFAULT_RECIPIENT_NAMEمتاح كـprocess.env.DEFAULT_RECIPIENT_NAME).defaultRoleUniversalIdentifierيجب أن يُشير إلى دور مُعرَّف باستخدامdefineRole()(انظر أعلاه).- يتم اكتشاف دوال ما قبل التثبيت وما بعده تلقائيًا أثناء بناء البيان — لا حاجة للإشارة إليها في
defineApplication().
بيانات التعريف لسوق التطبيقات
إذا كنت تخطط لـ نشر تطبيقك، فإن هذه الحقول الاختيارية تتحكّم في كيفية ظهوره في السوق:| الحقل | الوصف |
|---|---|
author | اسم المؤلف أو الشركة |
category | فئة التطبيق لتصفية سوق التطبيقات |
logoUrl | مسار شعار تطبيقك (مثلًا، public/logo.png) |
screenshots | مصفوفة لمسارات لقطات الشاشة (مثلًا، public/screenshot-1.png) |
aboutDescription | وصف ماركداون أطول لعلامة التبويب “حول”. إذا لم يتم تضمينه، يستخدم السوق ملف README.md الخاص بالحزمة من npm |
websiteUrl | رابط إلى موقعك الإلكتروني |
termsUrl | رابط إلى شروط الخدمة |
emailSupport | عنوان البريد الإلكتروني للدعم |
issueReportUrl | رابط إلى متتبّع المشاكل |
الأدوار والصلاحيات
يُحدّد الحقلdefaultRoleUniversalIdentifier في application-config.ts الدور الافتراضي الذي تستخدمه وظائف المنطق والمكوّنات الأمامية في تطبيقك. راجع defineRole أعلاه للحصول على التفاصيل.- رمز وقت التشغيل المحقون باسم
TWENTY_APP_ACCESS_TOKENمستمد من هذا الدور. - العميل مضبوط الأنواع مقيَّد بالأذونات الممنوحة لذلك الدور.
- اتبع مبدأ أقل الامتياز: أنشئ دورًا مخصصًا يضم فقط الأذونات التي تحتاجها وظائفك.
الدور الافتراضي للوظيفة
عند توليد تطبيق جديد بالقالب، ينشئ CLI ملفّ دور افتراضي:universalIdentifier لهذا الدور في application-config.ts باسم defaultRoleUniversalIdentifier:- *.role.ts يحدد ما يمكن أن يفعله الدور.
- application-config.ts يشير إلى ذلك الدور بحيث ترث وظائفك أذوناته.
- ابدأ من الدور المُنشأ بالقالب، ثم قيّده تدريجيًا باتباع مبدأ أقل الامتياز.
- استبدل
objectPermissionsوfieldPermissionsبالكائنات والحقول التي تحتاجها وظائفك فعليًا. permissionFlagsتتحكم في الوصول إلى القدرات على مستوى المنصة. اجعلها في حدّها الأدنى.- اطّلع على مثال عملي:
hello-world/src/roles/function-role.ts.
defineObject
تعريف كائنات مخصصة مع حقول
defineObject
تعريف كائنات مخصصة مع حقول
defineObject() لتعريف كائنات مع تحقق مدمج:- استخدم
defineObject()للحصول على تحقق مدمج ودعم أفضل من IDE. universalIdentifierيجب أن يكون فريدًا وثابتًا عبر عمليات النشر.- يتطلب كل حقل
nameوtypeوlabelومعرّفuniversalIdentifierثابتًا خاصًا به. - المصفوفة
fieldsاختيارية — يمكنك تعريف كائنات بدون حقول مخصصة. - يمكنك إنشاء كائنات جديدة باستخدام
yarn twenty add، والذي يرشدك خلال التسمية والحقول والعلاقات.
id وname وcreatedAt وupdatedAt وcreatedBy وupdatedBy وdeletedAt.
لا تحتاج إلى تعريف هذه في مصفوفة fields — أضف فقط حقولك المخصصة.
يمكنك تجاوز الحقول الافتراضية من خلال تعريف حقل بالاسم نفسه في مصفوفة fields الخاصة بك،
لكن هذا غير مستحسن.defineField — الحقول القياسية
وسّع الكائنات الموجودة بحقول إضافية
defineField — الحقول القياسية
وسّع الكائنات الموجودة بحقول إضافية
defineField() لإضافة حقول إلى كائنات لا تملكها — مثل كائنات Twenty القياسية (Person, Company, etc.) أو كائنات من تطبيقات أخرى. على خلاف الحقول المضمّنة في defineObject()، تتطلّب الحقول المستقلة objectUniversalIdentifier لتحديد الكائن الذي تقوم بتوسيعه:objectUniversalIdentifierيحدّد الكائن الهدف. بالنسبة للكائنات القياسية، استخدمSTANDARD_OBJECT_UNIVERSAL_IDENTIFIERSالمُصدَّر منtwenty-sdk.- عند تعريف الحقول بشكل مضمّن في
defineObject()، لا تحتاج إلىobjectUniversalIdentifier— إذ يُورَّث من الكائن الأب. defineField()هي الطريقة الوحيدة لإضافة حقول إلى كائنات لم تُنشئها باستخدامdefineObject().
defineField — حقول العلاقات
وصِل الكائنات معًا بعلاقات ثنائية الاتجاه
defineField — حقول العلاقات
وصِل الكائنات معًا بعلاقات ثنائية الاتجاه
| نوع العلاقة | الوصف | هل لديه مفتاح خارجي؟ |
|---|---|---|
MANY_TO_ONE | تشير العديد من سجلات هذا الكائن إلى سجل واحد من الهدف | نعم (joinColumnName) |
ONE_TO_MANY | يحتوي سجل واحد من هذا الكائن على العديد من سجلات الهدف | لا (الجانب العكسي) |
كيف تعمل العلاقات
تتطلّب كل علاقة حقلين يشيران إلى بعضهما البعض:- جانب MANY_TO_ONE — يوجد على الكائن الذي يحمل المفتاح الخارجي
- جانب ONE_TO_MANY — يوجد على الكائن الذي يملك المجموعة
FieldType.RELATION ويُحيل كلٌ منهما إلى الآخر عبر relationTargetFieldMetadataUniversalIdentifier.مثال: البطاقة البريدية لديها العديد من المستلمين
افترض أنPostCard يمكن إرسالها إلى العديد من سجلات PostCardRecipient. ينتمي كل مستلم إلى بطاقة بريدية واحدة بالضبط.الخطوة 1: عرّف جانب ONE_TO_MANY على PostCard (جانب “الواحد”):universalIdentifier الخاص بالآخر. لتجنّب مشكلات الاستيراد الدائري، صدّر معرّفات الحقول كثوابت مسمّاة من كل ملف، واستوردها في الملف الآخر. يقوم نظام البناء بحلّها في وقت الترجمة.الربط مع الكائنات القياسية
لإنشاء علاقة مع كائن Twenty مضمّن (Person, Company, etc.)، استخدمSTANDARD_OBJECT_UNIVERSAL_IDENTIFIERS:خصائص حقل العلاقة
| الخاصية | مطلوب | الوصف |
|---|---|---|
type | نعم | يجب أن يكون FieldType.RELATION |
relationTargetObjectMetadataUniversalIdentifier | نعم | قيمة universalIdentifier للكائن الهدف |
relationTargetFieldMetadataUniversalIdentifier | نعم | قيمة universalIdentifier للحقل المطابق على الكائن الهدف |
universalSettings.relationType | نعم | RelationType.MANY_TO_ONE أو RelationType.ONE_TO_MANY |
universalSettings.onDelete | MANY_TO_ONE فقط | ماذا يحدث عند حذف السجل المشار إليه: CASCADE، SET_NULL، RESTRICT، أو NO_ACTION |
universalSettings.joinColumnName | MANY_TO_ONE فقط | اسم عمود قاعدة البيانات للمفتاح الخارجي (مثل postCardId) |
حقول العلاقات المضمّنة في defineObject
يمكنك أيضًا تعريف حقول العلاقات مباشرةً داخلdefineObject(). في هذه الحالة، احذف objectUniversalIdentifier — إذ يُورَّث من الكائن الأب:defineLogicFunction
عرّف الدوال المنطقية ومشغّلاتها
defineLogicFunction
عرّف الدوال المنطقية ومشغّلاتها
defineLogicFunction() لتصدير تكوين مع معالج ومشغّلات اختيارية.- httpRoute: يعرِض وظيفتك على مسار وطريقة HTTP تحت نقطة النهاية
/s/:
مثال:path: '/post-card/create'يمكن استدعاؤه عبرhttps://your-twenty-server.com/s/post-card/create
- cron: يشغّل وظيفتك على جدول باستخدام تعبير CRON.
- databaseEvent: يعمل على أحداث دورة حياة كائنات مساحة العمل. عندما تكون عملية الحدث هي
updated، يمكن تحديد الحقول المحددة المراد الاستماع إليها في مصفوفةupdatedFields. إذا تُركت غير معرّفة أو فارغة، فسيؤدي أي تحديث إلى تشغيل الدالة.
مثال:person.updated،*.created،company.*
حمولة مشغل المسار
عندما يستدعي مُشغِّل المسار وظيفتك المنطقية، فإنها تتلقّى كائنRoutePayload الذي يتبع صيغة AWS HTTP API v2.
استورد نوع RoutePayload من twenty-sdk:RoutePayload على البنية التالية:| الخاصية | النوع | الوصف | مثال |
|---|---|---|---|
headers | Record\<string, string | undefined> | رؤوس HTTP (فقط تلك المدرجة في forwardedRequestHeaders) | انظر القسم أدناه |
queryStringParameters | Record\<string, string | undefined> | معلمات سلسلة الاستعلام (تُضمّ القيم المتعددة باستخدام فواصل) | /users?ids=1&ids=2&ids=3&name=Alice -> { ids: '1,2,3', name: 'Alice' } |
pathParameters | Record\<string, string | undefined> | معلمات المسار المستخرجة من نمط المسار | /users/:id, /users/123 -> { id: '123' } |
المحتوى | object | null | جسم الطلب المُحلَّل (JSON) | { id: 1 } -> { id: 1 } |
isBase64Encoded | قيمة منطقية | ما إذا كان جسم الطلب مُرمَّزًا بترميز base64 | |
requestContext.http.method | string | طريقة HTTP (GET, POST, PUT, PATCH, DELETE) | |
requestContext.http.path | string | المسار الخام للطلب |
forwardedRequestHeaders
افتراضيًا، لا تُمرَّر رؤوس HTTP من الطلبات الواردة إلى دالتك المنطقية لأسباب أمنية. للوصول إلى رؤوس محددة، أدرِجها في مصفوفةforwardedRequestHeaders:event.headers['content-type']).إتاحة دالة كأداة
يمكن إتاحة الدوال المنطقية بوصفها أدوات لوكلاء الذكاء الاصطناعي وسير العمل. عند تمييز دالة كأداة، تصبح قابلة للاكتشاف بواسطة ميزات الذكاء الاصطناعي في Twenty ويمكن استخدامها في أتمتة سير العمل.لتمييز دالة منطقية كأداة، عيِّنisTool: true:- يمكنك دمج
isToolمع المشغِّلات — إذ يمكن للدالة أن تكون أداة (قابلة للاستدعاء من قِبل وكلاء الذكاء الاصطناعي) وأن تُشغَّل بواسطة الأحداث في الوقت نفسه. toolInputSchema(اختياري): كائن JSON Schema يصف المعلمات التي تقبلها دالتك. يُحسَب المخطط تلقائيًا من خلال تحليل ساكن للشيفرة المصدرية، ولكن يمكنك تعيينه صراحةً:
description جيدًا. يعتمد وكلاء الذكاء الاصطناعي على حقل description الخاص بالدالة لتحديد وقت استخدام الأداة. كن محددًا بشأن ما تفعله الأداة ومتى ينبغي استدعاؤها.definePostInstallLogicFunction
تعريف دالة منطقية لما بعد التثبيت (واحدة لكل تطبيق)
definePostInstallLogicFunction
تعريف دالة منطقية لما بعد التثبيت (واحدة لكل تطبيق)
- تستخدم دوال ما بعد التثبيت
definePostInstallLogicFunction()— وهو إصدار متخصص يستبعد إعدادات المُشغِّل (cronTriggerSettingsوdatabaseEventTriggerSettingsوhttpRouteTriggerSettingsوisTool). - يتلقى المعالج
InstallPayloadيحتوي على{ previousVersion?: string; newVersion: string }— حيث إنnewVersionهو الإصدار الجاري تثبيته، وpreviousVersionهو الإصدار الذي كان مُثبّتًا سابقًا (أوundefinedعند التثبيت الأولي). استخدم هذه القيم للتمييز بين عمليات التثبيت الجديدة والترقيات ولتشغيل منطق الترحيل الخاص بالإصدار. - موعد تشغيل الخطاف: في عمليات التثبيت الجديدة فقط، افتراضيًا. مرّر
shouldRunOnVersionUpgrade: trueإذا كنت تريد تشغيله أيضًا عند ترقية التطبيق من إصدار سابق. عند إغفاله، تكون القيمة الافتراضية للعلمfalse، وتتجاوز الترقيات هذا الخطاف. - نموذج التنفيذ — غير متزامن افتراضيًا، والتزامني اختياري: يتحكّم العلم
shouldRunSynchronouslyفي كيفية تنفيذ ما بعد التثبيت.shouldRunSynchronously: false(الإعداد الافتراضي) — يتم إدراج الخطاف في قائمة الرسائل معretryLimit: 3ويعمل بشكل غير متزامن داخل عامل عمل. يعود ردّ التثبيت بمجرد وضع المهمة في الطابور، لذا فإن معالجًا بطيئًا أو متعطلًا لا يحجب المستدعي. سيُجرِّب العامل إعادة المحاولة حتى ثلاث مرات. استخدم هذا للمهام طويلة التشغيل — بَذر مجموعات بيانات كبيرة، استدعاء واجهات برمجة تطبيقات خارجية بطيئة، تهيئة موارد خارجية، أو أي شيء قد يتجاوز نافذة استجابة HTTP المعقولة.shouldRunSynchronously: true— يُنفّذ الخطاف ضمن تدفّق التثبيت مباشرةً (نفس المنفِّذ كما قبل التثبيت). يَحجُب طلب التثبيت حتى ينتهي المعالج، وإذا رمى استثناءً، سيتلقى مستدعي التثبيتPOST_INSTALL_ERROR. لا توجد محاولات إعادة تلقائية. استخدم هذا للمهام السريعة التي يجب إكمالها قبل الاستجابة — مثل إظهار خطأ تحقق للمستخدم، أو إعداد سريع سيعتمد عليه العميل مباشرةً بعد عودة نداء التثبيت. ضع في اعتبارك أن ترحيل البيانات الوصفية يكون قد طُبِّق بالفعل عند تشغيل ما بعد التثبيت، لذلك فإن فشل الوضع المتزامن لا يعيد التغييرات على المخطط إلى الوراء — بل يكتفي بإبراز الخطأ.
- تأكّد من أن معالجك قابل للتنفيذ المتكرر دون آثار جانبية. في الوضع غير المتزامن قد تُعيد قائمة الانتظار المحاولة حتى ثلاث مرات؛ وفي أي من الوضعين قد يعمل الخطاف مجددًا أثناء الترقيات عند ضبط
shouldRunOnVersionUpgrade: true. - متغيرات البيئة
APPLICATION_IDوAPP_ACCESS_TOKENوAPI_URLمتاحة داخل المعالج (كما في أي دالة منطق أخرى)، لذا يمكنك استدعاء واجهة Twenty API باستخدام رمز وصول للتطبيق مقيّد بنطاق تطبيقك. - يُسمح بدالة ما بعد التثبيت واحدة فقط لكل تطبيق. سيُنتج إنشاء ملف البيان خطأً إذا تم اكتشاف أكثر من واحدة.
- تُرفَق خصائص الدالة
universalIdentifierوshouldRunOnVersionUpgradeوshouldRunSynchronouslyتلقائيًا ببيان التطبيق ضمن الحقلpostInstallLogicFunctionأثناء عملية البناء — ولا تحتاج إلى الإشارة إليها فيdefineApplication(). - تم تعيين مهلة افتراضية إلى 300 ثانية (5 دقائق) للسماح بمهام الإعداد الأطول مثل تهيئة البيانات.
- لا يُنفَّذ في وضع التطوير: عند تسجيل تطبيق محليًا (عبر
yarn twenty dev)، يتجاوز الخادم تدفّق التثبيت بالكامل ويُزامن الملفات مباشرةً عبر مراقِب CLI — لذا لن يعمل ما بعد التثبيت في وضع التطوير مطلقًا، بغضّ النظر عنshouldRunSynchronously. استخدمyarn twenty exec --postInstallلتشغيله يدويًا على مساحة عمل قيد التشغيل.
definePreInstallLogicFunction
تعريف دالة منطقية لما قبل التثبيت (واحدة لكل تطبيق)
definePreInstallLogicFunction
تعريف دالة منطقية لما قبل التثبيت (واحدة لكل تطبيق)
InstallPayload)، لكنها موضوعة أبكر في تدفّق التثبيت كي تجهّز حالة يعتمد عليها الترحيل القادم — ومن الاستخدامات الشائعة: نسخ البيانات احتياطيًا، التحقق من التوافق مع المخطط الجديد، أو أرشفة السجلات التي ستُعاد هيكلتها أو ستُحذف.- تستخدم دوال ما قبل التثبيت
definePreInstallLogicFunction()— نفس الإعدادات المتخصصة كما في ما بعد التثبيت، لكنها مرتبطة بموضع مختلف ضمن دورة الحياة. - يتلقّى كلٌّ من معالجي ما قبل التثبيت وما بعد التثبيت النوع نفسه
InstallPayload:{ previousVersion?: string; newVersion: string }. استورده مرة واحدة وأعد استخدامه لكلا الخطافين. - موعد تشغيل الخطاف: موضوع مباشرةً قبل ترحيل البيانات الوصفية لمساحة العمل (
synchronizeFromManifest). قبل التنفيذ، يُشغِّل الخادم مزامنة “pared-down sync” ذات طابع إضافي فقط تقوم بتسجيل دالة ما قبل التثبيت للإصدار الجديد في البيانات الوصفية لمساحة العمل — دون لمس أي شيء آخر — ثم يُنفّذها. لأن هذه المزامنة «إضافية فقط»، تبقى كائنات وحقول وبيانات الإصدار السابق سليمة عند تشغيل معالجك: يمكنك قراءة حالة ما قبل الترحيل ونسخها احتياطيًا بأمان. - نموذج التنفيذ: يُنفَّذ ما قبل التثبيت بشكل متزامن ويحجب عملية التثبيت. إذا رمى المعالج استثناءً، تُلغى عملية التثبيت قبل تطبيق أي تغييرات على المخطط — وتبقى مساحة العمل على الإصدار السابق بحالة متّسقة. هذا مقصود: ما قبل التثبيت هو فرصتك الأخيرة لرفض ترقية تنطوي على مخاطر.
- كما هو الحال مع ما بعد التثبيت، يُسمح بدالة ما قبل التثبيت واحدة فقط لكل تطبيق. تُربَط تلقائيًا ببيان التطبيق تحت
preInstallLogicFunctionأثناء عملية البناء. - لا يُنفَّذ في وضع التطوير: كما في ما بعد التثبيت — يتم تجاوز تدفّق التثبيت بالكامل للتطبيقات المسجّلة محليًا، لذا لن يعمل ما قبل التثبيت مطلقًا عند
yarn twenty dev. استخدمyarn twenty exec --preInstallلتشغيله يدويًا.
ما قبل التثبيت مقابل ما بعد التثبيت: متى تستخدم أيّهما
اختيار خطاف التثبيت المناسب
ما قبل التثبيت مقابل ما بعد التثبيت: متى تستخدم أيّهما
اختيار خطاف التثبيت المناسب
InstallPayload. الاختلاف يكمن في موعد تشغيلهما نسبةً إلى ترحيل البيانات الوصفية لمساحة العمل، وهذا يغيّر البيانات التي يمكنهما التعامل معها بأمان.shouldRunSynchronously: true. راجع الأكورديون definePostInstallLogicFunction أعلاه لمعرفة متى تستخدم كل وضع.استخدم post-install لأي شيء يتطلّب وجود المخطط الجديد. وهذا هو السيناريو الشائع:- بَذر بيانات افتراضية (إنشاء سجلات أولية وعروض افتراضية ومحتوى تجريبي) للكائنات والحقول المضافة حديثًا.
- تسجيل خطافات الويب مع خدمات أطراف ثالثة بعد أن حصل التطبيق على بيانات الاعتماد الخاصة به.
- استدعاء واجهة برمجة التطبيقات الخاصة بك لإكمال إعداد يعتمد على البيانات الوصفية المتزامنة.
- منطق idempotent لتحقيق “تأكّد من وجود هذا” والذي ينبغي مواءمة الحالة في كل ترقية — بالاقتران مع
shouldRunOnVersionUpgrade: true.
PostCard افتراضي بعد التثبيت:pre-install عندما قد يُتلف الترحيل أو يدمّر البيانات الحالية. لأن ما قبل التثبيت يعمل مقابل المخطط السابق وفشله يُرجِع الترقية إلى الوراء، فهو المكان المناسب لأي شيء محفوف بالمخاطر:- نسخ البيانات احتياطيًا قبل حذفها أو إعادة هيكلتها — مثل إزالة حقل في v2 وتحتاج إلى نسخ قيمه إلى حقل آخر أو تصديرها إلى التخزين قبل تشغيل الترحيل.
- أرشفة السجلات التي سيبطلها قيد جديد — مثل أن يصبح حقل ما
NOT NULLوتحتاج أولًا إلى حذف الصفوف ذات القيم الفارغة أو إصلاحها. - التحقق من التوافق ورفض الترقية إذا تعذّر ترحيل البيانات الحالية بسلاسة — ارمِ من داخل المعالج وسيُلغى التثبيت دون تطبيق أي تغييرات. هذا أكثر أمانًا من اكتشاف عدم التوافق في منتصف الترحيل.
- إعادة تسمية البيانات أو إعادة تعيين مفاتيحها قبل تغيير في المخطط قد يؤدي إلى فقدان الارتباط.
| ترغب في… | استخدام |
|---|---|
| بذر بيانات افتراضية، تهيئة مساحة العمل، تسجيل موارد خارجية | post-install |
| تشغيل بذر طويل الأمد أو استدعاءات أطراف ثالثة لا ينبغي أن تحجب استجابة التثبيت | post-install (الإعداد الافتراضي — shouldRunSynchronously: false، مع محاولات إعادة من العامل) |
| تشغيل إعداد سريع سيعتمد عليه المستدعي مباشرةً بعد عودة نداء التثبيت | post-install مع shouldRunSynchronously: true |
| قراءة البيانات أو نسخها احتياطيًا والتي قد يفقدها الترحيل القادم | pre-install |
| رفض ترقية قد تُفسد البيانات الحالية | pre-install (ارمِ من المعالج) |
| تنفيذ مواءمة في كل ترقية | post-install مع shouldRunOnVersionUpgrade: true |
| تنفيذ إعداد لمرة واحدة في التثبيت الأول فقط | post-install مع shouldRunOnVersionUpgrade: false (الإعداد الافتراضي) |
defineFrontComponent
عرِّف مكوّنات أمامية لواجهة مستخدم مخصّصة
defineFrontComponent
عرِّف مكوّنات أمامية لواجهة مستخدم مخصّصة
أين يمكن استخدام مكوّنات الواجهة الأمامية
يمكن عرض مكوّنات الواجهة الأمامية في موقعين داخل Twenty:- اللوحة الجانبية — المكوّنات غير عديمة الرأس تفتح في اللوحة الجانبية اليمنى. هذا هو السلوك الافتراضي عندما يتم تشغيل مكوّن واجهة أمامية من قائمة الأوامر.
- الويدجت (لوحات المعلومات وصفحات السجلات) — يمكن تضمين مكوّنات الواجهة الأمامية كويدجت داخل تخطيطات الصفحات. عند تكوين لوحة معلومات أو تخطيط صفحة سجل، يمكن للمستخدمين إضافة ويدجت لمكوّن واجهة أمامية.
مثال أساسي
أسرع طريقة لرؤية مكوّن أمامي قيد العمل هي تسجيله كأمر. إضافة حقلcommand مع isPinned: true يجعلُه يظهر كزر إجراء سريع في الزاوية العلوية اليمنى من الصفحة — دون الحاجة إلى تخطيط صفحة:yarn twenty dev (أو تشغيل الأمر لمرة واحدة yarn twenty dev --once)، يظهر الإجراء السريع في الزاوية العلوية اليمنى من الصفحة:
حقول التكوين
| الحقل | مطلوب | الوصف |
|---|---|---|
universalIdentifier | نعم | معرّف فريد ثابت لهذا المكوّن |
component | نعم | دالة مكوّن React |
name | لا | اسم العرض |
الوصف | لا | وصف لما يفعله المكوّن |
isHeadless | لا | عيِّنه إلى true إذا كان المكوّن بلا واجهة مرئية (انظر أدناه) |
أمر | لا | سجّل المكوّن كأمر (انظر خيارات الأوامر أدناه) |
وضع مكوّن أمامي على صفحة
إضافةً إلى الأوامر، يمكنك تضمين مكوّن أمامي مباشرةً في صفحة سجل عبر إضافته كودجت في تخطيط صفحة. راجع قسم definePageLayout للتفاصيل.عديم الرأس مقابل غير عديم الرأس
تأتي مكوّنات الواجهة الأمامية بوضعَي عرض يتحكّم بهما الخيارisHeadless:غير عديم الرأس (افتراضي) — يعرض المكوّن واجهة مستخدم مرئية. عند تشغيله من قائمة الأوامر يفتح في اللوحة الجانبية. هذا هو السلوك الافتراضي عندما تكون isHeadless تساوي false أو يتم تجاهلها.عديم الرأس (isHeadless: true) — يتم تركيب المكوّن بشكل غير مرئي في الخلفية. لا يفتح اللوحة الجانبية. تم تصميم المكوّنات عديمة الرأس لإجراءات تنفّذ منطقًا ثم تُزيل تركيبها ذاتيًا — على سبيل المثال، تشغيل مهمة غير متزامنة، أو الانتقال إلى صفحة، أو إظهار نافذة تأكيد منبثقة. تتوافق بشكل طبيعي مع مكوّنات Command في SDK الموصوفة أدناه.null، فإن Twenty يتخطّى عرض حاوية له — ولن تظهر مساحة فارغة في التخطيط. لا يزال لدى المكوّن إمكانية الوصول إلى جميع الخطافات وواجهة برمجة الاتصال مع المضيف.مكوّنات Command في SDK
توفر حزمةtwenty-sdk أربعة مكوّنات مساعدة من نوع Command مصممة للمكوّنات عديمة الرأس في الواجهة الأمامية. كل مكوّن ينفّذ إجراءً عند التركيب، ويتعامل مع الأخطاء بعرض إشعار Snackbar، ويزيل تركيب مكوّن الواجهة الأمامية تلقائيًا عند الانتهاء.استوردها من twenty-sdk/command:Command— يشغّل رد نداء غير متزامن عبر الخاصيةexecute.CommandLink— ينتقل إلى مسار في التطبيق. الخصائص:to،params،queryParams،options.CommandModal— يفتح نافذة تأكيد منبثقة. إذا أكّد المستخدم، ينفّذ رد النداءexecute. الخصائص:title،subtitle،execute،confirmButtonText،confirmButtonAccent.CommandOpenSidePanelPage— يفتح صفحة محدّدة في اللوحة الجانبية. الخصائص:page،pageTitle،pageIcon.
Command لتشغيل إجراء من قائمة الأوامر:CommandModal لطلب التأكيد قبل التنفيذ:الوصول إلى سياق وقت التشغيل
داخل مكوّنك، استخدم خطافات SDK للوصول إلى المستخدم الحالي، والسجل، ومثيل المكوّن:| الخطّاف | القيم المعادة | الوصف |
|---|---|---|
useUserId() | string أو null | معرّف المستخدم الحالي |
useRecordId() | string أو null | معرّف السجل الحالي (عند وضعه على صفحة سجل) |
useFrontComponentId() | string | معرّف مثيل هذا المكوّن |
useFrontComponentExecutionContext(selector) | يختلف | الوصول إلى سياق التنفيذ الكامل عبر دالة محدِّد |
واجهة الاتصال مع المضيف
يمكن للمكوّنات الأمامية تشغيل التنقّل والنوافذ المنبثقة والإشعارات باستخدام دوال منtwenty-sdk:| دالة | الوصف |
|---|---|
navigate(to, params?, queryParams?, options?) | الانتقال إلى صفحة داخل التطبيق |
openSidePanelPage(params) | فتح لوحة جانبية |
closeSidePanel() | إغلاق اللوحة الجانبية |
openCommandConfirmationModal(params) | عرض مربع حوار تأكيد |
enqueueSnackbar(params) | عرض إشعار توست |
unmountFrontComponent() | إلغاء تركيب المكوّن |
updateProgress(progress) | تحديث مؤشّر التقدّم |
خيارات الأوامر
إضافة حقلcommand إلى defineFrontComponent تُسجِّل المكوّن في قائمة الأوامر (Cmd+K). إذا كانت قيمة isPinned هي true، فسيظهر أيضًا كزر إجراء سريع في الزاوية العلوية اليمنى من الصفحة.| الحقل | مطلوب | الوصف |
|---|---|---|
universalIdentifier | نعم | معرّف فريد ثابت للأمر |
التسمية | نعم | التسمية الكاملة المعروضة في قائمة الأوامر (Cmd+K) |
shortLabel | لا | تسمية أقصر تُعرَض على زر الإجراء السريع المثبّت |
أيقونة | لا | اسم الأيقونة المعروض بجانب التسمية (مثل 'IconBolt' و'IconSend') |
isPinned | لا | عند كونها true، يعرض الأمر كزر إجراء سريع في الزاوية العلوية اليمنى من الصفحة |
availabilityType | لا | تتحكّم في مكان ظهور الأمر: 'GLOBAL' (متاح دائمًا)، و'RECORD_SELECTION' (فقط عند تحديد سجلات)، أو 'FALLBACK' (يُعرَض عند عدم تطابق أي أوامر أخرى) |
availabilityObjectUniversalIdentifier | لا | تقييد الأمر بصفحات نوع كائن معيّن (مثل سجلات Company فقط) |
conditionalAvailabilityExpression | لا | تعبير منطقي للتحكم ديناميكيًا في ما إذا كان الأمر مرئيًا (انظر أدناه) |
تعابير الإتاحة الشرطية
يتيح لك الحقلconditionalAvailabilityExpression التحكّم في وقت ظهور الأمر بناءً على سياق الصفحة الحالي. استورد متغيّرات ومشغّلات مضبوطة الأنواع من twenty-sdk لبناء التعابير:| المتغيّر | النوع | الوصف |
|---|---|---|
pageType | string | نوع الصفحة الحالي (مثل 'RecordIndexPage' و'RecordShowPage') |
isInSidePanel | قيمة منطقية | ما إذا كان المكوّن معروضًا في لوحة جانبية |
numberOfSelectedRecords | رقم | عدد السجلات المحدّدة حاليًا |
isSelectAll | قيمة منطقية | ما إذا كان “تحديد الكل” مفعّلًا |
selectedRecords | array | كائنات السجلات المحدّدة |
favoriteRecordIds | array | معرّفات السجلات المفضّلة |
objectPermissions | الكائن | الأذونات الخاصة بنوع الكائن الحالي |
targetObjectReadPermissions | الكائن | أذونات القراءة للكائن الهدف |
targetObjectWritePermissions | الكائن | أذونات الكتابة للكائن الهدف |
featureFlags | الكائن | أعلام الميزات المفعَّلة |
objectMetadataItem | الكائن | بيانات التعريف لنوع الكائن الحالي |
hasAnySoftDeleteFilterOnView | قيمة منطقية | ما إذا كان العرض الحالي يحتوي على مرشّح حذف منطقي |
| المُشغِّل | الوصف |
|---|---|
isDefined(value) | true إذا لم تكن القيمة null/undefined |
isNonEmptyString(value) | true إذا كانت القيمة سلسلة غير فارغة |
includes(array, value) | true إذا كانت المصفوفة تحتوي على القيمة |
includesEvery(array, prop, value) | true إذا كانت خاصية كل عنصر تتضمن القيمة |
every(array, prop) | true إذا كانت الخاصية تُقيَّم بصحّة في كل عنصر |
everyDefined(array, prop) | true إذا كانت الخاصية معرّفة في كل عنصر |
everyEquals(array, prop, value) | true إذا كانت الخاصية تساوي القيمة في كل عنصر |
some(array, prop) | true إذا كانت الخاصية تُقيَّم بصحّة في عنصر واحد على الأقل |
someDefined(array, prop) | true إذا كانت الخاصية معرّفة في عنصر واحد على الأقل |
someEquals(array, prop, value) | true إذا كانت الخاصية تساوي القيمة في عنصر واحد على الأقل |
someNonEmptyString(array, prop) | true إذا كانت الخاصية سلسلة غير فارغة في عنصر واحد على الأقل |
none(array, prop) | true إذا كانت الخاصية تُقيَّم بخطأ في كل عنصر |
noneDefined(array, prop) | true إذا كانت الخاصية غير معرّفة في كل عنصر |
noneEquals(array, prop, value) | true إذا لم تكن الخاصية تساوي القيمة في أي عنصر |
الأصول العامة
يمكن للمكوّنات الأمامية الوصول إلى ملفات من دليلpublic/ للتطبيق باستخدام getPublicAssetUrl:التنسيق
تدعم المكوّنات الأمامية عدة أساليب للتنسيق. يمكنك استخدام:- أنماط مضمنة —
style={{ color: 'red' }} - مكوّنات Twenty لواجهة المستخدم — استورد من
twenty-sdk/ui(Button وTag وStatus وChip وAvatar وغيرها) - Emotion — CSS-in-JS مع
@emotion/react - Styled-components — أنماط
styled.div - Tailwind CSS — أصناف مساعدة
- أي مكتبة CSS-in-JS متوافقة مع React
defineSkill
عرّف مهارات وكيل الذكاء الاصطناعي
defineSkill
عرّف مهارات وكيل الذكاء الاصطناعي
defineSkill() لتعريف مهارات مع تحقّق مدمج:nameهي سلسلة معرّف فريدة للمهارة (يُنصَح باستخدام kebab-case).labelهو اسم العرض المقروء للبشر الظاهر في واجهة المستخدم.contentيحتوي على تعليمات المهارة — وهو النص الذي يستخدمه وكيل الذكاء الاصطناعي.icon(اختياري) يحدّد الأيقونة المعروضة في واجهة المستخدم.description(اختياري) يوفّر سياقًا إضافيًا حول غرض المهارة.
defineAgent
عرِّف وكلاء الذكاء الاصطناعي باستخدام موجهات مخصّصة
defineAgent
عرِّف وكلاء الذكاء الاصطناعي باستخدام موجهات مخصّصة
defineAgent() لإنشاء وكلاء بموجه نظام مخصّص:nameهي سلسلة معرّف فريدة للوكيل (يُنصح باستخدام kebab-case).labelهو اسم العرض الظاهر في واجهة المستخدم.promptهو موجه النظام الذي يحدّد سلوك الوكيل.description(اختياري) يوفّر سياقًا حول ما يفعله الوكيل.icon(اختياري) يحدّد الأيقونة المعروضة في واجهة المستخدم.modelId(اختياري) يتجاوز نموذج الذكاء الاصطناعي الافتراضي الذي يستخدمه الوكيل.
defineView
تعريف العروض المحفوظة للكائنات
defineView
تعريف العروض المحفوظة للكائنات
defineView() لتضمين عروض مُهيّأة مسبقًا مع تطبيقك:objectUniversalIdentifierيحدّد الكائن الذي ينطبق عليه هذا العرض.keyيحدّد نوع العرض (مثلViewKey.INDEXلعرض القائمة الرئيسي).fieldsيتحكّم في الأعمدة الظاهرة وترتيبها. يشير كل حقل إلىfieldMetadataUniversalIdentifier.- يمكنك أيضًا تعريف
filtersوfilterGroupsوgroupsوfieldGroupsلمزيد من التكوينات المتقدمة. positionيتحكّم في الترتيب عند وجود عدة عروض لنفس الكائن.
defineNavigationMenuItem
تعريف روابط التنقل في الشريط الجانبي
defineNavigationMenuItem
تعريف روابط التنقل في الشريط الجانبي
definePageLayout
عرّف تخطيطات صفحات مخصّصة لعرض السجلات
definePageLayout
عرّف تخطيطات صفحات مخصّصة لعرض السجلات
definePageLayout() لتضمين تخطيطات مخصّصة مع تطبيقك:typeيكون عادة'RECORD_PAGE'لتخصيص عرض التفاصيل لكائن محدّد.objectUniversalIdentifierيحدّد الكائن الذي ينطبق عليه هذا التخطيط.- يُعرّف كل
tabقسمًا من الصفحة معtitleوpositionوlayoutMode(CANVASلتخطيط حرّ). - يمكن لكل
widgetداخل لسان أن يعرض مكوّنًا أماميًا أو قائمة علاقات أو أنواع ويدجت مدمجة أخرى. positionعلى الألسنة يتحكّم في ترتيبها. استخدم قيمًا أعلى (مثل 50) لوضع الألسنة المخصّصة بعد الألسنة المدمجة.
الأصول العامة (مجلد public/)
يحتوي مجلد public/ في جذر تطبيقك على ملفات ثابتة — صور وأيقونات وخطوط وأي أصول أخرى يحتاجها تطبيقك وقت التشغيل. تُدرج هذه الملفات تلقائيًا في عمليات البناء، وتُزامَن أثناء وضع التطوير، وتُرفَع إلى الخادم.
الملفات الموضوعة في public/ هي:
- متاحة للعامة — بمجرد مزامنتها إلى الخادم، تُقدَّم الأصول عبر عنوان URL عام. لا يلزم توثيق للوصول إليها.
- متاحة في المكوّنات الأمامية — استخدم عناوين الأصول لعرض الصور أو الأيقونات أو أي وسائط داخل مكوّنات React لديك.
- متاحة في الدوال المنطقية — أشِر إلى عناوين الأصول في رسائل البريد الإلكتروني أو استجابات واجهات البرمجة أو أي منطق على جهة الخادم.
- مستخدمة لبيانات تعريف السوق — يشير حقلا
logoUrlوscreenshotsفيdefineApplication()إلى ملفات من هذا المجلد (مثلpublic/logo.png). تُعرَض هذه عند نشر تطبيقك في السوق. - تُزامَن تلقائيًا في وضع التطوير — عند إضافة ملف في
public/أو تحديثه أو حذفه، تتم مزامنته إلى الخادم تلقائيًا. لا حاجة لإعادة التشغيل. - مضمَّنة في عمليات البناء — يقوم
yarn twenty buildبتجميع جميع الأصول العامة ضمن مخرجات التوزيع.
الوصول إلى الأصول العامة باستخدام getPublicAssetUrl
استخدم المساعد getPublicAssetUrl من twenty-sdk للحصول على العنوان الكامل لملف في دليل public/ لديك. يعمل ذلك في كلٍ من الدوال المنطقية والمكوّنات الأمامية.
في دالة منطقية:
path نسبية إلى مجلد public/ الخاص بتطبيقك. كلٌّ من getPublicAssetUrl('logo.png') وgetPublicAssetUrl('public/logo.png') يُحلاّن إلى العنوان نفسه — تتم إزالة بادئة public/ تلقائيًا إن وُجدت.
استخدام حِزَم npm
يمكنك تثبيت واستخدام أي حزمة npm في تطبيقك. يتم تجميع كلٍ من الدوال المنطقية والمكوّنات الأمامية باستخدام esbuild، والذي يُضمّن جميع التبعيات ضمن المخرجات — لا حاجة إلىnode_modules وقت التشغيل.
تثبيت حزمة
كيف يعمل التجميع
تستخدم خطوة البناء أداة esbuild لإنتاج ملف واحد مستقل لكل دالة منطقية ولكل مكوّن أمامي. تُضمَّن جميع الحزم المستوردة داخل الحزمة. الدوال المنطقية تعمل في بيئة Node.js. الوحدات المدمجة في Node (fs وpath وcrypto وhttp وغيرها) متاحة ولا تحتاج إلى تثبيت.
المكوّنات الأمامية تعمل ضمن Web Worker. وحدات Node المدمجة غير متاحة — المتاح فقط واجهات برمجة المتصفّح وحِزَم npm التي تعمل في بيئة المتصفّح.
كلتا البيئتين تحتويان على twenty-client-sdk/core وtwenty-client-sdk/metadata كوحدات متاحة مُسبقًا — لا تُضمَّن هذه ضمن الحزم بل تُحلّ وقت التشغيل بواسطة الخادم.
توليد قوالب الكيانات باستخدام yarn twenty add
بدلًا من إنشاء ملفات الكيانات يدويًا، يمكنك استخدام أداة القوالب التفاعلية:
universalIdentifier ثابت واستدعاء defineEntity() الصحيح.
يمكنك أيضًا تمرير نوع الكيان مباشرة لتخطي المطالبة الأولى:
أنواع الكيانات المتاحة
| نوع الكيان | أمر | الملف المُولَّد |
|---|---|---|
| كائن | yarn twenty add object | src/objects/\<name>.ts |
| الحقل | yarn twenty add field | src/fields/\<name>.ts |
| دالة منطقية | yarn twenty add logicFunction | src/logic-functions/\<name>.ts |
| مكوّن أمامي | yarn twenty add frontComponent | src/front-components/\<name>.tsx |
| دور | yarn twenty add role | src/roles/\<name>.ts |
| مهارة | yarn twenty add skill | src/skills/\<name>.ts |
| وكيل | yarn twenty add agent | src/agents/\<name>.ts |
| عرض | yarn twenty add view | src/views/\<name>.ts |
| عنصر قائمة التنقّل | yarn twenty add navigationMenuItem | src/navigation-menu-items/\<name>.ts |
| تخطيط الصفحة | yarn twenty add pageLayout | src/page-layouts/\<name>.ts |
ما الذي تُنشئه أداة القوالب
لكل نوع كيان قالب خاص به. على سبيل المثال، يسألyarn twenty add object عن:
- الاسم (مفرد) — مثل
invoice - الاسم (جمع) — مثل
invoices - التسمية (مفرد) — تُستمد تلقائيًا من الاسم (مثل
Invoice) - التسمية (جمع) — تُملأ تلقائيًا (مثل
Invoices) - إنشاء عرض وعنصر تنقّل؟ — إذا أجبت بنعم، فستُنشئ أداة القوالب أيضًا عرضًا مطابقًا ورابط شريط جانبي للكائن الجديد.
field أكثر تفصيلاً: يطلب اسم الحقل وتسمية الحقل ونوعه (من قائمة بكل أنواع الحقول المتاحة مثل TEXT وNUMBER وSELECT وRELATION وغيرها)، ومعرّف universalIdentifier للكائن الهدف.
مسار خرج مخصّص
استخدم العلم--path لوضع الملف المُولَّد في موقع مخصّص:
عملاء واجهة برمجة تطبيقات مضبوطة الأنواع (twenty-client-sdk)
توفر حزمة twenty-client-sdk عميلين لـ GraphQL ذوي أنواع ثابتة للتفاعل مع واجهة Twenty البرمجية من وظائفك المنطقية ومكوّنات الواجهة الأمامية.
| العميل | استيراد | نقطة النهاية | مُولَّد؟ |
|---|---|---|---|
CoreApiClient | twenty-client-sdk/core | /graphql — بيانات مساحة العمل (السجلات، الكائنات) | نعم، في وقت التطوير/البناء |
MetadataApiClient | twenty-client-sdk/metadata | /metadata — تكوين مساحة العمل، رفع الملفات | لا، يأتي مُجهزًا مسبقًا |
CoreApiClient
استعلام وتعديل بيانات مساحة العمل (السجلات، الكائنات)
CoreApiClient
استعلام وتعديل بيانات مساحة العمل (السجلات، الكائنات)
CoreApiClient هو العميل الرئيسي للاستعلام وتعديل بيانات مساحة العمل. يُولَّد من مخطط مساحة العمل لديك أثناء yarn twenty dev أو yarn twenty build، لذا فهو مضبوط الأنواع بالكامل ليتوافق مع كائناتك وحقولك.true لتضمين حقل، واستخدم __args للوسيطات، وعشّش الكائنات للعلاقات. ستحصل على إكمال تلقائي كامل وفحص للأنواع يعتمد على مخطط مساحة العمل لديك.yarn twenty dev أو yarn twenty build أولًا، فسيؤدي ذلك إلى خطأ. تحدث عملية التوليد تلقائيًا — إذ يستطلع CLI مخطط GraphQL لمساحة عملك وينشئ عميلًا مضبوط الأنواع باستخدام @genql/cli.استخدام CoreSchema للتعليقات التوضيحية للأنواع
CoreSchema يوفّر أنواع TypeScript المطابقة لكائنات مساحة العمل لديك — مفيد لتعيين أنواع حالة المكوّن أو معاملات الدوال:MetadataApiClient
إعدادات مساحة العمل، والتطبيقات، ورفع الملفات
MetadataApiClient
إعدادات مساحة العمل، والتطبيقات، ورفع الملفات
MetadataApiClient مُجهّزًا مسبقًا مع SDK (لا حاجة للتوليد). يستعلم عن نقطة النهاية /metadata للحصول على تكوين مساحة العمل والتطبيقات ورفع الملفات.رفع الملفات
يتضمنMetadataApiClient طريقة uploadFile لإرفاق الملفات بالحقول من نوع الملف:| المعلمة | النوع | الوصف |
|---|---|---|
fileBuffer | Buffer | المحتوى الخام للملف |
filename | string | اسم الملف (يُستخدم للتخزين والعرض) |
contentType | string | نوع MIME (القيمة الافتراضية application/octet-stream إذا لم يُحدَّد) |
fieldMetadataUniversalIdentifier | string | قيمة universalIdentifier لحقل نوع الملف في كائنك |
- يستخدم
universalIdentifierالخاص بالحقل (وليس معرّفه الخاص بمساحة العمل)، بحيث يعمل كود الرفع لديك عبر أي مساحة عمل مُثبَّت فيها تطبيقك. - العنوان
urlالمُعاد هو عنوان URL موقّع يمكنك استخدامه للوصول إلى الملف المرفوع.
TWENTY_API_URL— عنوان URL الأساسي لواجهة Twenty البرمجيةTWENTY_APP_ACCESS_TOKEN— مفتاح قصير العمر ذو نطاق يقتصر على الدور الافتراضي لوظيفة تطبيقك
process.env. تُحدَّد أذونات مفتاح واجهة برمجة التطبيقات بواسطة الدور المشار إليه في defaultRoleUniversalIdentifier ضمن application-config.ts.اختبار تطبيقك
يوفّر SDK واجهات برمجة قابلة للتنفيذ برمجيًا تمكّنك من بناء تطبيقك ونشره وتثبيته وإلغاء تثبيته من شيفرة الاختبار. بالاقتران مع Vitest وعملاء واجهة البرمجة مضبوطي الأنواع، يمكنك كتابة اختبارات تكامل تتحقّق من أن تطبيقك يعمل من البداية إلى النهاية مقابل خادم Twenty حقيقي.إعداد
يتضمّن التطبيق المُولَّد بالقالب بالفعل Vitest. إذا أعددته يدويًا، فثبّت التبعيات:vitest.config.ts في جذر تطبيقك:
واجهات SDK البرمجية
يُصدِّر المسار الفرعيtwenty-sdk/cli دوالًا يمكنك استدعاؤها مباشرةً من شيفرة الاختبار:
| دالة | الوصف |
|---|---|
appBuild | بناء التطبيق واختياريًا حزم ملف tarball |
appDeploy | رفع ملف tarball إلى الخادم |
appInstall | تثبيت التطبيق على مساحة العمل النشطة |
appUninstall | إلغاء تثبيت التطبيق من مساحة العمل النشطة |
success: boolean وعلى إمّا data أو error.
كتابة اختبار تكامل
إليك مثالًا كاملًا يبني التطبيق وينشره ويثبّته، ثم يتحقّق من ظهوره في مساحة العمل:تشغيل الاختبارات
تأكّد من تشغيل خادم Twenty المحلي لديك، ثم:التحقق من الأنواع
يمكنك أيضًا تشغيل التحقق من الأنواع على تطبيقك دون تشغيل الاختبارات:tsc --noEmit ويبلغ عن أي أخطاء في الأنواع.
مرجع CLI
بالإضافة إلىdev وbuild وadd وtypecheck، يوفّر CLI أوامر لتنفيذ الدوال وعرض السجلات وإدارة تثبيتات التطبيقات.
تنفيذ الدوال (yarn twenty exec)
تشغيل دالة منطقية يدويًا دون تشغيلها عبر HTTP أو cron أو حدث قاعدة بيانات:
عرض سجلات الدوال (yarn twenty logs)
بثّ سجلات التنفيذ لدوال تطبيقك المنطقية:
yarn twenty server logs، الذي يعرض سجلات حاوية Docker. يعرض yarn twenty logs سجلات تنفيذ دوال تطبيقك من خادم Twenty.إلغاء تثبيت تطبيق (yarn twenty uninstall)
أزل تطبيقك من مساحة العمل النشطة:
إدارة الريموتات
الريموت هو خادم Twenty يتصل به تطبيقك. أثناء الإعداد، تُنشئ أداة إنشاء الهيكل واحدًا لك تلقائيًا. يمكنك إضافة ريموتات أخرى أو التبديل بينها في أي وقت.~/.twenty/config.json.
التكامل المستمر (CI) باستخدام GitHub Actions
تولّد أداة إنشاء الهيكل سير عمل GitHub Actions جاهزًا للاستخدام في.github/workflows/ci.yml. يشغّل اختبارات التكامل لديك تلقائيًا عند كل دفع إلى main وعلى طلبات السحب.
سير العمل:
- يجلب الشيفرة الخاصة بك
- يشغّل خادم Twenty مؤقتًا باستخدام الإجراء
twentyhq/twenty/.github/actions/spawn-twenty-docker-image - يثبّت التبعيات باستخدام
yarn install --immutable - يشغّل
yarn testمع حقنTWENTY_API_URLوTWENTY_API_KEYمن مخرجات الإجراء
spawn-twenty-docker-image خادم Twenty عابرًا مباشرة في المشغّل ويُخرِج تفاصيل الاتصال. يتم توفير السر GITHUB_TOKEN تلقائيًا من قِبل GitHub.
لتثبيت إصدار محدّد من Twenty بدلًا من latest، غيّر متغير البيئة TWENTY_VERSION في أعلى سير العمل.