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/) هو مجرّد عرف، وليس متطلبًا.defineRole
تهيئة صلاحيات الدور والوصول إلى الكائنات
defineRole
تهيئة صلاحيات الدور والوصول إلى الكائنات
تُغلّف الأدوار الصلاحيات على كائنات وإجراءات مساحة العمل لديك.
restricted-company-role.ts
defineApplication
تهيئة بيانات التعريف للتطبيق (مطلوب، واحد لكل تطبيق)
defineApplication
تهيئة بيانات التعريف للتطبيق (مطلوب، واحد لكل تطبيق)
يجب أن يحتوي كل تطبيق على استدعاء واحد فقط لـ الملاحظات:
يُشار إلى
defineApplication يصف:- الهوية: المعرّفات، اسم العرض، والوصف.
- الأذونات: أيُّ دورٍ تستخدمه وظائفه ومكوّناته الأمامية.
- (اختياري) المتغيرات: أزواج مفتاح-قيمة تُعرض لوظائفك كمتغيرات بيئة.
- (اختياري) دوال ما قبل التثبيت/ما بعد التثبيت: دوال منطقية تعمل قبل التثبيت أو بعده.
src/application-config.ts
- حقول
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 ملفّ دور افتراضي: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
تعريف كائنات مخصصة مع حقول
defineObject
تعريف كائنات مخصصة مع حقول
تصف الكائنات المخصصة كلًا من المخطط والسلوك للسجلات في مساحة عملك. استخدم النقاط الرئيسية:
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 — الحقول القياسية
وسّع الكائنات الموجودة بحقول إضافية
defineField — الحقول القياسية
وسّع الكائنات الموجودة بحقول إضافية
استخدم النقاط الرئيسية:
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().
defineField — حقول العلاقات
وصِل الكائنات معًا بعلاقات ثنائية الاتجاه
defineField — حقول العلاقات
وصِل الكائنات معًا بعلاقات ثنائية الاتجاه
تربط العلاقات الكائنات معًا. في Twenty، تكون العلاقات دائمًا ثنائية الاتجاه — حيث تعرّف الجانبين، ويشير كل جانب إلى الآخر.هناك نوعان من العلاقات:
الخطوة 2: عرّف جانب MANY_TO_ONE على PostCardRecipient (جانب “العديد” — يحمل المفتاح الخارجي):
| نوع العلاقة | الوصف | هل لديه مفتاح خارجي؟ |
|---|---|---|
MANY_TO_ONE | تشير العديد من سجلات هذا الكائن إلى سجل واحد من الهدف | نعم (joinColumnName) |
ONE_TO_MANY | يحتوي سجل واحد من هذا الكائن على العديد من سجلات الهدف | لا (الجانب العكسي) |
كيف تعمل العلاقات
تتطلّب كل علاقة حقلين يشيران إلى بعضهما البعض:- جانب MANY_TO_ONE — يوجد على الكائن الذي يحمل المفتاح الخارجي
- جانب ONE_TO_MANY — يوجد على الكائن الذي يملك المجموعة
FieldType.RELATION ويُحيل كلٌ منهما إلى الآخر عبر relationTargetFieldMetadataUniversalIdentifier.مثال: البطاقة البريدية لديها العديد من المستلمين
افترض أنPostCard يمكن إرسالها إلى العديد من سجلات PostCardRecipient. ينتمي كل مستلم إلى بطاقة بريدية واحدة بالضبط.الخطوة 1: عرّف جانب ONE_TO_MANY على PostCard (جانب “الواحد”):src/fields/post-card-recipients-on-post-card.field.ts
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
خصائص حقل العلاقة
| الخاصية | مطلوب | الوصف |
|---|---|---|
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 — إذ يُورَّث من الكائن الأب:توليد قوالب الكيانات باستخدام 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 لوضع الملف المُولَّد في موقع مخصّص: