Skip to main content
The twenty-sdk package provides defineEntity functions to declare your app’s data model. يجب عليك استخدام export default defineEntity({...}) لكي يكتشف SDK الكيانات الخاصة بك. تتحقق هذه الدوال من تكوينك وقت البناء وتوفّر إكمالًا تلقائيًا في بيئة التطوير وأمان الأنواع.
تنظيم الملفات يعود إليك. يعتمد اكتشاف الكيانات على AST — حيث يعثر SDK على استدعاءات export default defineEntity(...) بغض النظر عن مكان وجود الملف. تجميع الملفات حسب النوع (مثلًا، logic-functions/ وroles/) هو مجرّد عرف، وليس متطلبًا.
تُغلّف الأدوار الصلاحيات على كائنات وإجراءات مساحة العمل لديك.
restricted-company-role.ts
يجب أن يحتوي كل تطبيق على استدعاء واحد فقط لـ defineApplication يصف:
  • الهوية: المعرّفات، اسم العرض، والوصف.
  • الأذونات: أيُّ دورٍ تستخدمه وظائفه ومكوّناته الأمامية.
  • (اختياري) المتغيرات: أزواج مفتاح-قيمة تُعرض لوظائفك كمتغيرات بيئة.
  • (اختياري) دوال ما قبل التثبيت/ما بعد التثبيت: دوال منطقية تعمل قبل التثبيت أو بعده.
src/application-config.ts
الملاحظات:
  • حقول universalIdentifier هي معرّفات حتمية تملكها أنت. أنشِئها مرة واحدة واحتفظ بها ثابتة عبر عمليات المزامنة.
  • applicationVariables تصبح متغيرات بيئة لوظائفك ومكوّناتك الأمامية (على سبيل المثال، DEFAULT_RECIPIENT_NAME متاح كـ process.env.DEFAULT_RECIPIENT_NAME).
  • defaultRoleUniversalIdentifier يجب أن يُشير إلى دور مُعرَّف باستخدام defineRole() (انظر أعلاه).
  • يتم اكتشاف دوال ما قبل التثبيت وما بعده تلقائيًا أثناء بناء البيان — لا حاجة للإشارة إليها في defineApplication().

بيانات التعريف لسوق التطبيقات

إذا كنت تخطط لـ نشر تطبيقك، فإن هذه الحقول الاختيارية تتحكّم في كيفية ظهوره في السوق:

الأدوار والصلاحيات

يُحدّد الحقل defaultRoleUniversalIdentifier في application-config.ts الدور الافتراضي الذي تستخدمه وظائف المنطق والمكوّنات الأمامية في تطبيقك. راجع defineRole أعلاه للحصول على التفاصيل.
  • رمز وقت التشغيل المحقون باسم TWENTY_APP_ACCESS_TOKEN مستمد من هذا الدور.
  • العميل مضبوط الأنواع مقيَّد بالأذونات الممنوحة لذلك الدور.
  • اتبع مبدأ أقل الامتياز: أنشئ دورًا مخصصًا يضم فقط الأذونات التي تحتاجها وظائفك.
الدور الافتراضي للوظيفة
عند توليد تطبيق جديد بالقالب، ينشئ CLI ملفّ دور افتراضي:
src/roles/default-role.ts
يُشار إلى universalIdentifier لهذا الدور في application-config.ts باسم defaultRoleUniversalIdentifier:
  • *.role.ts يحدد ما يمكن أن يفعله الدور.
  • application-config.ts يشير إلى ذلك الدور بحيث ترث وظائفك أذوناته.
الملاحظات:
  • ابدأ من الدور المُنشأ بالقالب، ثم قيّده تدريجيًا باتباع مبدأ أقل الامتياز.
  • استبدل objectPermissions وfieldPermissions بالكائنات والحقول التي تحتاجها وظائفك فعليًا.
  • permissionFlags تتحكم في الوصول إلى القدرات على مستوى المنصة. اجعلها في حدّها الأدنى.
  • اطّلع على مثال عملي: hello-world/src/roles/function-role.ts.
تصف الكائنات المخصصة كلًا من المخطط والسلوك للسجلات في مساحة عملك. استخدم defineObject() لتعريف كائنات مع تحقق مدمج:
postCard.object.ts
النقاط الرئيسية:
  • استخدم defineObject() للحصول على تحقق مدمج ودعم أفضل من IDE.
  • universalIdentifier يجب أن يكون فريدًا وثابتًا عبر عمليات النشر.
  • يتطلب كل حقل name وtype وlabel ومعرّف universalIdentifier ثابتًا خاصًا به.
  • المصفوفة fields اختيارية — يمكنك تعريف كائنات بدون حقول مخصصة.
  • يمكنك إنشاء كائنات جديدة باستخدام yarn twenty add، والذي يرشدك خلال التسمية والحقول والعلاقات.
يتم إنشاء الحقول الأساسية تلقائيًا. عند تعريف كائن مخصص، يضيف Twenty تلقائيًا حقولًا قياسية مثل id وname وcreatedAt وupdatedAt وcreatedBy وupdatedBy وdeletedAt. لا تحتاج إلى تعريف هذه في مصفوفة fields — أضف فقط حقولك المخصصة. يمكنك تجاوز الحقول الافتراضية من خلال تعريف حقل بالاسم نفسه في مصفوفة fields الخاصة بك، لكن هذا غير مستحسن.
استخدم defineField() لإضافة حقول إلى كائنات لا تملكها — مثل كائنات Twenty القياسية (Person, Company, etc.) أو كائنات من تطبيقات أخرى. على خلاف الحقول المضمّنة في defineObject()، تتطلّب الحقول المستقلة objectUniversalIdentifier لتحديد الكائن الذي تقوم بتوسيعه:
src/fields/company-loyalty-tier.field.ts
النقاط الرئيسية:
  • objectUniversalIdentifier يحدّد الكائن الهدف. بالنسبة للكائنات القياسية، استخدم STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS المُصدَّر من twenty-sdk.
  • عند تعريف الحقول بشكل مضمّن في defineObject()، لا تحتاج إلى objectUniversalIdentifier — إذ يُورَّث من الكائن الأب.
  • defineField() هي الطريقة الوحيدة لإضافة حقول إلى كائنات لم تُنشئها باستخدام defineObject().
تربط العلاقات الكائنات معًا. في Twenty، تكون العلاقات دائمًا ثنائية الاتجاه — حيث تعرّف الجانبين، ويشير كل جانب إلى الآخر.هناك نوعان من العلاقات:

كيف تعمل العلاقات

تتطلّب كل علاقة حقلين يشيران إلى بعضهما البعض:
  1. جانب MANY_TO_ONE — يوجد على الكائن الذي يحمل المفتاح الخارجي
  2. جانب ONE_TO_MANY — يوجد على الكائن الذي يملك المجموعة
يستخدم كلا الحقلين FieldType.RELATION ويُحيل كلٌ منهما إلى الآخر عبر relationTargetFieldMetadataUniversalIdentifier.

مثال: البطاقة البريدية لديها العديد من المستلمين

افترض أن PostCard يمكن إرسالها إلى العديد من سجلات PostCardRecipient. ينتمي كل مستلم إلى بطاقة بريدية واحدة بالضبط.الخطوة 1: عرّف جانب ONE_TO_MANY على PostCard (جانب “الواحد”):
src/fields/post-card-recipients-on-post-card.field.ts
الخطوة 2: عرّف جانب MANY_TO_ONE على PostCardRecipient (جانب “العديد” — يحمل المفتاح الخارجي):
src/fields/post-card-on-post-card-recipient.field.ts
الاستيرادات الدائرية: كلا حقلي العلاقة يُحيل كلٌ منهما إلى universalIdentifier الخاص بالآخر. لتجنّب مشكلات الاستيراد الدائري، صدّر معرّفات الحقول كثوابت مسمّاة من كل ملف، واستوردها في الملف الآخر. يقوم نظام البناء بحلّها في وقت التجميع.

الربط مع الكائنات القياسية

لإنشاء علاقة مع كائن Twenty مضمّن (Person, Company, etc.)، استخدم STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS:
src/fields/person-on-self-hosting-user.field.ts

خصائص حقل العلاقة

حقول العلاقات المضمّنة في defineObject

يمكنك أيضًا تعريف حقول العلاقات مباشرةً داخل defineObject(). في هذه الحالة، احذف objectUniversalIdentifier — إذ يُورَّث من الكائن الأب:

توليد قوالب الكيانات باستخدام yarn twenty add

بدلًا من إنشاء ملفات الكيانات يدويًا، يمكنك استخدام أداة القوالب التفاعلية:
ستطالبك باختيار نوع الكيان وتُرشدك خلال الحقول المطلوبة. تُولّد ملفًا جاهزًا للاستخدام مع universalIdentifier ثابت واستدعاء defineEntity() الصحيح. يمكنك أيضًا تمرير نوع الكيان مباشرة لتخطي المطالبة الأولى:

أنواع الكيانات المتاحة

ما الذي تُنشئه أداة القوالب

لكل نوع كيان قالب خاص به. على سبيل المثال، يسأل yarn twenty add object عن:
  1. الاسم (مفرد) — مثل invoice
  2. الاسم (جمع) — مثل invoices
  3. التسمية (مفرد) — تُستمد تلقائيًا من الاسم (مثل Invoice)
  4. التسمية (جمع) — تُملأ تلقائيًا (مثل Invoices)
  5. إنشاء عرض وعنصر تنقّل؟ — إذا أجبت بنعم، فستُنشئ أداة القوالب أيضًا عرضًا مطابقًا ورابط شريط جانبي للكائن الجديد.
أنواع الكيانات الأخرى لها مطالبات أبسط — فمعظمها يطلب اسمًا فقط. نوع الكيان field أكثر تفصيلاً: يطلب اسم الحقل وتسمية الحقل ونوعه (من قائمة بكل أنواع الحقول المتاحة مثل TEXT وNUMBER وSELECT وRELATION وغيرها)، ومعرّف universalIdentifier للكائن الهدف.

مسار خرج مخصّص

استخدم العلم --path لوضع الملف المُولَّد في موقع مخصّص: