From 982f0c4a4d1127e26a1996ec043f4a55f5ff480d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 15:57:15 +0100 Subject: [PATCH] i18n - docs translations (#18534) Created by Github action --------- Co-authored-by: github-actions Co-authored-by: Charles Bochet --- packages/twenty-docs/docs.json | 14 +- .../l/ar/developers/extend/api.mdx | 147 ++++ .../l/ar/developers/extend/apps/building.mdx | 689 ++++++++++++++++++ .../extend/apps/getting-started.mdx | 233 ++++++ .../ar/developers/extend/apps/publishing.mdx | 119 +++ .../developers/extend/capabilities/apps.mdx | 22 +- .../l/ar/developers/extend/extend.mdx | 11 +- .../l/ar/developers/extend/webhooks.mdx | 116 +++ .../l/ar/developers/introduction.mdx | 22 +- .../how-tos/export-your-data.mdx | 6 +- .../how-tos/import-data-via-api.mdx | 10 +- .../capabilities/what-is-twenty.mdx | 2 +- .../display-related-record-data.mdx | 2 +- .../frontend-commands.mdx | 2 +- .../frontend-commands.mdx | 2 +- .../l/de/developers/extend/api.mdx | 147 ++++ .../l/de/developers/extend/apps/building.mdx | 689 ++++++++++++++++++ .../extend/apps/getting-started.mdx | 233 ++++++ .../de/developers/extend/apps/publishing.mdx | 119 +++ .../l/de/developers/extend/extend.mdx | 11 +- .../l/de/developers/extend/webhooks.mdx | 116 +++ .../l/de/developers/introduction.mdx | 22 +- .../how-tos/export-your-data.mdx | 6 +- .../how-tos/import-data-via-api.mdx | 10 +- .../capabilities/what-is-twenty.mdx | 2 +- .../display-related-record-data.mdx | 2 +- .../frontend-commands.mdx | 2 +- .../l/it/developers/extend/api.mdx | 147 ++++ .../l/it/developers/extend/apps/building.mdx | 689 ++++++++++++++++++ .../extend/apps/getting-started.mdx | 233 ++++++ .../it/developers/extend/apps/publishing.mdx | 119 +++ .../l/it/developers/extend/extend.mdx | 11 +- .../l/it/developers/extend/webhooks.mdx | 116 +++ .../l/it/developers/introduction.mdx | 22 +- .../how-tos/export-your-data.mdx | 6 +- .../how-tos/import-data-via-api.mdx | 10 +- .../capabilities/what-is-twenty.mdx | 2 +- .../display-related-record-data.mdx | 2 +- .../frontend-commands.mdx | 2 +- .../l/pt/developers/extend/api.mdx | 147 ++++ .../l/pt/developers/extend/apps/building.mdx | 689 ++++++++++++++++++ .../extend/apps/getting-started.mdx | 233 ++++++ .../pt/developers/extend/apps/publishing.mdx | 119 +++ .../developers/extend/capabilities/apps.mdx | 22 +- .../l/pt/developers/extend/extend.mdx | 11 +- .../l/pt/developers/extend/webhooks.mdx | 116 +++ .../l/pt/developers/introduction.mdx | 22 +- .../how-tos/export-your-data.mdx | 6 +- .../how-tos/import-data-via-api.mdx | 10 +- .../capabilities/what-is-twenty.mdx | 2 +- .../display-related-record-data.mdx | 2 +- .../l/ro/developers/extend/api.mdx | 147 ++++ .../l/ro/developers/extend/apps/building.mdx | 689 ++++++++++++++++++ .../extend/apps/getting-started.mdx | 233 ++++++ .../ro/developers/extend/apps/publishing.mdx | 119 +++ .../l/ro/developers/extend/extend.mdx | 11 +- .../l/ro/developers/extend/webhooks.mdx | 116 +++ .../l/ro/developers/introduction.mdx | 22 +- .../how-tos/export-your-data.mdx | 6 +- .../how-tos/import-data-via-api.mdx | 10 +- .../capabilities/what-is-twenty.mdx | 2 +- .../display-related-record-data.mdx | 2 +- .../l/ru/developers/extend/api.mdx | 147 ++++ .../l/ru/developers/extend/apps/building.mdx | 689 ++++++++++++++++++ .../extend/apps/getting-started.mdx | 233 ++++++ .../ru/developers/extend/apps/publishing.mdx | 119 +++ .../developers/extend/capabilities/apps.mdx | 22 +- .../l/ru/developers/extend/extend.mdx | 11 +- .../l/ru/developers/extend/webhooks.mdx | 116 +++ .../l/ru/developers/introduction.mdx | 22 +- .../how-tos/export-your-data.mdx | 6 +- .../how-tos/import-data-via-api.mdx | 10 +- .../capabilities/what-is-twenty.mdx | 2 +- .../display-related-record-data.mdx | 2 +- .../l/tr/developers/extend/api.mdx | 147 ++++ .../l/tr/developers/extend/apps/building.mdx | 689 ++++++++++++++++++ .../extend/apps/getting-started.mdx | 233 ++++++ .../tr/developers/extend/apps/publishing.mdx | 119 +++ .../developers/extend/capabilities/apps.mdx | 22 +- .../l/tr/developers/extend/extend.mdx | 11 +- .../l/tr/developers/extend/webhooks.mdx | 116 +++ .../l/tr/developers/introduction.mdx | 22 +- .../how-tos/export-your-data.mdx | 6 +- .../how-tos/import-data-via-api.mdx | 10 +- .../capabilities/what-is-twenty.mdx | 2 +- .../display-related-record-data.mdx | 2 +- .../frontend-commands.mdx | 2 +- 87 files changed, 9331 insertions(+), 280 deletions(-) create mode 100644 packages/twenty-docs/l/ar/developers/extend/api.mdx create mode 100644 packages/twenty-docs/l/ar/developers/extend/apps/building.mdx create mode 100644 packages/twenty-docs/l/ar/developers/extend/apps/getting-started.mdx create mode 100644 packages/twenty-docs/l/ar/developers/extend/apps/publishing.mdx create mode 100644 packages/twenty-docs/l/ar/developers/extend/webhooks.mdx create mode 100644 packages/twenty-docs/l/de/developers/extend/api.mdx create mode 100644 packages/twenty-docs/l/de/developers/extend/apps/building.mdx create mode 100644 packages/twenty-docs/l/de/developers/extend/apps/getting-started.mdx create mode 100644 packages/twenty-docs/l/de/developers/extend/apps/publishing.mdx create mode 100644 packages/twenty-docs/l/de/developers/extend/webhooks.mdx create mode 100644 packages/twenty-docs/l/it/developers/extend/api.mdx create mode 100644 packages/twenty-docs/l/it/developers/extend/apps/building.mdx create mode 100644 packages/twenty-docs/l/it/developers/extend/apps/getting-started.mdx create mode 100644 packages/twenty-docs/l/it/developers/extend/apps/publishing.mdx create mode 100644 packages/twenty-docs/l/it/developers/extend/webhooks.mdx create mode 100644 packages/twenty-docs/l/pt/developers/extend/api.mdx create mode 100644 packages/twenty-docs/l/pt/developers/extend/apps/building.mdx create mode 100644 packages/twenty-docs/l/pt/developers/extend/apps/getting-started.mdx create mode 100644 packages/twenty-docs/l/pt/developers/extend/apps/publishing.mdx create mode 100644 packages/twenty-docs/l/pt/developers/extend/webhooks.mdx create mode 100644 packages/twenty-docs/l/ro/developers/extend/api.mdx create mode 100644 packages/twenty-docs/l/ro/developers/extend/apps/building.mdx create mode 100644 packages/twenty-docs/l/ro/developers/extend/apps/getting-started.mdx create mode 100644 packages/twenty-docs/l/ro/developers/extend/apps/publishing.mdx create mode 100644 packages/twenty-docs/l/ro/developers/extend/webhooks.mdx create mode 100644 packages/twenty-docs/l/ru/developers/extend/api.mdx create mode 100644 packages/twenty-docs/l/ru/developers/extend/apps/building.mdx create mode 100644 packages/twenty-docs/l/ru/developers/extend/apps/getting-started.mdx create mode 100644 packages/twenty-docs/l/ru/developers/extend/apps/publishing.mdx create mode 100644 packages/twenty-docs/l/ru/developers/extend/webhooks.mdx create mode 100644 packages/twenty-docs/l/tr/developers/extend/api.mdx create mode 100644 packages/twenty-docs/l/tr/developers/extend/apps/building.mdx create mode 100644 packages/twenty-docs/l/tr/developers/extend/apps/getting-started.mdx create mode 100644 packages/twenty-docs/l/tr/developers/extend/apps/publishing.mdx create mode 100644 packages/twenty-docs/l/tr/developers/extend/webhooks.mdx diff --git a/packages/twenty-docs/docs.json b/packages/twenty-docs/docs.json index 14aee96c37..ec68711031 100644 --- a/packages/twenty-docs/docs.json +++ b/packages/twenty-docs/docs.json @@ -1253,7 +1253,7 @@ "l/ar/developers/extend/api", "l/ar/developers/extend/webhooks", { - "group": "Apps", + "group": "التطبيقات", "pages": [ "l/ar/developers/extend/apps/getting-started", "l/ar/developers/extend/apps/building", @@ -3037,7 +3037,7 @@ "l/it/developers/extend/api", "l/it/developers/extend/webhooks", { - "group": "Apps", + "group": "App", "pages": [ "l/it/developers/extend/apps/getting-started", "l/it/developers/extend/apps/building", @@ -4375,7 +4375,7 @@ "l/pt/developers/extend/api", "l/pt/developers/extend/webhooks", { - "group": "Apps", + "group": "Aplicativos", "pages": [ "l/pt/developers/extend/apps/getting-started", "l/pt/developers/extend/apps/building", @@ -4821,7 +4821,7 @@ "l/ro/developers/extend/api", "l/ro/developers/extend/webhooks", { - "group": "Apps", + "group": "Aplicații", "pages": [ "l/ro/developers/extend/apps/getting-started", "l/ro/developers/extend/apps/building", @@ -5267,7 +5267,7 @@ "l/ru/developers/extend/api", "l/ru/developers/extend/webhooks", { - "group": "Apps", + "group": "Приложения", "pages": [ "l/ru/developers/extend/apps/getting-started", "l/ru/developers/extend/apps/building", @@ -5713,7 +5713,7 @@ "l/tr/developers/extend/api", "l/tr/developers/extend/webhooks", { - "group": "Apps", + "group": "Uygulamalar", "pages": [ "l/tr/developers/extend/apps/getting-started", "l/tr/developers/extend/apps/building", @@ -6159,7 +6159,7 @@ "l/zh/developers/extend/api", "l/zh/developers/extend/webhooks", { - "group": "Apps", + "group": "应用", "pages": [ "l/zh/developers/extend/apps/getting-started", "l/zh/developers/extend/apps/building", diff --git a/packages/twenty-docs/l/ar/developers/extend/api.mdx b/packages/twenty-docs/l/ar/developers/extend/api.mdx new file mode 100644 index 0000000000..b43b0e375e --- /dev/null +++ b/packages/twenty-docs/l/ar/developers/extend/api.mdx @@ -0,0 +1,147 @@ +--- +title: واجهات برمجة التطبيقات +description: استعلم وعدّل بيانات إدارة علاقات العملاء (CRM) لديك برمجياً باستخدام REST أو GraphQL. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +تم تصميم Twenty ليكون صديقًا للمطورين، حيث يوفر واجهات برمجة قوية تتكيف مع نموذج البيانات المخصص. نحن نوفر أربعة أنواع متميزة من واجهات برمجة التطبيقات لتلبية احتياجات التكامل المختلفة. + +## نهج المطوّر أولاً + +تقوم Twenty بإنشاء واجهات برمجة التطبيقات خصيصاً لنموذج بياناتك: + +* **لا حاجة إلى معرفات طويلة**: استخدم أسماء الكائنات والحقول مباشرة في نقاط النهاية +* **معاملة متساوية للكائنات القياسية والمخصصة**: تحصل كائناتك المخصصة على نفس معاملة واجهة برمجة التطبيقات كما هو الحال مع الكائنات المضمنة +* **نقاط نهاية مخصصة**: يحصل كل كائن وحقل على نقطة نهاية API الخاصة به +* **وثائق مخصصة**: يتم إنشاؤها خصيصًا لنموذج بيانات مساحة عملك + + +وثائق واجهة برمجة التطبيقات المخصصة لك متاحة ضمن **الإعدادات → واجهات برمجة التطبيقات وخطافات الويب** بعد إنشاء مفتاح API. نظرًا لأن Twenty تُنشئ واجهات برمجة تطبيقات تتطابق مع نموذج البيانات المخصص لديك، فإن الوثائق فريدة لمساحة عملك. + + +## نوعا واجهات برمجة التطبيقات + +### واجهة برمجة التطبيقات الأساسية + +يتم الوصول إليها عبر `/rest/` أو `/graphql/` + +تعامَل مع **السجلات** الفعلية لديك (البيانات): + +* إنشاء وقراءة وتحديث وحذف الأشخاص والشركات والفرص، إلخ. +* استعلام وتصفية البيانات +* إدارة العلاقات بين السجلات + +### واجهة برمجة البيانات الوصفية + +يتم الوصول إليها عبر `/rest/metadata/` أو `/metadata/` + +إدارة **مساحة العمل ونموذج البيانات** لديك: + +* إنشاء أو تعديل أو حذف الكائنات والحقول +* تكوين إعدادات مساحة العمل +* تعريف العلاقات بين الكائنات + +## REST مقابل GraphQL + +تتوفر واجهات برمجة التطبيقات الأساسية وواجهات البيانات الوصفية بصيغتي REST وGraphQL: + +| التنسيق | العمليات المتاحة | +| ----------- | ----------------------------------------------------------------------------- | +| **REST** | CRUD، عمليات الدفعات، إدراج/تحديث | +| **GraphQL** | نفس الشيء + **عمليات إدراج/تحديث مجمعة**، واستعلامات العلاقات في استدعاء واحد | + +اختر بناءً على احتياجاتك — كلا الصيغتين تصلان إلى البيانات نفسها. + +## نقاط نهاية API + +| البيئة | عنوان URL الأساسي | +| --------------------- | ------------------------- | +| **السحابة** | `https://api.twenty.com/` | +| **الاستضافة الذاتية** | `https://{your-domain}/` | + +## المصادقة + +كل طلب API يتطلب تضمين مفتاح API في رأس الطلب: + +``` +Authorization: Bearer YOUR_API_KEY +``` + +### قم بإنشاء مفتاح API + +1. انتقل إلى **الإعدادات → واجهات برمجة التطبيقات وخطافات الويب** +2. انقر على **+ إنشاء مفتاح** +3. التكوين: + * **الاسم**: اسم وصفي للمفتاح + * **تاريخ الانتهاء**: متى تنتهي صلاحية المفتاح +4. انقر على **حفظ** +5. **انسخه فوراً** — يظهر المفتاح مرة واحدة فقط + + + + +يمنح مفتاح API الخاص بك الوصول إلى بيانات حساسة. لا تشاركه مع خدمات غير موثوقة. إذا تم اختراقه، عطّلْه فوراً وأنشئ مفتاحاً جديداً. + + +### تعيين دور لمفتاح API + +لتحسين الأمان، عيّن دوراً محدداً لتقييد الوصول: + +1. اذهب إلى **الإعدادات → الأدوار** +2. انقر على الدور الذي ترغب في تعيينه +3. افتح علامة التبويب **التعيين** +4. ضمن **مفاتيح API**، انقر على **+ تعيين إلى مفتاح API** +5. حدد مفتاح API + +سيرث المفتاح أذونات ذلك الدور. راجع [الأذونات](/l/ar/user-guide/permissions-access/capabilities/permissions) للحصول على التفاصيل. + +### إدارة مفاتيح API + +**إعادة التوليد**: الإعدادات → واجهات برمجة التطبيقات وخطافات الويب → انقر على المفتاح → **إعادة التوليد** + +**حذف**: الإعدادات → واجهات برمجة التطبيقات وخطافات الويب → انقر على المفتاح → **حذف** + +## ملعب واجهة برمجة التطبيقات + +اختبر واجهات برمجة التطبيقات لديك مباشرة في المتصفح باستخدام الملعب المدمج لدينا — متاح لكلٍ من **REST** و**GraphQL**. + +### الوصول إلى الملعب + +1. انتقل إلى **الإعدادات → واجهات برمجة التطبيقات وخطافات الويب** +2. أنشئ مفتاح API (مطلوب) +3. انقر على **REST API** أو **GraphQL API** لفتح الملعب + +### ما الذي ستحصل عليه + +* **وثائق تفاعلية**: يتم إنشاؤها لنموذج البيانات المحدد لديك +* **اختبارات حيّة**: تنفيذ استدعاءات API فعلية على مساحة عملك +* **مستكشف المخطط**: تصفح الكائنات والحقول والعلاقات المتاحة +* **منشئ الطلبات**: أنشئ الاستعلامات مع الإكمال التلقائي + +يعكس الملعب الكائنات والحقول المخصصة لديك، لذا تكون الوثائق دائماً دقيقة لمساحة عملك. + +## عمليات الدفعات + +كلٌ من REST وGraphQL يدعمان عمليات الدفعات: + +* **حجم الدفعة**: حتى 60 سجل لكل طلب +* **العمليات**: إنشاء وتحديث وحذف سجلات متعددة + +**ميزات خاصة بـ GraphQL:** + +* **إدراج/تحديث دفعي**: إنشاء أو تحديث في استدعاء واحد +* استخدم الأسماء الجمع للكائنات (على سبيل المثال، `CreateCompanies` بدلاً من `CreateCompany`) + +## حدود المعدل + +يتم تنظيم طلبات API لضمان استقرار المنصة: + +| الحد | القيمة | +| -------------- | ---------------------- | +| **الطلبات** | 100 استدعاء في الدقيقة | +| **حجم الدفعة** | 60 سجل لكل استدعاء | + + +استخدم عمليات الدفعات لزيادة الإنتاجية — عالج ما يصل إلى 60 سجلًا في استدعاء API واحد بدلاً من إجراء طلبات فردية. + diff --git a/packages/twenty-docs/l/ar/developers/extend/apps/building.mdx b/packages/twenty-docs/l/ar/developers/extend/apps/building.mdx new file mode 100644 index 0000000000..0007a7d282 --- /dev/null +++ b/packages/twenty-docs/l/ar/developers/extend/apps/building.mdx @@ -0,0 +1,689 @@ +--- +title: بناء التطبيقات +description: عرّف الكائنات، والدوال المنطقية، ومكوّنات الواجهة الأمامية، وغير ذلك باستخدام Twenty SDK. +--- + + +التطبيقات حاليًا في مرحلة الاختبار الألفا. الميزة تعمل لكنها لا تزال قيد التطور. + + +## استخدم موارد SDK (الأنواع والتكوين) + +يوفّر twenty-sdk كتلَ بناءٍ مضبوطة الأنواع ودوال مساعدة تستخدمها داخل تطبيقك. فيما يلي الأجزاء الأساسية التي ستتعامل معها غالبًا. + +### دوال مساعدة + +يوفّر SDK دوالًا مساعدة لتعريف كيانات تطبيقك. كما هو موضح في [اكتشاف الكيانات](/l/ar/developers/extend/apps/getting-started#entity-detection)، يجب استخدام `export default define({...})` كي يتم اكتشاف كياناتك: + +| دالة | الغرض | +| -------------------------------- | ---------------------------------------------------- | +| `defineApplication` | تهيئة بيانات التعريف للتطبيق (مطلوب، واحد لكل تطبيق) | +| `defineObject` | تعريف كائنات مخصصة مع حقول | +| `defineLogicFunction` | تعريف وظائف منطقية مع معالجات | +| `definePreInstallLogicFunction` | تعريف دالة منطقية لما قبل التثبيت (واحدة لكل تطبيق) | +| `definePostInstallLogicFunction` | تعريف دالة منطقية لما بعد التثبيت (واحدة لكل تطبيق) | +| `defineFrontComponent` | عرِّف مكوّنات أمامية لواجهة مستخدم مخصّصة | +| `defineRole` | تهيئة صلاحيات الدور والوصول إلى الكائنات | +| `defineField` | وسّع الكائنات الموجودة بحقول إضافية | +| `defineView` | تعريف العروض المحفوظة للكائنات | +| `defineNavigationMenuItem` | تعريف روابط التنقل في الشريط الجانبي | +| `defineSkill` | عرّف مهارات وكيل الذكاء الاصطناعي | + +تتحقق هذه الدوال من تكوينك وقت البناء وتوفّر إكمالًا تلقائيًا في بيئة التطوير وأمان الأنواع. + +### تعريف الكائنات + +تصف الكائنات المخصصة كلًا من المخطط والسلوك للسجلات في مساحة عملك. استخدم `defineObject()` لتعريف كائنات مع تحقق مدمج: + +```typescript +// src/app/postCard.object.ts +import { defineObject, FieldType } from 'twenty-sdk'; + +enum PostCardStatus { + DRAFT = 'DRAFT', + SENT = 'SENT', + DELIVERED = 'DELIVERED', + RETURNED = 'RETURNED', +} + +export default defineObject({ + universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05', + nameSingular: 'postCard', + namePlural: 'postCards', + labelSingular: 'Post Card', + labelPlural: 'Post Cards', + description: 'A post card object', + icon: 'IconMail', + fields: [ + { + universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b', + name: 'content', + type: FieldType.TEXT, + label: 'Content', + description: "Postcard's content", + icon: 'IconAbc', + }, + { + universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac', + name: 'recipientName', + type: FieldType.FULL_NAME, + label: 'Recipient name', + icon: 'IconUser', + }, + { + universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266', + name: 'recipientAddress', + type: FieldType.ADDRESS, + label: 'Recipient address', + icon: 'IconHome', + }, + { + universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e', + name: 'status', + type: FieldType.SELECT, + label: 'Status', + icon: 'IconSend', + defaultValue: `'${PostCardStatus.DRAFT}'`, + options: [ + { value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' }, + { value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' }, + { value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' }, + { value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' }, + ], + }, + { + universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433', + name: 'deliveredAt', + type: FieldType.DATE_TIME, + label: 'Delivered at', + icon: 'IconCheck', + isNullable: true, + defaultValue: null, + }, + ], +}); +``` + +النقاط الرئيسية: + +* استخدم `defineObject()` للحصول على تحقق مدمج ودعم أفضل من IDE. +* `universalIdentifier` يجب أن يكون فريدًا وثابتًا عبر عمليات النشر. +* يتطلب كل حقل `name` و`type` و`label` ومعرّف `universalIdentifier` ثابتًا خاصًا به. +* المصفوفة `fields` اختيارية — يمكنك تعريف كائنات بدون حقول مخصصة. +* يمكنك إنشاء كائنات جديدة باستخدام `yarn twenty entity:add`، والذي يرشدك خلال التسمية والحقول والعلاقات. + + +**يتم إنشاء الحقول الأساسية تلقائيًا.** عند تعريف كائن مخصص، يضيف Twenty تلقائيًا حقولًا قياسية +مثل `id` و`name` و`createdAt` و`updatedAt` و`createdBy` و`updatedBy` و`deletedAt`. +لا تحتاج إلى تعريف هذه في مصفوفة `fields` — أضف فقط حقولك المخصصة. +يمكنك تجاوز الحقول الافتراضية من خلال تعريف حقل بالاسم نفسه في مصفوفة `fields` الخاصة بك، +لكن هذا غير مستحسن. + + +### تكوين التطبيق (application-config.ts) + +كل تطبيق لديه ملف واحد `application-config.ts` يصف: + +* **هوية التطبيق**: المعرفات، اسم العرض، والوصف. +* **كيفية تشغيل وظائفه**: الدور الذي تستخدمه للأذونات. +* **متغيرات (اختياري)**: أزواج مفتاح-قيمة تُعرض لوظائفك كمتغيرات بيئة. +* **(اختياري) دالة ما قبل التثبيت**: دالة منطقية تعمل قبل تثبيت التطبيق. +* **(اختياري) دالة ما بعد التثبيت**: دالة منطقية تعمل بعد تثبيت التطبيق. + +استخدم `defineApplication()` لتعريف تهيئة تطبيقك: + +```typescript +// src/application-config.ts +import { defineApplication } from 'twenty-sdk'; +import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role'; + +export default defineApplication({ + universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7', + displayName: 'My Twenty App', + description: 'My first Twenty app', + icon: 'IconWorld', + applicationVariables: { + DEFAULT_RECIPIENT_NAME: { + universalIdentifier: '19e94e59-d4fe-4251-8981-b96d0a9f74de', + description: 'Default recipient name for postcards', + value: 'Jane Doe', + isSecret: false, + }, + }, + defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, +}); +``` + +الملاحظات: + +* حقول `universalIdentifier` هي معرّفات حتمية تخصك؛ أنشئها مرة واحدة واحتفظ بها ثابتة عبر عمليات المزامنة. +* `applicationVariables` تصبح متغيرات بيئة لوظائفك (على سبيل المثال، `DEFAULT_RECIPIENT_NAME` متاح كـ `process.env.DEFAULT_RECIPIENT_NAME`). +* `defaultRoleUniversalIdentifier` يجب أن يطابق ملف الدور (انظر أدناه). +* يتم اكتشاف دوال ما قبل التثبيت وما بعد التثبيت تلقائيًا أثناء إنشاء ملف البيان. راجع [دوال ما قبل التثبيت](#pre-install-functions) و[دوال ما بعد التثبيت](#post-install-functions). + +#### الأدوار والصلاحيات + +يمكن للتطبيقات تعريف أدوار تُغلّف الصلاحيات على كائنات وإجراءات مساحة العمل لديك. يعين الحقل `defaultRoleUniversalIdentifier` في `application-config.ts` الدور الافتراضي الذي تستخدمه وظائف المنطق في تطبيقك. + +* مفتاح واجهة البرمجة في وقت التشغيل المحقون باسم `TWENTY_API_KEY` مستمد من دور الوظيفة الافتراضي هذا. +* سيُقيَّد العميل مضبوط الأنواع بالأذونات الممنوحة لذلك الدور. +* اتبع مبدأ أقل الامتياز: أنشئ دورًا مخصصًا بالأذونات التي تحتاجها وظائفك فقط، ثم أشِر إلى معرّفه الشامل. + +##### الدور الافتراضي للوظيفة (*.role.ts) + +عند توليد تطبيق جديد بالقالب، ينشئ CLI أيضًا ملف دور افتراضي. استخدم `defineRole()` لتعريف أدوار مع تحقق مدمج: + +```typescript +// src/roles/default-role.ts +import { defineRole, PermissionFlag } from 'twenty-sdk'; + +export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = + 'b648f87b-1d26-4961-b974-0908fd991061'; + +export default defineRole({ + universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, + label: 'Default function role', + description: 'Default role for function Twenty client', + canReadAllObjectRecords: false, + canUpdateAllObjectRecords: false, + canSoftDeleteAllObjectRecords: false, + canDestroyAllObjectRecords: false, + canUpdateAllSettings: false, + canBeAssignedToAgents: false, + canBeAssignedToUsers: false, + canBeAssignedToApiKeys: false, + objectPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + canReadObjectRecords: true, + canUpdateObjectRecords: true, + canSoftDeleteObjectRecords: false, + canDestroyObjectRecords: false, + }, + ], + fieldPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + fieldUniversalIdentifier: 'b2c37dc0-8ae7-470e-96cd-1476b47dfaff', + canReadFieldValue: false, + canUpdateFieldValue: false, + }, + ], + permissionFlags: [PermissionFlag.APPLICATIONS], +}); +``` + +يُشار بعد ذلك إلى `universalIdentifier` لهذا الدور في `application-config.ts` باسم `defaultRoleUniversalIdentifier`. بعبارة أخرى: + +* **\\*.role.ts** يحدد ما يمكن أن يفعله الدور الافتراضي للوظيفة. +* **application-config.ts** يشير إلى ذلك الدور بحيث ترث وظائفك أذوناته. + +الملاحظات: + +* ابدأ من الدور المُنشأ بالقالب، ثم قيّده تدريجيًا باتباع مبدأ أقل الامتياز. +* استبدل `objectPermissions` و`fieldPermissions` بالكائنات/الحقول التي تحتاجها وظائفك. +* `permissionFlags` تتحكم في الوصول إلى القدرات على مستوى المنصة. اجعلها في الحد الأدنى؛ أضف فقط ما تحتاجه. +* اطّلع على مثال عملي في تطبيق Hello World: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). + +### تكوين الوظيفة المنطقية ونقطة الدخول + +كل ملف وظيفة يستخدم `defineLogicFunction()` لتصدير تكوين مع معالج ومشغّلات اختيارية. + +```typescript +// src/app/createPostCard.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk'; +import { CoreApiClient, type Person } from 'twenty-sdk/generated'; + +const handler = async (params: RoutePayload) => { + const client = new CoreApiClient(); + const name = 'name' in params.queryStringParameters + ? params.queryStringParameters.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world' + : 'Hello world'; + + const result = await client.mutation({ + createPostCard: { + __args: { data: { name } }, + id: true, + name: true, + }, + }); + return result; +}; + +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'create-new-post-card', + timeoutSeconds: 2, + handler, + triggers: [ + // Public HTTP route trigger '/s/post-card/create' + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/post-card/create', + httpMethod: 'GET', + isAuthRequired: false, + }, + // Cron trigger (CRON pattern) + // { + // universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2', + // type: 'cron', + // pattern: '0 0 1 1 *', + // }, + // Database event trigger + // { + // universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156', + // type: 'databaseEvent', + // eventName: 'person.updated', + // updatedFields: ['name'], + // }, + ], +}); +``` + +أنواع المشغلات الشائعة: + +* **route**: يعرِض وظيفتك على مسار وطريقة HTTP **تحت نقطة النهاية `/s/`**: + +> مثال: `path: '/post-card/create',` -> الاستدعاء على `/s/post-card/create` + +* **cron**: يشغّل وظيفتك على جدول باستخدام تعبير CRON. +* **databaseEvent**: يعمل على أحداث دورة حياة كائنات مساحة العمل. عندما تكون عملية الحدث هي `updated`، يمكن تحديد الحقول المحددة المراد الاستماع إليها في مصفوفة `updatedFields`. إذا تُركت غير معرّفة أو فارغة، فسيؤدي أي تحديث إلى تشغيل الدالة. + +> مثال: `person.updated` + +الملاحظات: + +* المصفوفة `triggers` اختيارية. يمكن استخدام الوظائف بدون مشغلات كوظائف مساعدة تُستدعى بواسطة وظائف أخرى. +* يمكنك مزج أنواع متعددة من المشغلات في وظيفة واحدة. + +### دوال ما قبل التثبيت + +دالة ما قبل التثبيت هي دالة منطقية تعمل تلقائيًا قبل تثبيت تطبيقك على مساحة عمل. يفيد ذلك في مهام التحقق، وفحص المتطلبات المسبقة، أو تجهيز حالة مساحة العمل قبل متابعة التثبيت الرئيسي. + +عند إنشاء هيكل تطبيق جديد باستخدام `create-twenty-app`، يتم إنشاء دالة ما قبل التثبيت لك في `src/logic-functions/pre-install.ts`: + +```typescript +// src/logic-functions/pre-install.ts +import { definePreInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Pre install logic function executed successfully!', payload.previousVersion); +}; + +export default definePreInstallLogicFunction({ + universalIdentifier: '', + name: 'pre-install', + description: 'Runs before installation to prepare the application.', + timeoutSeconds: 300, + handler, +}); +``` + +يمكنك أيضًا تنفيذ دالة ما قبل التثبيت يدويًا في أي وقت باستخدام CLI: + +```bash filename="Terminal" +yarn twenty function:execute --preInstall +``` + +النقاط الرئيسية: + +* تستخدم دوال ما قبل التثبيت `definePreInstallLogicFunction()` — وهو إصدار متخصص يستبعد إعدادات المُشغِّل (`cronTriggerSettings` و`databaseEventTriggerSettings` و`httpRouteTriggerSettings` و`isTool`). +* يتلقى المُعالج `InstallLogicFunctionPayload` يحوي `{ previousVersion: string }` — إصدار التطبيق الذي كان مُثبّتًا سابقًا (أو سلسلة فارغة للتثبيتات الجديدة). +* يُسمح بدالة ما قبل التثبيت واحدة فقط لكل تطبيق. سيُنتج إنشاء ملف البيان خطأً إذا تم اكتشاف أكثر من واحدة. +* يتم تعيين `universalIdentifier` للدالة تلقائيًا كـ `preInstallLogicFunctionUniversalIdentifier` في بيان التطبيق أثناء الإنشاء — لست بحاجة إلى الإشارة إليه في `defineApplication()`. +* تم ضبط المهلة الافتراضية على 300 ثانية (5 دقائق) للسماح بمهام التحضير الأطول. +* لا تحتاج دوال ما قبل التثبيت إلى مُشغِّلات — إذ يستدعيها النظام الأساسي قبل التثبيت أو يدويًا عبر `function:execute --preInstall`. + +### دوال ما بعد التثبيت + +دالة ما بعد التثبيت هي دالة منطقية تعمل تلقائيًا بعد تثبيت تطبيقك على مساحة عمل. هذا مفيد لمهام الإعداد لمرة واحدة مثل تهيئة البيانات الافتراضية، وإنشاء السجلات الأولية، أو تكوين إعدادات مساحة العمل. + +عند إنشاء هيكل تطبيق جديد باستخدام `create-twenty-app`، يتم إنشاء دالة ما بعد التثبيت لك في `src/logic-functions/post-install.ts`: + +```typescript +// src/logic-functions/post-install.ts +import { definePostInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Post install logic function executed successfully!', payload.previousVersion); +}; + +export default definePostInstallLogicFunction({ + universalIdentifier: '', + name: 'post-install', + description: 'Runs after installation to set up the application.', + timeoutSeconds: 300, + handler, +}); +``` + +يمكنك أيضًا تنفيذ دالة ما بعد التثبيت يدويًا في أي وقت باستخدام CLI: + +```bash filename="Terminal" +yarn twenty function:execute --postInstall +``` + +النقاط الرئيسية: + +* تستخدم دوال ما بعد التثبيت `definePostInstallLogicFunction()` — وهو إصدار متخصص يستبعد إعدادات المُشغِّل (`cronTriggerSettings` و`databaseEventTriggerSettings` و`httpRouteTriggerSettings` و`isTool`). +* يتلقى المُعالج `InstallLogicFunctionPayload` يحوي `{ previousVersion: string }` — إصدار التطبيق الذي كان مُثبّتًا سابقًا (أو سلسلة فارغة للتثبيتات الجديدة). +* يُسمح بدالة ما بعد التثبيت واحدة فقط لكل تطبيق. سيُنتج إنشاء ملف البيان خطأً إذا تم اكتشاف أكثر من واحدة. +* يتم تعيين `universalIdentifier` للدالة تلقائيًا كـ `postInstallLogicFunctionUniversalIdentifier` في بيان التطبيق أثناء الإنشاء — لست بحاجة إلى الإشارة إليه في `defineApplication()`. +* تم تعيين مهلة افتراضية إلى 300 ثانية (5 دقائق) للسماح بمهام الإعداد الأطول مثل تهيئة البيانات. +* لا تحتاج دوال ما بعد التثبيت إلى مُشغِّلات — حيث يستدعيها النظام الأساسي أثناء التثبيت أو يدويًا عبر `function:execute --postInstall`. + +### حمولة مشغل المسار + + +**تغيير غير متوافق (v1.16، يناير 2026):** لقد تغير تنسيق حمولة مشغل المسار. قبل v1.16، كانت معلمات الاستعلام، ومعلمات المسار، وجسم الطلب تُرسل مباشرةً كحمولة. بدءًا من v1.16، أصبحت متداخلة داخل كائن منظَّم `RoutePayload`. + +**قبل v1.16:** +```typescript +const handler = async (params) => { + const { param1, param2 } = params; // Direct access +}; +``` + +**بعد v1.16:** +```typescript +const handler = async (event: RoutePayload) => { + const { param1, param2 } = event.body; // Access via .body + const { queryParam } = event.queryStringParameters; + const { id } = event.pathParameters; +}; +``` + +**لترحيل الدوال الحالية:** حدّث المعالج لديك لفكّ البنية من `event.body` أو `event.queryStringParameters` أو `event.pathParameters` بدلاً من القراءة مباشرةً من كائن params. + + +عندما يستدعي مشغّل المسار وظيفتك المنطقية، يتلقى كائنًا من النوع `RoutePayload` يتبع تنسيق AWS HTTP API v2. استورد النوع من `twenty-sdk`: + +```typescript +import { defineLogicFunction, type RoutePayload } from 'twenty-sdk'; + +const handler = async (event: RoutePayload) => { + // Access request data + const { headers, queryStringParameters, pathParameters, body } = event; + + // HTTP method and path are available in requestContext + const { method, path } = event.requestContext.http; + + return { message: 'Success' }; +}; +``` + +يحتوي نوع `RoutePayload` على البنية التالية: + +| الخاصية | النوع | الوصف | +| ---------------------------- | ------------------------------------- | --------------------------------------------------------------------------------------- | +| `headers` | `Record` | رؤوس HTTP (فقط تلك المدرجة في `forwardedRequestHeaders`) | +| `queryStringParameters` | `Record` | معلمات سلسلة الاستعلام (تُضمّ القيم المتعددة باستخدام فواصل) | +| `pathParameters` | `Record` | معلمات المسار المستخرجة من نمط المسار (على سبيل المثال، `/users/:id` → `{ id: '123' }`) | +| `المحتوى` | `object \| null` | جسم الطلب المُحلَّل (JSON) | +| `isBase64Encoded` | `قيمة منطقية` | ما إذا كان جسم الطلب مُرمَّزًا بترميز base64 | +| `requestContext.http.method` | `string` | طريقة HTTP (GET, POST, PUT, PATCH, DELETE) | +| `requestContext.http.path` | `string` | المسار الخام للطلب | + +### تمرير رؤوس HTTP + +افتراضيًا، **لا** تُمرَّر رؤوس HTTP من الطلبات الواردة إلى دالتك المنطقية لأسباب أمنية. للوصول إلى رؤوس محددة، قم بإدراجها صراحةً في مصفوفة `forwardedRequestHeaders`: + +```typescript +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'webhook-handler', + handler, + triggers: [ + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/webhook', + httpMethod: 'POST', + isAuthRequired: false, + forwardedRequestHeaders: ['x-webhook-signature', 'content-type'], + }, + ], +}); +``` + +في المعالج الخاص بك، يمكنك حينها الوصول إلى هذه الرؤوس: + +```typescript +const handler = async (event: RoutePayload) => { + const signature = event.headers['x-webhook-signature']; + const contentType = event.headers['content-type']; + + // Validate webhook signature... + return { received: true }; +}; +``` + + + تُحوَّل أسماء الرؤوس إلى أحرف صغيرة. يمكنك الوصول إليها باستخدام مفاتيح بأحرف صغيرة (على سبيل المثال، `event.headers['content-type']`). + + +يمكنك إنشاء وظائف جديدة بطريقتين: + +* **مُنشأ بالقالب**: شغّل `yarn twenty entity:add` واختر خيار إضافة دالة منطقية جديدة. يُولّد هذا ملفًا مبدئيًا مع معالج وتكوين. +* **يدوي**: أنشئ ملفًا جديدًا `*.logic-function.ts` واستخدم `defineLogicFunction()` مع اتباع النمط نفسه. + +### تمييز دالة منطقية كأداة + +يمكن إتاحة الدوال المنطقية بوصفها **أدوات** لوكلاء الذكاء الاصطناعي وسير العمل. عندما يتم تمييز دالة كأداة، تصبح قابلة للاكتشاف بواسطة ميزات الذكاء الاصطناعي الخاصة بـ Twenty ويمكن اختيارها كخطوة في أتمتة سير العمل. + +لتمييز دالة منطقية كأداة، عيّن `isTool: true` وقدّم `toolInputSchema` يصف معاملات الإدخال المتوقعة باستخدام [مخطط JSON](https://json-schema.org/): + +```typescript +// src/logic-functions/enrich-company.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import { CoreApiClient } from 'twenty-sdk/generated'; + +const handler = async (params: { companyName: string; domain?: string }) => { + const client = new CoreApiClient(); + + const result = await client.mutation({ + createTask: { + __args: { + data: { + title: `Enrich data for ${params.companyName}`, + body: `Domain: ${params.domain ?? 'unknown'}`, + }, + }, + id: true, + }, + }); + + return { taskId: result.createTask.id }; +}; + +export default defineLogicFunction({ + universalIdentifier: 'f47ac10b-58cc-4372-a567-0e02b2c3d479', + name: 'enrich-company', + description: 'Enrich a company record with external data', + timeoutSeconds: 10, + handler, + isTool: true, + toolInputSchema: { + type: 'object', + properties: { + companyName: { + type: 'string', + description: 'The name of the company to enrich', + }, + domain: { + type: 'string', + description: 'The company website domain (optional)', + }, + }, + required: ['companyName'], + }, +}); +``` + +النقاط الرئيسية: + +* **`isTool`** (`boolean`, الافتراضي: `false`): عند ضبطه على `true`، يتم تسجيل الدالة كأداة وتصبح متاحة لوكلاء الذكاء الاصطناعي ولأتمتة سير العمل. +* **`toolInputSchema`** (`object`, اختياري): كائن JSON Schema يصف المعلمات التي تقبلها دالتك. يستخدم وكلاء الذكاء الاصطناعي هذا المخطط لفهم المدخلات التي تتوقعها الأداة وللتحقق من صحة الاستدعاءات. إذا تم إغفاله، فالقيمة الافتراضية للمخطط هي `{ type: 'object', properties: {} }` (من دون معلمات). +* الدوال التي لديها `isTool: false` (أو غير معيَّنة) **غير** معروضة كأدوات. لا يزال بالإمكان تنفيذها مباشرةً أو استدعاؤها بواسطة دوال أخرى، لكنها لن تظهر في اكتشاف الأدوات. +* **تسمية الأداة**: عند كشفها كأداة، يتم تطبيع اسم الدالة تلقائيًا إلى `logic_function_` (تحويله إلى أحرف صغيرة، واستبدال المحارف غير الأبجدية الرقمية بشرطات سفلية). على سبيل المثال، `enrich-company` تصبح `logic_function_enrich_company`. +* يمكنك دمج `isTool` مع المشغِّلات — إذ يمكن للدالة أن تكون أداة (قابلة للاستدعاء من قِبل وكلاء الذكاء الاصطناعي) وأن تُشغَّل بواسطة أحداث (cron، وأحداث قاعدة البيانات، والمسارات) في الوقت نفسه. + + +**اكتب `description` جيدًا.** يعتمد وكلاء الذكاء الاصطناعي على حقل `description` الخاص بالدالة لتحديد وقت استخدام الأداة. كن محددًا بشأن ما تفعله الأداة ومتى ينبغي استدعاؤها. + + +### المكوّنات الأمامية + +تتيح لك المكوّنات الأمامية إنشاء مكوّنات React مخصّصة تُعرَض داخل واجهة مستخدم Twenty. استخدم `defineFrontComponent()` لتعريف مكوّنات مع تحقّق مدمج: + +```typescript +// src/front-components/my-widget.tsx +import { defineFrontComponent } from 'twenty-sdk'; + +const MyWidget = () => { + return ( +
+

My Custom Widget

+

This is a custom front component for Twenty.

+
+ ); +}; + +export default defineFrontComponent({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'my-widget', + description: 'A custom widget component', + component: MyWidget, +}); +``` + +النقاط الرئيسية: + +* المكوّنات الأمامية هي مكوّنات React تُعرَض ضمن سياقات معزولة داخل Twenty. +* يشير الحقل `component` إلى مكوّن React الخاص بك. +* يتم بناء المكوّنات ومزامنتها تلقائيًا أثناء `yarn twenty app:dev`. + +يمكنك إنشاء مكوّنات أمامية جديدة بطريقتين: + +* **مُنشأ بالقالب**: شغّل `yarn twenty entity:add` واختر خيار إضافة مكوّن أمامي جديد. +* **يدوي**: أنشئ ملفًا جديدًا `.tsx` واستخدم `defineFrontComponent()` مع اتباع النمط نفسه. + +### المهارات + +تُحدِّد المهارات تعليمات وإمكانات قابلة لإعادة الاستخدام يمكن لوكلاء الذكاء الاصطناعي استخدامها داخل مساحة العمل لديك. استخدم `defineSkill()` لتعريف مهارات مع تحقّق مدمج: + +```typescript +// src/skills/example-skill.ts +import { defineSkill } from 'twenty-sdk'; + +export default defineSkill({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'sales-outreach', + label: 'Sales Outreach', + description: 'Guides the AI agent through a structured sales outreach process', + icon: 'IconBrain', + content: `You are a sales outreach assistant. When reaching out to a prospect: +1. Research the company and recent news +2. Identify the prospect's role and likely pain points +3. Draft a personalized message referencing specific details +4. Keep the tone professional but conversational`, +}); +``` + +النقاط الرئيسية: + +* `name` هي سلسلة معرّف فريدة للمهارة (يُنصَح باستخدام kebab-case). +* `label` هو اسم العرض المقروء للبشر الظاهر في واجهة المستخدم. +* `content` يحتوي على تعليمات المهارة — وهو النص الذي يستخدمه وكيل الذكاء الاصطناعي. +* `icon` (اختياري) يحدّد الأيقونة المعروضة في واجهة المستخدم. +* `description` (اختياري) يوفّر سياقًا إضافيًا حول غرض المهارة. + +يمكنك إنشاء مهارات جديدة بطريقتين: + +* **مُنشأ بالقالب**: شغِّل `yarn twenty entity:add` واختر خيار إضافة مهارة جديدة. +* **يدوي**: أنشئ ملفًا جديدًا واستخدم `defineSkill()` مع اتباع النمط نفسه. + +### عملاء مُولَّدون مضبوطو الأنواع + +يتم توليد عميلين مضبوطي الأنواع تلقائيًا بواسطة `yarn twenty app:dev` وتخزينهما في `node_modules/twenty-sdk/generated` استنادًا إلى مخطط مساحة العمل لديك: + +* **`CoreApiClient`** — يُجري استعلامات إلى نقطة النهاية `/graphql` للحصول على بيانات مساحة العمل +* **`MetadataApiClient`** — يستعلم عن نقطة النهاية `/metadata` لتكوين مساحة العمل وتحميل الملفات. + +```typescript +import { CoreApiClient, MetadataApiClient } from 'twenty-sdk/generated'; + +const client = new CoreApiClient(); +const { me } = await client.query({ me: { id: true, displayName: true } }); + +const metadataClient = new MetadataApiClient(); +const { currentWorkspace } = await metadataClient.query({ currentWorkspace: { id: true } }); +``` + +يُعاد توليد كلا العميلين تلقائيًا بواسطة `yarn twenty app:dev` كلما تغيّرت كائناتك أو حقولك. + +#### بيانات الاعتماد وقت التشغيل في الدوال المنطقية + +عندما تعمل دالتك على Twenty، يقوم النظام الأساسي بحقن بيانات الاعتماد كمتغيرات بيئة قبل تنفيذ كودك: + +* `TWENTY_API_URL`: عنوان URL الأساسي لواجهة Twenty البرمجية التي يستهدفها تطبيقك. +* `TWENTY_API_KEY`: مفتاح قصير العمر ذو نطاق يقتصر على الدور الافتراضي لوظيفة تطبيقك. + +الملاحظات: + +* لا تحتاج إلى تمرير عنوان URL أو مفتاح واجهة برمجة التطبيقات إلى العميل المُولَّد. يقوم بقراءة `TWENTY_API_URL` و`TWENTY_API_KEY` من process.env وقت التشغيل. +* تُحدَّد أذونات مفتاح واجهة برمجة التطبيقات بواسطة الدور المشار إليه في `application-config.ts` عبر `defaultRoleUniversalIdentifier`. هذا هو الدور الافتراضي الذي تستخدمه الدوال المنطقية في تطبيقك. +* يمكن للتطبيقات تعريف أدوار لاتباع مبدأ أقل الامتياز. امنح فقط الأذونات التي تحتاجها وظائفك، ثم وجّه `defaultRoleUniversalIdentifier` إلى المعرّف الشامل لذلك الدور. + +#### رفع الملفات + +يتضمن `MetadataApiClient` المُولَّد طريقة `uploadFile` لإرفاق الملفات بالحقول من نوع ملف ضمن كائنات مساحة العمل الخاصة بك. نظرًا لأن عملاء GraphQL القياسيون لا يدعمون تحميل الملفات متعددة الأجزاء افتراضيًا، يوفر العميل هذه الطريقة المخصصة التي تطبق [مواصفة طلب GraphQL متعدد الأجزاء](https://github.com/jaydenseric/graphql-multipart-request-spec) في الخلفية. + +```typescript +import { MetadataApiClient } from 'twenty-sdk/generated'; +import * as fs from 'fs'; + +const metadataClient = new MetadataApiClient(); + +const fileBuffer = fs.readFileSync('./invoice.pdf'); + +const uploadedFile = await metadataClient.uploadFile( + fileBuffer, // file contents as a Buffer + 'invoice.pdf', // filename + 'application/pdf', // MIME type (defaults to 'application/octet-stream') + '58a0a314-d7ea-4865-9850-7fb84e72f30b', // field universal identifier +); + +console.log(uploadedFile); +// { id: '...', path: '...', size: 12345, createdAt: '...', url: 'https://...' } +``` + +توقيع الطريقة: + +```typescript +uploadFile( + fileBuffer: Buffer, + filename: string, + contentType: string, + fieldMetadataUniversalIdentifier: string, +): Promise<{ id: string; path: string; size: number; createdAt: string; url: string }> +``` + +| المعلمة | النوع | الوصف | +| ---------------------------------- | -------- | ---------------------------------------------------------------------------------- | +| `fileBuffer` | `Buffer` | المحتوى الخام للملف | +| `filename` | `string` | اسم الملف (يُستخدم للتخزين والعرض) | +| `contentType` | `string` | نوع MIME للملف (القيمة الافتراضية هي `application/octet-stream` إذا لم يتم تحديده) | +| `fieldMetadataUniversalIdentifier` | `string` | قيمة `universalIdentifier` لحقل نوع الملف في كائنك | + +النقاط الرئيسية: + +* تتوفر طريقة `uploadFile` على `MetadataApiClient` لأن عملية الـ mutation الخاصة بالرفع تُعالَج عبر نقطة النهاية `/metadata`. +* تستخدم `universalIdentifier` الخاص بالحقل (وليس المعرّف الخاص بمساحة العمل)، ليعمل كود الرفع لديك عبر أي مساحة عمل مُثبَّت فيها تطبيقك — بما يتماشى مع كيفية إشارة التطبيقات إلى الحقول في كل مكان آخر. +* العنوان `url` المُعاد هو عنوان URL موقّع يمكنك استخدامه للوصول إلى الملف المرفوع. + +### مثال Hello World + +استكشف مثالًا بسيطًا شاملًا من البداية إلى النهاية يوضح الكائنات والوظائف المنطقية والمكوّنات الأمامية ومشغّلات متعددة [هنا](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/hello-world). diff --git a/packages/twenty-docs/l/ar/developers/extend/apps/getting-started.mdx b/packages/twenty-docs/l/ar/developers/extend/apps/getting-started.mdx new file mode 100644 index 0000000000..2a111d1047 --- /dev/null +++ b/packages/twenty-docs/l/ar/developers/extend/apps/getting-started.mdx @@ -0,0 +1,233 @@ +--- +title: البدء +description: أنشئ أول تطبيق Twenty خلال دقائق. +--- + + +التطبيقات حاليًا في مرحلة الاختبار الألفا. الميزة تعمل لكنها لا تزال قيد التطور. + + +تتيح لك التطبيقات توسيع Twenty باستخدام كائنات وحقول ووظائف منطقية ومهارات ذكاء اصطناعي ومكونات واجهة مستخدم مخصصة — جميعها تُدار ككود. + +**ما الذي يمكنك فعله اليوم:** + +* عرِّف كائنات وحقولًا مخصصة على شكل كود (نموذج بيانات مُدار) +* أنشئ وظائف منطقية مع مشغلات مخصصة (مسارات HTTP، cron، أحداث قاعدة البيانات) +* حدد المهارات لوكلاء الذكاء الاصطناعي +* أنشئ مكونات واجهية تُعرَض داخل واجهة مستخدم Twenty +* انشر التطبيق نفسه عبر مساحات عمل متعددة + +## المتطلبات الأساسية + +* Node.js 24+ وYarn 4 +* مساحة عمل Twenty ومفتاح واجهة برمجة التطبيقات (أنشئ واحدًا على https://app.twenty.com/settings/api-webhooks) + +## البدء + +أنشئ تطبيقًا جديدًا باستخدام المُهيئ الرسمي، ثم قم بالمصادقة وابدأ التطوير: + +```bash filename="Terminal" +# Scaffold a new app (includes all examples by default) +npx create-twenty-app@latest my-twenty-app +cd my-twenty-app + +# Start dev mode: automatically syncs local changes to your workspace +yarn twenty app:dev +``` + +يدعم المُهيئ وضعين للتحكم في ملفات الأمثلة التي سيتم تضمينها: + +```bash filename="Terminal" +# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item, skill) +npx create-twenty-app@latest my-app + +# Minimal: only core files (application-config.ts and default-role.ts) +npx create-twenty-app@latest my-app --minimal +``` + +من هنا يمكنك: + +```bash filename="Terminal" +# Add a new entity to your application (guided) +yarn twenty entity:add + +# Watch your application's function logs +yarn twenty function:logs + +# Execute a function by name +yarn twenty function:execute -n my-function -p '{"name": "test"}' + +# Execute the pre-install function +yarn twenty function:execute --preInstall + +# Execute the post-install function +yarn twenty function:execute --postInstall + +# Uninstall the application from the current workspace +yarn twenty app:uninstall + +# Display commands' help +yarn twenty help +``` + +راجع أيضًا: صفحات مرجع CLI لـ [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) و[twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk). + +## هيكل المشروع (مُنشأ بالقالب) + +عند تشغيل `npx create-twenty-app@latest my-twenty-app`، يقوم المُهيئ بما يلي: + +* ينسخ تطبيقًا أساسيًا مصغّرًا إلى `my-twenty-app/` +* يضيف اعتمادًا محليًا `twenty-sdk` وتهيئة Yarn 4 +* ينشئ ملفات ضبط ونصوصًا مرتبطة بـ `twenty` CLI +* يُنشئ الملفات الأساسية (تهيئة التطبيق، دور الدالة الافتراضي، دالتا ما قبل التثبيت وما بعد التثبيت) بالإضافة إلى ملفات أمثلة استنادًا إلى وضع الإنشاء. + +يبدو التطبيق المُنشأ حديثًا باستخدام الوضع الافتراضي `--exhaustive` كما يلي: + +```text filename="my-twenty-app/" +my-twenty-app/ + package.json + yarn.lock + .gitignore + .nvmrc + .yarnrc.yml + .yarn/ + install-state.gz + .oxlintrc.json + tsconfig.json + README.md + public/ # Public assets folder (images, fonts, etc.) + src/ + ├── application-config.ts # Required - main application configuration + ├── roles/ + │ └── default-role.ts # Default role for logic functions + ├── objects/ + │ └── example-object.ts # Example custom object definition + ├── fields/ + │ └── example-field.ts # Example standalone field definition + ├── logic-functions/ + │ ├── hello-world.ts # Example logic function + │ ├── pre-install.ts # Pre-install logic function + │ └── post-install.ts # Post-install logic function + ├── front-components/ + │ └── hello-world.tsx # Example front component + ├── views/ + │ └── example-view.ts # Example saved view definition + ├── navigation-menu-items/ + │ └── example-navigation-menu-item.ts # Example sidebar navigation link + └── skills/ + └── example-skill.ts # Example AI agent skill definition +``` + +مع `--minimal`، سيتم إنشاء الملفات الأساسية فقط (`application-config.ts`، `roles/default-role.ts`، `logic-functions/pre-install.ts`، و`logic-functions/post-install.ts`). + +بشكل عام: + +* **package.json**: يصرّح باسم التطبيق والإصدار والمحرّكات (Node 24+، Yarn 4)، ويضيف `twenty-sdk` بالإضافة إلى نص برمجي `twenty` يفوِّض إلى `twenty` CLI المحلي. شغِّل `yarn twenty help` لعرض جميع الأوامر المتاحة. +* **.gitignore**: يتجاهل العناصر الشائعة مثل `node_modules` و`.yarn` و`generated/` (عميل مضبوط الأنواع) و`dist/` و`build/` ومجلدات التغطية وملفات السجلات وملفات `.env*`. +* **yarn.lock**، **.yarnrc.yml**، **.yarn/**: تقوم بقفل وتكوين حزمة أدوات Yarn 4 المستخدمة في المشروع. +* **.nvmrc**: يثبّت إصدار Node.js المتوقع للمشروع. +* **.oxlintrc.json** و **tsconfig.json**: يقدّمان إعدادات الفحص والتهيئة لـ TypeScript لمصادر TypeScript في تطبيقك. +* **README.md**: ملف README قصير في جذر التطبيق يتضمن تعليمات أساسية. +* **public/**: مجلد لتخزين الأصول العامة (صور، خطوط، ملفات ثابتة) التي سيتم تقديمها مع تطبيقك. الملفات الموضوعة هنا تُرفع أثناء المزامنة وتكون متاحة أثناء وقت التشغيل. +* **src/**: المكان الرئيسي حيث تعرّف تطبيقك ككود + +### اكتشاف الكيانات + +يكتشف SDK الكيانات عبر تحليل ملفات TypeScript الخاصة بك بحثًا عن استدعاءات **`export default define({...})`**. يحتوي كل نوع كيان على دالة مساعدة مقابلة يتم تصديرها من `twenty-sdk`: + +| دالة مساعدة | نوع الكيان | +| -------------------------------- | ---------------------------------------------- | +| `defineObject` | تعريفات كائنات مخصصة | +| `defineLogicFunction` | تعريفات الوظائف المنطقية | +| `definePreInstallLogicFunction` | دالة منطقية لما قبل التثبيت (تعمل قبل التثبيت) | +| `definePostInstallLogicFunction` | دالة منطقية لما بعد التثبيت (تعمل بعد التثبيت) | +| `defineFrontComponent` | تعريفات المكونات الواجهية | +| `defineRole` | تعريفات الأدوار | +| `defineField` | امتدادات الحقول للكائنات الموجودة | +| `defineView` | تعريفات العروض المحفوظة | +| `defineNavigationMenuItem` | تعريفات عناصر قائمة التنقل | +| `defineSkill` | تعريفات مهارات وكلاء الذكاء الاصطناعي | + + +**تسمية الملفات مرنة.** يعتمد اكتشاف الكيانات على بنية الشجرة المجردة (AST) — إذ يقوم SDK بفحص ملفات المصدر لديك بحثًا عن النمط `export default define({...})`. يمكنك تنظيم ملفاتك ومجلداتك كيفما تشاء. التجميع حسب نوع الكيان (مثلًا، `logic-functions/` و`roles/`) هو مجرد عرف لتنظيم الشيفرة، وليس مطلبًا إلزاميًا. + + +مثال على كيان تم اكتشافه: + +```typescript +// This file can be named anything and placed anywhere in src/ +import { defineObject, FieldType } from 'twenty-sdk'; + +export default defineObject({ + universalIdentifier: '...', + nameSingular: 'postCard', + // ... rest of config +}); +``` + +ستضيف الأوامر اللاحقة مزيدًا من الملفات والمجلدات: + +* سيقوم `yarn twenty app:dev` بتوليد عميلين API مضبوطي الأنواع تلقائيًا في `node_modules/twenty-sdk/generated`: `CoreApiClient` (لبيانات مساحة العمل عبر `/graphql`) و`MetadataApiClient` (لتكوين مساحة العمل وتحميل الملفات عبر `/metadata`). +* `yarn twenty entity:add` سيضيف ملفات تعريف الكيانات ضمن `src/` لكائناتك المخصّصة، والوظائف، ومكوّنات الواجهة الأمامية، والأدوار، والمهارات، وغير ذلك. + +## المصادقة + +في المرة الأولى التي تشغّل فيها `yarn twenty auth:login`، سيُطلب منك إدخال: + +* عنوان URL لواجهة برمجة التطبيقات (الافتراضي http://localhost:3000 أو ملف تعريف مساحة العمل الحالية لديك) +* مفتاح واجهة برمجة التطبيقات + +تُخزَّن بيانات اعتمادك لكل مستخدم في `~/.twenty/config.json`. يمكنك الاحتفاظ بملفات تعريف متعددة والتبديل بينها. + +### إدارة مساحات العمل + +```bash filename="Terminal" +# Login interactively (recommended) +yarn twenty auth:login + +# Login to a specific workspace profile +yarn twenty auth:login --workspace my-custom-workspace + +# List all configured workspaces +yarn twenty auth:list + +# Switch the default workspace (interactive) +yarn twenty auth:switch + +# Switch to a specific workspace +yarn twenty auth:switch production + +# Check current authentication status +yarn twenty auth:status +``` + +بمجرد أن تقوم بالتبديل بين مساحات العمل باستخدام `yarn twenty auth:switch`، ستستخدم جميع الأوامر اللاحقة تلك المساحة افتراضيًا. لا يزال بإمكانك تجاوزه مؤقتًا باستخدام `--workspace `. + +## إعداد يدوي (بدون المهيئ) + +بينما نوصي باستخدام `create-twenty-app` للحصول على أفضل تجربة للبدء، يمكنك أيضًا إعداد مشروع يدويًا. لا تثبّت CLI عالميًا. بدل ذلك، أضف `twenty-sdk` كاعتماد محلي واربط سكربتًا واحدًا في ملف package.json لديك: + +```bash filename="Terminal" +yarn add -D twenty-sdk +``` + +ثم أضف سكربتًا باسم `twenty`: + +```json filename="package.json" +{ + "scripts": { + "twenty": "twenty" + } +} +``` + +الآن يمكنك تشغيل جميع الأوامر عبر `yarn twenty `، مثلًا: `yarn twenty app:dev`، `yarn twenty help`، إلخ. + +## استكشاف الأخطاء وإصلاحها + +* أخطاء المصادقة: شغّل `yarn twenty auth:login` وتأكد من أن مفتاح واجهة برمجة التطبيقات لديك يمتلك الأذونات المطلوبة. +* يتعذّر الاتصال بالخادم: تحقق من عنوان URL لواجهة برمجة التطبيقات وأن خادم Twenty قابل للوصول. +* الأنواع أو العميل مفقود/قديم: أعد تشغيل `yarn twenty app:dev` — فهو ينشئ العميل مضبوط الأنواع بشكل تلقائي. +* وضع التطوير لا يزامن: تأكد من أن `yarn twenty app:dev` قيد التشغيل وأن التغييرات ليست متجاهلة من بيئتك. + +قناة المساعدة على Discord: https://discord.com/channels/1130383047699738754/1130386664812982322 diff --git a/packages/twenty-docs/l/ar/developers/extend/apps/publishing.mdx b/packages/twenty-docs/l/ar/developers/extend/apps/publishing.mdx new file mode 100644 index 0000000000..5f901cdec6 --- /dev/null +++ b/packages/twenty-docs/l/ar/developers/extend/apps/publishing.mdx @@ -0,0 +1,119 @@ +--- +title: النشر +description: وزّع تطبيق Twenty الخاص بك على سوق Twenty أو انشره داخليًا. +--- + + +التطبيقات حاليًا في مرحلة الاختبار الألفا. الميزة تعمل لكنها لا تزال قيد التطور. + + +## نظرة عامة + +بمجرد أن يكون تطبيقك [مبنيًا ومختبرًا محليًا](/l/ar/developers/extend/apps/building)، لديك مساران لتوزيعه: + +* **النشر على npm** — أدرج تطبيقك في سوق Twenty ليتسنى لأي مساحة عمل اكتشافه وتثبيته. +* **إرسال tarball** — انشر تطبيقك إلى خادم Twenty معيّن للاستخدام الداخلي من دون جعله متاحًا للعامة. + +## النشر على npm + +يُتيح النشر على npm إمكانية العثور على تطبيقك في سوق Twenty. يمكن لأي مساحة عمل في Twenty استعراض تطبيقات السوق وتثبيتها وترقيتها مباشرةً من واجهة المستخدم. + +### المتطلبات + +* حساب على [npm](https://www.npmjs.com) +* يجب أن يستخدم اسم الحزمة البادئة `twenty-app-` (مثلًا، `twenty-app-postcard-sender`) + +### الخطوات + +1. **قم ببناء تطبيقك** — تقوم أداة CLI بتجميع مصادر TypeScript الخاصة بك وإنشاء ملف بيان التطبيق: + +```bash filename="Terminal" +yarn twenty app:build +``` + +2. **النشر على npm** — ادفع الحزمة المبنية إلى سجل npm: + +```bash filename="Terminal" +npx twenty app:publish +``` + +### الاكتشاف التلقائي + +تُكتشف الحِزم التي تحمل البادئة `twenty-app-` تلقائيًا بواسطة فهرس سوق Twenty. بعد نشره، سيظهر تطبيقك في السوق خلال بضع دقائق — من دون الحاجة إلى تسجيل يدوي أو موافقة يدوية. + +### النشر عبر CI + +يتضمن المشروع المُولَّد سير عمل GitHub Actions يقوم بالنشر عند كل إصدار. يشغِّل `app:build`، ثم ينفِّذ `npm publish --provenance` من مخرجات البناء: + +```yaml filename=".github/workflows/publish.yml" +name: Publish +on: + release: + types: [published] + +permissions: + contents: read + id-token: write + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "24" + registry-url: https://registry.npmjs.org + - run: yarn install --immutable + - run: npx twenty app:build + - run: npm publish --provenance --access public + working-directory: .twenty/output + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} +``` + +بالنسبة لأنظمة CI الأخرى (GitLab CI، CircleCI، إلخ)، تنطبق الأوامر الثلاثة نفسها: `yarn install`، ثم `npx twenty app:build`، ثم `npm publish` من `.twenty/output`. + + +**npm provenance** اختياري ولكنه موصى به. يضيف النشر باستخدام `--provenance` شارة ثقة إلى إدراجك على npm، مما يتيح للمستخدمين التحقق من أن الحزمة تم بناؤها من التزام محدد ضمن خط أنابيب CI عام. راجع [وثائق npm provenance](https://docs.npmjs.com/generating-provenance-statements) للحصول على تعليمات الإعداد. + + +## التوزيع الداخلي + +بالنسبة للتطبيقات التي لا تريد إتاحتها للعامة — مثل الأدوات المملوكة، أو عمليات التكامل الخاصة بالمؤسسات فقط، أو الإصدارات التجريبية — يمكنك إرسال tarball مباشرةً إلى خادم Twenty. + +### إرسال tarball + +قم ببناء تطبيقك وانشره إلى خادم محدد في خطوة واحدة: + +```bash filename="Terminal" +npx twenty app:publish --server +``` + +يمكن لأي مساحة عمل على ذلك الخادم بعدها تثبيت التطبيق وترقيته من صفحة الإعدادات **التطبيقات**. + +### إدارة الإصدارات + +لطرح تحديث: + +1. ارفع قيمة الحقل `version` في ملف `package.json` +2. أرسل tarball جديدًا باستخدام `npx twenty app:publish --server ` +3. سترى مساحات العمل على ذلك الخادم الترقية متاحة في إعداداتها + + +التطبيقات الداخلية مقتصرة على الخادم الذي تُرسل إليه. لن تظهر في السوق العام ولا يمكن لمساحات العمل على خوادم أخرى تثبيتها. + + +## فئات التطبيقات + +تُنظِّم Twenty التطبيقات في ثلاث فئات استنادًا إلى طريقة توزيعها: + +| الفئة | كيف يعمل | مرئي في سوق Twenty؟ | +| ----------- | ---------------------------------------------------------------------------------------------------- | ------------------- | +| **التطوير** | تطبيقات وضع التطوير المحلي التي تعمل عبر `yarn twenty app:dev`. تُستخدم للبناء والاختبار. | لا | +| **منشور** | تطبيقات منشورة على npm مع البادئة `twenty-app-`. مدرجة في سوق Twenty لتتمكن أي مساحة عمل من تثبيتها. | نعم | +| **داخلي** | تطبيقات منشورة عبر tarball إلى خادم محدد. متاحة فقط لمساحات العمل على ذلك الخادم. | لا | + + +ابدأ في وضع **التطوير** أثناء بناء تطبيقك. عندما يصبح جاهزًا، اختر **منشور** (npm) للتوزيع الواسع أو **داخلي** (tarball) للنشر الخاص. + diff --git a/packages/twenty-docs/l/ar/developers/extend/capabilities/apps.mdx b/packages/twenty-docs/l/ar/developers/extend/capabilities/apps.mdx index fd073685ee..409ab29c15 100644 --- a/packages/twenty-docs/l/ar/developers/extend/capabilities/apps.mdx +++ b/packages/twenty-docs/l/ar/developers/extend/capabilities/apps.mdx @@ -321,11 +321,11 @@ export default defineObject({ لكن هذا غير مستحسن. -### Defining fields on existing objects +### تعريف الحقول على الكائنات الموجودة -Use `defineField()` to add custom fields to existing objects — both standard objects (like `company`, `person`, `opportunity`) and custom objects defined by other apps. Each field lives in its own file and references the target object by its `universalIdentifier`. +استخدم `defineField()` لإضافة حقول مخصصة إلى الكائنات الموجودة — سواء الكائنات القياسية (مثل `company` و`person` و`opportunity`) أو الكائنات المخصصة التي تُعرِّفها تطبيقات أخرى. يوجد كل حقل في ملفه الخاص ويشير إلى الكائن الهدف بواسطة `universalIdentifier` الخاص به. -To reference standard objects, import `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` from `twenty-sdk`. This constant provides stable identifiers for all built-in objects and their fields: +للإشارة إلى الكائنات القياسية، استورد `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` من `twenty-sdk`. يوفر هذا الثابت معرِّفات مستقرة لجميع الكائنات المضمنة وحقولها: ```typescript // src/fields/apollo-total-funding.field.ts @@ -349,22 +349,22 @@ export default defineField({ النقاط الرئيسية: -* `objectUniversalIdentifier` tells Twenty which object to attach the field to. Use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS..universalIdentifier` for standard objects. -* Each field requires its own stable `universalIdentifier`, a `name`, `type`, `label`, and the target `objectUniversalIdentifier`. -* You can scaffold new fields using `yarn twenty entity:add` and choosing the field option. -* `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` is also exported as `STANDARD_OBJECT` for convenience — both refer to the same constant. +* `objectUniversalIdentifier` يُحدِّد لـ Twenty الكائن الذي سيُرفَق به الحقل. استخدم `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS..universalIdentifier` للكائنات القياسية. +* يتطلب كل حقل `universalIdentifier` ثابتًا خاصًا به، و`name`، و`type`، و`label`، و`objectUniversalIdentifier` الخاص بالكائن الهدف. +* يمكنك إنشاء حقول جديدة باستخدام `yarn twenty entity:add` واختيار خيار الحقل. +* يُصدَّر `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` أيضًا باسم `STANDARD_OBJECT` لسهولة الاستخدام — كلاهما يشير إلى الثابت نفسه. -Available standard objects include: `attachment`, `blocklist`, `calendarChannel`, `calendarEvent`, `calendarEventParticipant`, `company`, `connectedAccount`, `dashboard`, `favorite`, `favoriteFolder`, `message`, `messageChannel`, `messageParticipant`, `messageThread`, `note`, `noteTarget`, `opportunity`, `person`, `task`, `taskTarget`, `timelineActivity`, `workflow`, `workflowAutomatedTrigger`, `workflowRun`, `workflowVersion`, and `workspaceMember`. +تشمل الكائنات القياسية المتاحة: `attachment`، `blocklist`، `calendarChannel`، `calendarEvent`، `calendarEventParticipant`، `company`، `connectedAccount`، `dashboard`، `favorite`، `favoriteFolder`، `message`، `messageChannel`، `messageParticipant`، `messageThread`، `note`، `noteTarget`، `opportunity`، `person`، `task`، `taskTarget`، `timelineActivity`، `workflow`، `workflowAutomatedTrigger`، `workflowRun`، `workflowVersion`، و`workspaceMember`. -Each standard object also exposes its field identifiers. For example, to reference a specific field on a standard object in role permissions: +يُوفِّر كل كائن قياسي أيضًا معرّفات حقوله. على سبيل المثال، للإشارة إلى حقل محدد على كائن قياسي ضمن أذونات الأدوار: ```typescript STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.fields.name.universalIdentifier ``` -#### Relation fields on existing objects +#### حقول العلاقات على الكائنات الموجودة -You can also define relation fields that link existing objects to your custom objects: +يمكنك أيضًا تعريف حقول علاقات تربط الكائنات الموجودة بكائناتك المخصصة: ```typescript // src/fields/people-on-call-recording.field.ts diff --git a/packages/twenty-docs/l/ar/developers/extend/extend.mdx b/packages/twenty-docs/l/ar/developers/extend/extend.mdx index 8ad62dd5af..00d25108e1 100644 --- a/packages/twenty-docs/l/ar/developers/extend/extend.mdx +++ b/packages/twenty-docs/l/ar/developers/extend/extend.mdx @@ -1,7 +1,6 @@ --- title: التوسيع description: وسّع وظائف Twenty باستخدام واجهات برمجة التطبيقات، وخطافات الويب، والتطبيقات المخصصة. -redirect: /developers/introduction --- @@ -16,18 +15,18 @@ redirect: /developers/introduction * **واجهات برمجة التطبيقات**: استعلم وعدّل بيانات إدارة علاقات العملاء (CRM) لديك برمجياً باستخدام REST أو GraphQL * **خطافات الويب**: استقبل إشعارات في الوقت الفعلي عند وقوع أحداث في Twenty -* **التطبيقات**: أنشئ تطبيقات مخصصة توسّع قدرات Twenty - قريباً! +* **التطبيقات**: أنشئ تطبيقات مخصصة توسّع قدرات Twenty ## البدء - + اتصل بـ Twenty برمجياً - + احصل على إشعارات بالأحداث في الوقت الفعلي - - أنشئ تخصيصات كرمز برمجي (ألفا) + + أنشئ تخصيصات كرمز برمجي diff --git a/packages/twenty-docs/l/ar/developers/extend/webhooks.mdx b/packages/twenty-docs/l/ar/developers/extend/webhooks.mdx new file mode 100644 index 0000000000..a9d4c8e71e --- /dev/null +++ b/packages/twenty-docs/l/ar/developers/extend/webhooks.mdx @@ -0,0 +1,116 @@ +--- +title: خطافات الويب +description: استقبل إشعارات في الوقت الفعلي عند وقوع أحداث في نظام إدارة علاقات العملاء (CRM) الخاص بك. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +تدفع خطافات الويب البيانات إلى أنظمتك في الوقت الفعلي عند وقوع أحداث في Twenty — دون الحاجة إلى الاستطلاع الدوري. استخدمها للحفاظ على تزامن الأنظمة الخارجية، وتشغيل الأتمتة، أو إرسال التنبيهات. + +## إنشاء خطاف ويب + +1. انتقل إلى **الإعدادات → APIs & Webhooks → Webhooks** +2. انقر على **+ إنشاء خطاف ويب** +3. أدخل عنوان URL لخطاف الويب الخاص بك (يجب أن يكون قابلاً للوصول علنًا) +4. انقر على **حفظ** + +يتم تفعيل خطاف الويب فورًا ويبدأ في إرسال الإشعارات. + + + +### إدارة خطافات الويب + +**تحرير**: انقر على خطاف الويب → تحديث عنوان URL → **حفظ** + +**حذف**: انقر على خطاف الويب → **حذف** → تأكيد + +## الأحداث + +يرسل Twenty خطافات الويب لأنواع الأحداث التالية: + +| حدث | مثال | +| --------------- | ---------------------------------------------------------- | +| **إنشاء سجل** | `person.created`, `company.created`, `note.created` | +| **تحديث السجل** | `person.updated`, `company.updated`, `opportunity.updated` | +| **حذف السجل** | `person.deleted`, `company.deleted` | + +يتم إرسال جميع أنواع الأحداث إلى عنوان URL لخطاف الويب الخاص بك. قد تتم إضافة تصفية الأحداث في الإصدارات المستقبلية. + +## تنسيق الحمولة + +يرسل كل خطاف ويب طلب HTTP من نوع POST يتضمن جسمًا بصيغة JSON: + +```json +{ + "event": "person.created", + "data": { + "id": "abc12345", + "firstName": "Alice", + "lastName": "Doe", + "email": "alice@example.com", + "createdAt": "2025-02-10T15:30:45Z", + "createdBy": "user_123" + }, + "timestamp": "2025-02-10T15:30:50Z" +} +``` + +| الحقل | الوصف | +| ----------- | ----------------------------------------------- | +| `event` | ما الذي حدث (على سبيل المثال، `person.created`) | +| `data` | السجل الكامل الذي تم إنشاؤه/تحديثه/حذفه | +| `timestamp` | وقت حدوث الحدث (UTC) | + + +استجب بحالة **HTTP 2xx** ‏(200-299) لتأكيد الاستلام. تُسجَّل الاستجابات غير 2xx كإخفاقات في التسليم. + + +## التحقق من صحة خطاف الويب + +يقوم Twenty بتوقيع كل طلب خطاف ويب لأغراض الأمان. تحقّق من التواقيع للتأكد من أن الطلبات أصيلة. + +### الرؤوس + +| الترويسة | الوصف | +| ---------------------------- | ------------------- | +| `X-Twenty-Webhook-Signature` | توقيع HMAC SHA256 | +| `X-Twenty-Webhook-Timestamp` | الطابع الزمني للطلب | + +### خطوات التحقق + +1. احصل على الطابع الزمني من `X-Twenty-Webhook-Timestamp` +2. أنشئ السلسلة: `{timestamp}:{JSON payload}` +3. احسب HMAC SHA256 باستخدام سر خطاف الويب الخاص بك +4. قارِن مع `X-Twenty-Webhook-Signature` + +### مثال (Node.js) + +```javascript +const crypto = require("crypto"); + +const timestamp = req.headers["x-twenty-webhook-timestamp"]; +const payload = JSON.stringify(req.body); +const secret = "your-webhook-secret"; + +const stringToSign = `${timestamp}:${payload}`; +const expectedSignature = crypto + .createHmac("sha256", secret) + .update(stringToSign) + .digest("hex"); + +const receivedSignature = req.headers["x-twenty-webhook-signature"]; +const isValid = crypto.timingSafeEqual( + Buffer.from(expectedSignature, "hex"), + Buffer.from(receivedSignature, "hex") +); +``` + +## خطافات الويب مقابل سير العمل + +| طريقة | الاتجاه | حالة الاستخدام | +| ----------------------------- | ------- | ----------------------------------------------------------- | +| **خطافات الويب** | OUT | إخطار الأنظمة الخارجية تلقائيًا بأي تغيير في السجل | +| **سير العمل + طلب HTTP** | OUT | إرسال البيانات إلى الخارج بمنطق مخصص (عوامل تصفية، تحويلات) | +| **مشغّل خطاف ويب لسير العمل** | IN | استقبال البيانات في Twenty من الأنظمة الخارجية | + +لاستقبال البيانات الخارجية، راجع [إعداد مشغّل خطاف الويب](/l/ar/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger). diff --git a/packages/twenty-docs/l/ar/developers/introduction.mdx b/packages/twenty-docs/l/ar/developers/introduction.mdx index 786730a122..b3404d481e 100644 --- a/packages/twenty-docs/l/ar/developers/introduction.mdx +++ b/packages/twenty-docs/l/ar/developers/introduction.mdx @@ -5,28 +5,18 @@ description: مرحبًا بك في وثائق المطوّرين الخاصة import { CardTitle } from "/snippets/card-title.mdx" - - - API - استعلام وتعديل بيانات CRM الخاصة بك باستخدام REST أو GraphQL. + + + التوسيع + أنشئ عمليات تكامل مع واجهات برمجة التطبيقات وخطافات الويب والتطبيقات المخصصة. - - Webhooks - استقبل إشعارات في الوقت الفعلي عند حدوث الأحداث. - - - - Apps - أنشئ تطبيقات مخصصة توسّع قدرات Twenty. - - - + الاستضافة الذاتية قم بنشر Twenty وإدارته على البنية التحتية الخاصة بك. - + المساهمة انضم إلى مجتمعنا مفتوح المصدر وساهم في Twenty. diff --git a/packages/twenty-docs/l/ar/user-guide/data-migration/how-tos/export-your-data.mdx b/packages/twenty-docs/l/ar/user-guide/data-migration/how-tos/export-your-data.mdx index f239d5c375..bbf91f7406 100644 --- a/packages/twenty-docs/l/ar/user-guide/data-migration/how-tos/export-your-data.mdx +++ b/packages/twenty-docs/l/ar/user-guide/data-migration/how-tos/export-your-data.mdx @@ -24,7 +24,7 @@ import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; * يتم تصدير **الأعمدة المرئية** فقط * يتم تصدير **السجلات المصفّاة** فقط (استنادًا إلى العرض الحالي لديك) -بالنسبة لعمليات التصدير الأكبر (أكثر من 20,000 سجل)، استخدم عوامل التصفية للتصدير على دفعات أو استخدم [واجهة برمجة التطبيقات (API)](/l/ar/developers/api). +بالنسبة لعمليات التصدير الأكبر (أكثر من 20,000 سجل)، استخدم عوامل التصفية للتصدير على دفعات أو استخدم [واجهة برمجة التطبيقات (API)](/l/ar/developers/extend/api). ### الصلاحيات @@ -148,7 +148,7 @@ import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; 2. استخدم واجهة برمجة تطبيقات GraphQL للاستعلام عن السجلات 3. عالج النتائج في تطبيقك -راجع: [وثائق واجهة برمجة التطبيقات (API)](/l/ar/developers/api) +راجع: [وثائق واجهة برمجة التطبيقات (API)](/l/ar/developers/extend/api) ## نصائح وأفضل الممارسات @@ -206,4 +206,4 @@ import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; * [كيفية تحديث السجلات الموجودة](/l/ar/user-guide/data-migration/how-tos/update-existing-records-via-import) — حرّر وأعد استيراد ملف التصدير الخاص بك * [كيفية استيراد البيانات عبر واجهة برمجة التطبيقات (API)](/l/ar/user-guide/data-migration/how-tos/import-data-via-api) — لمجموعات البيانات الكبيرة -* [وثائق واجهة برمجة التطبيقات (API)](/l/ar/developers/api) — أنشئ عمليات سير عمل تصدير مخصصة +* [وثائق واجهة برمجة التطبيقات (API)](/l/ar/developers/extend/api) — أنشئ عمليات سير عمل تصدير مخصصة diff --git a/packages/twenty-docs/l/ar/user-guide/data-migration/how-tos/import-data-via-api.mdx b/packages/twenty-docs/l/ar/user-guide/data-migration/how-tos/import-data-via-api.mdx index 667dfd1a36..5ad98708ef 100644 --- a/packages/twenty-docs/l/ar/user-guide/data-migration/how-tos/import-data-via-api.mdx +++ b/packages/twenty-docs/l/ar/user-guide/data-migration/how-tos/import-data-via-api.mdx @@ -57,10 +57,10 @@ description: متى وكيف تستخدم واجهات API الخاصة بـ Twe تدعم Twenty نوعين من واجهات API: -| واجهة برمجة التطبيقات | الأفضل لـ | التوثيق | -| --------------------- | ------------------------------------------------------ | ------------------------------------------------- | -| **GraphQL** | استعلامات مرنة، وجلب البيانات المرتبطة، وعمليات معقّدة | [وثائق API](/l/ar/developers/api) | -| **REST** | عمليات CRUD بسيطة، وأنماط REST مألوفة | [وثائق API](/l/ar/developers/api) | +| واجهة برمجة التطبيقات | الأفضل لـ | التوثيق | +| --------------------- | ------------------------------------------------------ | ----------------------------------- | +| **GraphQL** | استعلامات مرنة، وجلب البيانات المرتبطة، وعمليات معقّدة | [وثائق API](/l/ar/developers/extend/api) | +| **REST** | عمليات CRUD بسيطة، وأنماط REST مألوفة | [وثائق API](/l/ar/developers/extend/api) | كلتا واجهتي API تدعمان: @@ -173,4 +173,4 @@ description: متى وكيف تستخدم واجهات API الخاصة بـ Twe للحصول على تفاصيل التنفيذ الكاملة وأمثلة الشيفرة ومرجع المخطط (schema): -* [وثائق API](/l/ar/developers/api) +* [وثائق API](/l/ar/developers/extend/api) diff --git a/packages/twenty-docs/l/ar/user-guide/getting-started/capabilities/what-is-twenty.mdx b/packages/twenty-docs/l/ar/user-guide/getting-started/capabilities/what-is-twenty.mdx index 92e2cbf201..d2e3a27e37 100644 --- a/packages/twenty-docs/l/ar/user-guide/getting-started/capabilities/what-is-twenty.mdx +++ b/packages/twenty-docs/l/ar/user-guide/getting-started/capabilities/what-is-twenty.mdx @@ -35,7 +35,7 @@ description: Twenty هو نظام إدارة علاقات العملاء (CRM) * **لوحات التحكم:** تتبع الأداء باستخدام تقارير مخصصة وتصوّرات مرئية. [عرض لوحات التحكم](/l/ar/user-guide/dashboards/overview). * **الأذونات والوصول:** تحكّم في مَن يمكنه عرض بياناتك وتحريرها وإدارتها باستخدام أذونات مستندة إلى الأدوار. [تكوين الوصول](/l/ar/user-guide/permissions-access/overview). * **الملاحظات والمهام:** أنشئ ملاحظات ومهام مرتبطة بسجلاتك لتحسين التعاون. -* **واجهة برمجة التطبيقات والويب هوكس:** الاتصال بالتطبيقات الأخرى وإنشاء عمليات تكامل مخصصة. [ابدأ التكامل](/l/ar/developers/api). +* **واجهة برمجة التطبيقات والويب هوكس:** الاتصال بالتطبيقات الأخرى وإنشاء عمليات تكامل مخصصة. [ابدأ التكامل](/l/ar/developers/extend/api). ## انضم الآن diff --git a/packages/twenty-docs/l/ar/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx b/packages/twenty-docs/l/ar/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx index 98078badd3..3a1282705b 100644 --- a/packages/twenty-docs/l/ar/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx +++ b/packages/twenty-docs/l/ar/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx @@ -95,7 +95,7 @@ description: اعرض بيانات من سجلات مرتبطة (مثل معلو * حجم الشركة: `{{searchRecords[0].employees}}` -**قيود المهام والملاحظات**: العلاقات في المهام والملاحظات مُحدّدة في الشفرة كعلاقات متعدّدة-لمتعدّدة وليست متاحة بعد في محفّزات أو إجراءات سير العمل. للوصول إلى هذه العلاقات، استخدم بدلًا من ذلك [API](/l/ar/developers/api). +**قيود المهام والملاحظات**: العلاقات في المهام والملاحظات مُحدّدة في الشفرة كعلاقات متعدّدة-لمتعدّدة وليست متاحة بعد في محفّزات أو إجراءات سير العمل. للوصول إلى هذه العلاقات، استخدم بدلًا من ذلك [API](/l/ar/developers/extend/api). ## مزامنة ثنائية الاتجاه diff --git a/packages/twenty-docs/l/cs/developers/contribute/capabilities/frontend-development/frontend-commands.mdx b/packages/twenty-docs/l/cs/developers/contribute/capabilities/frontend-development/frontend-commands.mdx index a585ffa655..81e659957d 100644 --- a/packages/twenty-docs/l/cs/developers/contribute/capabilities/frontend-development/frontend-commands.mdx +++ b/packages/twenty-docs/l/cs/developers/contribute/capabilities/frontend-development/frontend-commands.mdx @@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/cs/developers/contribute/capabilities/front ### Správa stavu -[Jotai](https://jotai.org/) zajišťuje správu stavu. +[Jotai](https://jotai.org/) handles state management. Podívejte se na [osvědčené postupy](/l/cs/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) pro více informací o správě stavu. diff --git a/packages/twenty-docs/l/de/developers/contribute/capabilities/frontend-development/frontend-commands.mdx b/packages/twenty-docs/l/de/developers/contribute/capabilities/frontend-development/frontend-commands.mdx index 08ff346423..a713b70424 100644 --- a/packages/twenty-docs/l/de/developers/contribute/capabilities/frontend-development/frontend-commands.mdx +++ b/packages/twenty-docs/l/de/developers/contribute/capabilities/frontend-development/frontend-commands.mdx @@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/de/developers/contribute/capabilities/front ### Zustandsverwaltung -[Jotai](https://jotai.org/) übernimmt die Zustandsverwaltung. +[Jotai](https://jotai.org/) handles state management. Siehe [Best Practices](/l/de/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) für mehr Informationen zur Zustandsverwaltung. diff --git a/packages/twenty-docs/l/de/developers/extend/api.mdx b/packages/twenty-docs/l/de/developers/extend/api.mdx new file mode 100644 index 0000000000..4b6aa0b8ec --- /dev/null +++ b/packages/twenty-docs/l/de/developers/extend/api.mdx @@ -0,0 +1,147 @@ +--- +title: APIs +description: Abfragen und ändern Sie Ihre CRM-Daten programmatisch mit REST oder GraphQL. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +Twenty wurde so entwickelt, dass es entwicklerfreundlich ist und leistungsstarke APIs bietet, die sich an Ihr individuelles Datenmodell anpassen. Wir bieten vier verschiedene API-Typen, um unterschiedlichen Integrationsanforderungen gerecht zu werden. + +## Developer-First-Ansatz + +Twenty generiert APIs speziell für Ihr Datenmodell: + +* **Keine langen IDs erforderlich**: Verwenden Sie Ihre Objekt- und Feldnamen direkt in Endpunkten +* **Standard- und benutzerdefinierte Objekte werden gleich behandelt**: Ihre benutzerdefinierten Objekte erhalten dieselbe API-Behandlung wie integrierte Objekte +* **Dedizierte Endpunkte**: Jedes Objekt und Feld erhält seinen eigenen API-Endpunkt +* **Benutzerdefinierte Dokumentation**: Speziell für das Datenmodell Ihres Arbeitsbereichs generiert + + +Ihre personalisierte API-Dokumentation ist nach dem Erstellen eines API-Schlüssels unter **Einstellungen → API & Webhooks** verfügbar. Da Twenty APIs erzeugt, die Ihrem benutzerdefinierten Datenmodell entsprechen, ist die Dokumentation für Ihren Arbeitsbereich einzigartig. + + +## Die beiden API-Typen + +### Core API + +Zugriff auf `/rest/` oder `/graphql/` + +Arbeiten Sie mit Ihren tatsächlichen **Datensätzen** (den Daten): + +* Personen, Unternehmen, Opportunities usw. erstellen, lesen, aktualisieren und löschen +* Daten abfragen und filtern +* Datensatzbeziehungen verwalten + +### Metadata API + +Zugriff auf `/rest/metadata/` oder `/metadata/` + +Verwalten Sie Ihren **Arbeitsbereich und Ihr Datenmodell**: + +* Objekte und Felder erstellen, ändern oder löschen +* Arbeitsbereichseinstellungen konfigurieren +* Beziehungen zwischen Objekten definieren + +## REST vs GraphQL + +Sowohl Core- als auch Metadata-APIs sind in REST- und GraphQL-Formaten verfügbar: + +| Format | Verfügbare Vorgänge | +| ----------- | ------------------------------------------------------------------- | +| **REST** | CRUD, Batch-Vorgänge, Upserts | +| **GraphQL** | Dasselbe plus **Batch-Upserts**, Beziehungsabfragen in einem Aufruf | + +Wählen Sie je nach Bedarf — beide Formate greifen auf dieselben Daten zu. + +## API-Endpunkte + +| Umgebung | Basis-URL | +| ----------------- | ------------------------- | +| **Cloud** | `https://api.twenty.com/` | +| **Selbsthosting** | `https://{your-domain}/` | + +## Authentifizierung + +Jede API-Anfrage erfordert einen API-Schlüssel im Header: + +``` +Authorization: Bearer YOUR_API_KEY +``` + +### API-Schlüssel erstellen + +1. Gehen Sie zu **Einstellungen → APIs & Webhooks** +2. Klicken Sie auf **+ Schlüssel erstellen** +3. Konfigurieren: + * **Name**: Beschreibender Name für den Schlüssel + * **Ablaufdatum**: Wann der Schlüssel abläuft +4. Klicken Sie auf **Speichern** +5. **Sofort kopieren** — der Schlüssel wird nur einmal angezeigt + + + + +Ihr API-Schlüssel gewährt Zugriff auf sensible Daten. Teilen Sie ihn nicht mit nicht vertrauenswürdigen Diensten. Wenn er kompromittiert wurde, deaktivieren Sie ihn umgehend und erstellen Sie einen neuen. + + +### Einem API-Schlüssel eine Rolle zuweisen + +Für mehr Sicherheit weisen Sie eine spezifische Rolle zu, um den Zugriff zu beschränken: + +1. Gehen Sie zu **Einstellungen → Rollen** +2. Klicken Sie auf die Rolle, die Sie zuweisen möchten +3. Öffnen Sie den Tab **Zuweisungen** +4. Unter **API-Schlüssel** auf **+ API-Schlüssel zuweisen** klicken +5. Wählen Sie den API-Schlüssel aus + +Der Schlüssel übernimmt die Berechtigungen dieser Rolle. Siehe [Berechtigungen](/l/de/user-guide/permissions-access/capabilities/permissions) für Details. + +### API-Schlüssel verwalten + +**Neu generieren**: Einstellungen → APIs & Webhooks → Schlüssel anklicken → **Neu generieren** + +**Löschen**: Einstellungen → APIs & Webhooks → Schlüssel anklicken → **Löschen** + +## API-Playground + +Testen Sie Ihre APIs direkt im Browser mit unserem integrierten Playground — verfügbar für **REST** und **GraphQL**. + +### Auf den Playground zugreifen + +1. Gehen Sie zu **Einstellungen → APIs & Webhooks** +2. API-Schlüssel erstellen (erforderlich) +3. Klicken Sie auf **REST API** oder **GraphQL API**, um den Playground zu öffnen + +### Was Sie erhalten + +* **Interaktive Dokumentation**: Für Ihr spezifisches Datenmodell generiert +* **Live-Tests**: Führen Sie echte API-Aufrufe gegen Ihren Arbeitsbereich aus +* **Schema-Explorer**: Verfügbare Objekte, Felder und Beziehungen durchsuchen +* **Request-Builder**: Abfragen mit Autovervollständigung erstellen + +Der Playground spiegelt Ihre benutzerdefinierten Objekte und Felder wider, sodass die Dokumentation für Ihren Arbeitsbereich stets korrekt ist. + +## Batch-Vorgänge + +Sowohl REST als auch GraphQL unterstützen Batch-Vorgänge: + +* **Batch-Größe**: Bis zu 60 Datensätze pro Anfrage +* **Vorgänge**: Mehrere Datensätze erstellen, aktualisieren, löschen + +**GraphQL-Exklusivfunktionen:** + +* **Batch-Upsert**: Erstellen oder Aktualisieren in einem Aufruf +* Verwenden Sie Pluralobjektnamen (z. B. `CreateCompanies` statt `CreateCompany`) + +## Rate Limits + +API-Anfragen werden gedrosselt, um die Stabilität der Plattform zu gewährleisten: + +| Limit | Wert | +| --------------- | ------------------------ | +| **Anfragen** | 100 Aufrufe pro Minute | +| **Batch-Größe** | 60 Datensätze pro Aufruf | + + +Verwenden Sie Batch-Vorgänge, um den Durchsatz zu maximieren — verarbeiten Sie bis zu 60 Datensätze in einem einzelnen API-Aufruf, statt einzelne Anfragen zu senden. + diff --git a/packages/twenty-docs/l/de/developers/extend/apps/building.mdx b/packages/twenty-docs/l/de/developers/extend/apps/building.mdx new file mode 100644 index 0000000000..9d83333538 --- /dev/null +++ b/packages/twenty-docs/l/de/developers/extend/apps/building.mdx @@ -0,0 +1,689 @@ +--- +title: Apps erstellen +description: Definieren Sie Objekte, Logikfunktionen, Frontend-Komponenten und mehr mit dem Twenty SDK. +--- + + +Apps befinden sich derzeit in der Alpha-Testphase. Die Funktion ist funktionsfähig, entwickelt sich jedoch noch weiter. + + +## SDK-Ressourcen verwenden (Typen & Konfiguration) + +Das twenty-sdk stellt typisierte Bausteine und Hilfsfunktionen bereit, die Sie in Ihrer App verwenden. Im Folgenden finden Sie die wichtigsten Bausteine, mit denen Sie am häufigsten arbeiten. + +### Hilfsfunktionen + +Das SDK stellt Hilfsfunktionen bereit, um die Entitäten Ihrer App zu definieren. Wie in [Entitätserkennung](/l/de/developers/extend/apps/getting-started#entity-detection) beschrieben, müssen Sie `export default define({...})` verwenden, damit Ihre Entitäten erkannt werden: + +| Funktion | Zweck | +| -------------------------------- | --------------------------------------------------------------- | +| `defineApplication` | Anwendungsmetadaten konfigurieren (erforderlich, eine pro App) | +| `defineObject` | Benutzerdefinierte Objekte mit Feldern definieren | +| `defineLogicFunction` | Logikfunktionen mit Handlern definieren | +| `definePreInstallLogicFunction` | Eine Pre-Installations-Logikfunktion definieren (eine pro App) | +| `definePostInstallLogicFunction` | Eine Post-Installations-Logikfunktion definieren (eine pro App) | +| `defineFrontComponent` | Frontend-Komponenten für benutzerdefinierte UI definieren | +| `defineRole` | Rollenberechtigungen und Objektzugriff konfigurieren | +| `defineField` | Bestehende Objekte mit zusätzlichen Feldern erweitern | +| `defineView` | Gespeicherte Views für Objekte definieren | +| `defineNavigationMenuItem` | Seitenleisten-Navigationslinks definieren | +| `defineSkill` | Skills für KI-Agenten definieren | + +Diese Funktionen validieren Ihre Konfiguration zur Build-Zeit und bieten IDE-Autovervollständigung sowie Typsicherheit. + +### Objekte definieren + +Benutzerdefinierte Objekte beschreiben sowohl Schema als auch Verhalten für Datensätze in Ihrem Workspace. Verwenden Sie `defineObject()`, um Objekte mit eingebauter Validierung zu definieren: + +```typescript +// src/app/postCard.object.ts +import { defineObject, FieldType } from 'twenty-sdk'; + +enum PostCardStatus { + DRAFT = 'DRAFT', + SENT = 'SENT', + DELIVERED = 'DELIVERED', + RETURNED = 'RETURNED', +} + +export default defineObject({ + universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05', + nameSingular: 'postCard', + namePlural: 'postCards', + labelSingular: 'Post Card', + labelPlural: 'Post Cards', + description: 'A post card object', + icon: 'IconMail', + fields: [ + { + universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b', + name: 'content', + type: FieldType.TEXT, + label: 'Content', + description: "Postcard's content", + icon: 'IconAbc', + }, + { + universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac', + name: 'recipientName', + type: FieldType.FULL_NAME, + label: 'Recipient name', + icon: 'IconUser', + }, + { + universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266', + name: 'recipientAddress', + type: FieldType.ADDRESS, + label: 'Recipient address', + icon: 'IconHome', + }, + { + universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e', + name: 'status', + type: FieldType.SELECT, + label: 'Status', + icon: 'IconSend', + defaultValue: `'${PostCardStatus.DRAFT}'`, + options: [ + { value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' }, + { value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' }, + { value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' }, + { value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' }, + ], + }, + { + universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433', + name: 'deliveredAt', + type: FieldType.DATE_TIME, + label: 'Delivered at', + icon: 'IconCheck', + isNullable: true, + defaultValue: null, + }, + ], +}); +``` + +Hauptpunkte: + +* Verwenden Sie `defineObject()` für eingebaute Validierung und bessere IDE-Unterstützung. +* Der `universalIdentifier` muss eindeutig und über Deployments hinweg stabil sein. +* Jedes Feld benötigt `name`, `type`, `label` und einen eigenen stabilen `universalIdentifier`. +* Das Array `fields` ist optional — Sie können Objekte ohne benutzerdefinierte Felder definieren. +* Sie können mit `yarn twenty entity:add` neue Objekte erzeugen; der Assistent führt Sie durch Benennung, Felder und Beziehungen. + + +**Basisfelder werden automatisch erstellt.** Wenn Sie ein benutzerdefiniertes Objekt definieren, fügt Twenty automatisch Standardfelder hinzu +wie `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` und `deletedAt`. +Sie müssen diese nicht in Ihrem `fields`-Array definieren — fügen Sie nur Ihre benutzerdefinierten Felder hinzu. +Sie können Standardfelder überschreiben, indem Sie in Ihrem `fields`-Array ein Feld mit demselben Namen definieren, +dies wird jedoch nicht empfohlen. + + +### Anwendungskonfiguration (application-config.ts) + +Jede App hat eine einzelne Datei `application-config.ts`, die Folgendes beschreibt: + +* **Was die App ist**: Bezeichner, Anzeigename und Beschreibung. +* **Wie ihre Funktionen ausgeführt werden**: welche Rolle sie für Berechtigungen verwenden. +* **(Optional) Variablen**: Schlüssel–Wert-Paare, die Ihren Funktionen als Umgebungsvariablen zur Verfügung gestellt werden. +* **(Optional) Pre-Installationsfunktion**: eine Logikfunktion, die vor der Installation der App ausgeführt wird. +* **(Optional) Post-Installationsfunktion**: eine Logikfunktion, die nach der Installation der App ausgeführt wird. + +Verwenden Sie `defineApplication()`, um Ihre Anwendungskonfiguration zu definieren: + +```typescript +// src/application-config.ts +import { defineApplication } from 'twenty-sdk'; +import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role'; + +export default defineApplication({ + universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7', + displayName: 'My Twenty App', + description: 'My first Twenty app', + icon: 'IconWorld', + applicationVariables: { + DEFAULT_RECIPIENT_NAME: { + universalIdentifier: '19e94e59-d4fe-4251-8981-b96d0a9f74de', + description: 'Default recipient name for postcards', + value: 'Jane Doe', + isSecret: false, + }, + }, + defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, +}); +``` + +Notizen: + +* `universalIdentifier`-Felder sind deterministische IDs, die Sie besitzen; generieren Sie sie einmal und halten Sie sie über Synchronisierungen hinweg stabil. +* `applicationVariables` werden zu Umgebungsvariablen für Ihre Funktionen (zum Beispiel ist `DEFAULT_RECIPIENT_NAME` als `process.env.DEFAULT_RECIPIENT_NAME` verfügbar). +* `defaultRoleUniversalIdentifier` muss mit der Rollendatei übereinstimmen (siehe unten). +* Pre-Installations- und Post-Installationsfunktionen werden während des Manifest-Builds automatisch erkannt. Siehe [Pre-Installationsfunktionen](#pre-install-functions) und [Post-Installationsfunktionen](#post-install-functions). + +#### Rollen und Berechtigungen + +Anwendungen können Rollen definieren, die Berechtigungen für die Objekte und Aktionen Ihres Workspaces kapseln. Das Feld `defaultRoleUniversalIdentifier` in `application-config.ts` legt die Standardrolle fest, die von den Logikfunktionen Ihrer App verwendet wird. + +* Der zur Laufzeit als `TWENTY_API_KEY` injizierte API-Schlüssel wird von dieser Standard-Funktionsrolle abgeleitet. +* Der typisierte Client ist auf die dieser Rolle gewährten Berechtigungen beschränkt. +* Befolgen Sie das Least-Privilege-Prinzip: Erstellen Sie eine dedizierte Rolle nur mit den Berechtigungen, die Ihre Funktionen benötigen, und verweisen Sie dann auf deren universellen Bezeichner. + +##### Standard-Funktionsrolle (*.role.ts) + +Wenn Sie eine neue App erzeugen, erstellt die CLI auch eine Standard-Rolldatei. Verwenden Sie `defineRole()`, um Rollen mit eingebauter Validierung zu definieren: + +```typescript +// src/roles/default-role.ts +import { defineRole, PermissionFlag } from 'twenty-sdk'; + +export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = + 'b648f87b-1d26-4961-b974-0908fd991061'; + +export default defineRole({ + universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, + label: 'Default function role', + description: 'Default role for function Twenty client', + canReadAllObjectRecords: false, + canUpdateAllObjectRecords: false, + canSoftDeleteAllObjectRecords: false, + canDestroyAllObjectRecords: false, + canUpdateAllSettings: false, + canBeAssignedToAgents: false, + canBeAssignedToUsers: false, + canBeAssignedToApiKeys: false, + objectPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + canReadObjectRecords: true, + canUpdateObjectRecords: true, + canSoftDeleteObjectRecords: false, + canDestroyObjectRecords: false, + }, + ], + fieldPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + fieldUniversalIdentifier: 'b2c37dc0-8ae7-470e-96cd-1476b47dfaff', + canReadFieldValue: false, + canUpdateFieldValue: false, + }, + ], + permissionFlags: [PermissionFlag.APPLICATIONS], +}); +``` + +Der `universalIdentifier` dieser Rolle wird anschließend in `application-config.ts` als `defaultRoleUniversalIdentifier` referenziert. Anders ausgedrückt: + +* **\*.role.ts** definiert, was die Standard-Funktionsrolle darf. +* **application-config.ts** verweist auf diese Rolle, sodass Ihre Funktionen deren Berechtigungen erben. + +Notizen: + +* Beginnen Sie mit der vorab erstellten Rolle und schränken Sie sie schrittweise gemäß dem Least-Privilege-Prinzip ein. +* Ersetzen Sie `objectPermissions` und `fieldPermissions` durch die Objekte/Felder, die Ihre Funktionen benötigen. +* `permissionFlags` steuern den Zugriff auf Funktionen auf Plattformebene. Halten Sie sie minimal; fügen Sie nur hinzu, was Sie benötigen. +* Ein funktionierendes Beispiel finden Sie in der Hello-World-App: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). + +### Konfiguration von Logikfunktionen und Einstiegspunkt + +Jede Funktionsdatei verwendet `defineLogicFunction()`, um eine Konfiguration mit einem Handler und optionalen Triggern zu exportieren. + +```typescript +// src/app/createPostCard.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk'; +import { CoreApiClient, type Person } from 'twenty-sdk/generated'; + +const handler = async (params: RoutePayload) => { + const client = new CoreApiClient(); + const name = 'name' in params.queryStringParameters + ? params.queryStringParameters.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world' + : 'Hello world'; + + const result = await client.mutation({ + createPostCard: { + __args: { data: { name } }, + id: true, + name: true, + }, + }); + return result; +}; + +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'create-new-post-card', + timeoutSeconds: 2, + handler, + triggers: [ + // Public HTTP route trigger '/s/post-card/create' + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/post-card/create', + httpMethod: 'GET', + isAuthRequired: false, + }, + // Cron trigger (CRON pattern) + // { + // universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2', + // type: 'cron', + // pattern: '0 0 1 1 *', + // }, + // Database event trigger + // { + // universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156', + // type: 'databaseEvent', + // eventName: 'person.updated', + // updatedFields: ['name'], + // }, + ], +}); +``` + +Häufige Trigger-Typen: + +* **route**: Stellt Ihre Funktion unter einem HTTP-Pfad und einer Methode **unter dem Endpunkt `/s/`** bereit: + +> z. B. `path: '/post-card/create',` -> Aufruf unter `/s/post-card/create` + +* **cron**: Führt Ihre Funktion nach Zeitplan mithilfe eines CRON-Ausdrucks aus. +* **databaseEvent**: Wird bei Lebenszyklusereignissen von Workspace-Objekten ausgeführt. Wenn die Ereignisoperation `updated` ist, können bestimmte zu überwachende Felder im Array `updatedFields` angegeben werden. Wenn das Array undefiniert oder leer ist, löst jede Aktualisierung die Funktion aus. + +> z. B. `person.updated` + +Notizen: + +* Das Array `triggers` ist optional. Funktionen ohne Trigger können als von anderen Funktionen aufgerufene Utility-Funktionen verwendet werden. +* Sie können mehrere Trigger-Typen in einer Funktion kombinieren. + +### Pre-Installationsfunktionen + +Eine Pre-Installationsfunktion ist eine Logikfunktion, die automatisch ausgeführt wird, bevor Ihre App in einem Arbeitsbereich installiert wird. Dies ist nützlich für Validierungsaufgaben, Überprüfungen von Voraussetzungen oder die Vorbereitung des Status des Arbeitsbereichs, bevor die Hauptinstallation fortgesetzt wird. + +Wenn Sie mit `create-twenty-app` eine neue App erstellen, wird für Sie eine Pre-Installationsfunktion unter `src/logic-functions/pre-install.ts` erzeugt: + +```typescript +// src/logic-functions/pre-install.ts +import { definePreInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Pre install logic function executed successfully!', payload.previousVersion); +}; + +export default definePreInstallLogicFunction({ + universalIdentifier: '', + name: 'pre-install', + description: 'Runs before installation to prepare the application.', + timeoutSeconds: 300, + handler, +}); +``` + +Sie können die Pre-Installationsfunktion auch jederzeit manuell über die CLI ausführen: + +```bash filename="Terminal" +yarn twenty function:execute --preInstall +``` + +Hauptpunkte: + +* Pre-Installationsfunktionen verwenden `definePreInstallLogicFunction()` — eine spezialisierte Variante, die Trigger-Einstellungen (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`) weglässt. +* Der Handler erhält ein `InstallLogicFunctionPayload` mit `{ previousVersion: string }` — die Version der App, die zuvor installiert war (oder eine leere Zeichenkette bei Neuinstallationen). +* Pro Anwendung ist nur eine Pre-Installationsfunktion zulässig. Der Manifest-Build schlägt fehl, wenn mehr als eine erkannt wird. +* Der `universalIdentifier` der Funktion wird während des Builds im Anwendungsmanifest automatisch als `preInstallLogicFunctionUniversalIdentifier` gesetzt — Sie müssen ihn nicht in `defineApplication()` referenzieren. +* Das standardmäßige Timeout ist auf 300 Sekunden (5 Minuten) festgelegt, um längere Vorbereitungsvorgänge zu ermöglichen. +* Pre-Installationsfunktionen benötigen keine Trigger — sie werden von der Plattform vor der Installation oder manuell über `function:execute --preInstall` aufgerufen. + +### Post-Installationsfunktionen + +Eine Post-Installationsfunktion ist eine Logikfunktion, die automatisch ausgeführt wird, nachdem Ihre App in einem Arbeitsbereich installiert wurde. Dies ist nützlich für einmalige Einrichtungsvorgänge wie das Befüllen mit Standarddaten, das Erstellen erster Datensätze oder das Konfigurieren von Arbeitsbereichseinstellungen. + +Wenn Sie mit `create-twenty-app` eine neue App erstellen, wird für Sie eine Post-Installationsfunktion unter `src/logic-functions/post-install.ts` erzeugt: + +```typescript +// src/logic-functions/post-install.ts +import { definePostInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Post install logic function executed successfully!', payload.previousVersion); +}; + +export default definePostInstallLogicFunction({ + universalIdentifier: '', + name: 'post-install', + description: 'Runs after installation to set up the application.', + timeoutSeconds: 300, + handler, +}); +``` + +Sie können die Post-Installationsfunktion auch jederzeit manuell über die CLI ausführen: + +```bash filename="Terminal" +yarn twenty function:execute --postInstall +``` + +Hauptpunkte: + +* Post-Installationsfunktionen verwenden `definePostInstallLogicFunction()` — eine spezialisierte Variante, die Trigger-Einstellungen (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`) weglässt. +* Der Handler erhält ein `InstallLogicFunctionPayload` mit `{ previousVersion: string }` — die Version der App, die zuvor installiert war (oder eine leere Zeichenkette bei Neuinstallationen). +* Pro Anwendung ist nur eine Post-Installationsfunktion zulässig. Der Manifest-Build schlägt fehl, wenn mehr als eine erkannt wird. +* Der `universalIdentifier` der Funktion wird während des Builds im Anwendungsmanifest automatisch als `postInstallLogicFunctionUniversalIdentifier` gesetzt — Sie müssen ihn nicht in `defineApplication()` referenzieren. +* Das standardmäßige Timeout ist auf 300 Sekunden (5 Minuten) festgelegt, um längere Einrichtungsvorgänge wie Daten-Seeding zu ermöglichen. +* Post-Installationsfunktionen benötigen keine Trigger — sie werden von der Plattform während der Installation oder manuell über `function:execute --postInstall` aufgerufen. + +### Routen-Trigger-Payload + + +**Breaking Change (v1.16, Januar 2026):** Das Format der Routen-Trigger-Payload hat sich geändert. Vor v1.16 wurden Query-Parameter, Pfadparameter und der Body direkt als Payload gesendet. Ab v1.16 sind sie innerhalb eines strukturierten `RoutePayload`-Objekts verschachtelt. + +**Vor v1.16:** +```typescript +const handler = async (params) => { + const { param1, param2 } = params; // Direct access +}; +``` + +**Nach v1.16:** +```typescript +const handler = async (event: RoutePayload) => { + const { param1, param2 } = event.body; // Access via .body + const { queryParam } = event.queryStringParameters; + const { id } = event.pathParameters; +}; +``` + +**So migrieren Sie bestehende Funktionen:** Aktualisieren Sie Ihren Handler, sodass er nicht mehr direkt aus dem params-Objekt destrukturiert, sondern aus `event.body`, `event.queryStringParameters` oder `event.pathParameters`. + + +Wenn ein Routen-Trigger Ihre Logikfunktion aufruft, erhält sie ein `RoutePayload`-Objekt, das dem AWS HTTP API v2-Format entspricht. Importieren Sie den Typ aus `twenty-sdk`: + +```typescript +import { defineLogicFunction, type RoutePayload } from 'twenty-sdk'; + +const handler = async (event: RoutePayload) => { + // Access request data + const { headers, queryStringParameters, pathParameters, body } = event; + + // HTTP method and path are available in requestContext + const { method, path } = event.requestContext.http; + + return { message: 'Success' }; +}; +``` + +Der Typ `RoutePayload` hat die folgende Struktur: + +| Eigenschaft | Typ | Beschreibung | +| ---------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------- | +| `headers` | `Record` | HTTP-Header (nur die in `forwardedRequestHeaders` aufgelisteten) | +| `queryStringParameters` | `Record` | Query-String-Parameter (mehrere Werte mit Kommas verbunden) | +| `pathParameters` | `Record` | Aus dem Routenmuster extrahierte Pfadparameter (z. B. `/users/:id` → `{ id: '123' }`) | +| `body` | `object \| null` | Geparster Request-Body (JSON) | +| `isBase64Encoded` | `boolean` | Gibt an, ob der Body Base64-codiert ist | +| `requestContext.http.method` | `string` | HTTP-Methode (GET, POST, PUT, PATCH, DELETE) | +| `requestContext.http.path` | `string` | Rohpfad der Anfrage | + +### Weiterleiten von HTTP-Headern + +Standardmäßig werden HTTP-Header von eingehenden Anfragen aus Sicherheitsgründen nicht an Ihre Logikfunktion weitergegeben. Um auf bestimmte Header zuzugreifen, listen Sie diese explizit im Array `forwardedRequestHeaders` auf: + +```typescript +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'webhook-handler', + handler, + triggers: [ + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/webhook', + httpMethod: 'POST', + isAuthRequired: false, + forwardedRequestHeaders: ['x-webhook-signature', 'content-type'], + }, + ], +}); +``` + +In Ihrem Handler können Sie anschließend auf diese Header zugreifen: + +```typescript +const handler = async (event: RoutePayload) => { + const signature = event.headers['x-webhook-signature']; + const contentType = event.headers['content-type']; + + // Validate webhook signature... + return { received: true }; +}; +``` + + + Header-Namen werden in Kleinbuchstaben normalisiert. Greifen Sie mit Schlüsseln in Kleinbuchstaben darauf zu (zum Beispiel `event.headers['content-type']`). + + +Sie können neue Funktionen auf zwei Arten erstellen: + +* **Generiert**: Führen Sie `yarn twenty entity:add` aus und wählen Sie die Option zum Hinzufügen einer neuen Logikfunktion. Dadurch wird eine Starterdatei mit Handler und Konfiguration erzeugt. +* **Manuell**: Erstellen Sie eine neue `*.logic-function.ts`-Datei und verwenden Sie `defineLogicFunction()` nach demselben Muster. + +### Eine Logikfunktion als Tool markieren + +Logikfunktionen können als **Tools** für KI-Agenten und Workflows verfügbar gemacht werden. Wenn eine Funktion als Tool markiert ist, wird sie von den KI-Funktionen von Twenty auffindbar und kann als Schritt in Workflow-Automatisierungen ausgewählt werden. + +Um eine Logikfunktion als Tool zu markieren, setzen Sie `isTool: true` und geben Sie ein `toolInputSchema` an, das die erwarteten Eingabeparameter mithilfe von [JSON Schema](https://json-schema.org/) beschreibt: + +```typescript +// src/logic-functions/enrich-company.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import { CoreApiClient } from 'twenty-sdk/generated'; + +const handler = async (params: { companyName: string; domain?: string }) => { + const client = new CoreApiClient(); + + const result = await client.mutation({ + createTask: { + __args: { + data: { + title: `Enrich data for ${params.companyName}`, + body: `Domain: ${params.domain ?? 'unknown'}`, + }, + }, + id: true, + }, + }); + + return { taskId: result.createTask.id }; +}; + +export default defineLogicFunction({ + universalIdentifier: 'f47ac10b-58cc-4372-a567-0e02b2c3d479', + name: 'enrich-company', + description: 'Enrich a company record with external data', + timeoutSeconds: 10, + handler, + isTool: true, + toolInputSchema: { + type: 'object', + properties: { + companyName: { + type: 'string', + description: 'The name of the company to enrich', + }, + domain: { + type: 'string', + description: 'The company website domain (optional)', + }, + }, + required: ['companyName'], + }, +}); +``` + +Hauptpunkte: + +* **`isTool`** (`boolean`, Standard: `false`): Wenn auf `true` gesetzt, wird die Funktion als Tool registriert und steht KI-Agenten und Workflow-Automatisierungen zur Verfügung. +* **`toolInputSchema`** (`object`, optional): Ein JSON-Schema-Objekt, das die Parameter beschreibt, die Ihre Funktion akzeptiert. KI-Agenten verwenden dieses Schema, um zu verstehen, welche Eingaben das Tool erwartet, und um Aufrufe zu validieren. Falls weggelassen, lautet der Standardwert für das Schema `{ type: 'object', properties: {} }` (keine Parameter). +* Funktionen mit `isTool: false` (oder nicht gesetzt) werden **nicht** als Tools bereitgestellt. Sie können weiterhin direkt ausgeführt oder von anderen Funktionen aufgerufen werden, erscheinen jedoch nicht in der Tool-Erkennung. +* **Tool-Benennung**: Wenn als Tool bereitgestellt, wird der Funktionsname automatisch zu `logic_function_` normalisiert (in Kleinbuchstaben umgewandelt, nicht alphanumerische Zeichen durch Unterstriche ersetzt). Beispielsweise wird `enrich-company` zu `logic_function_enrich_company`. +* Sie können `isTool` mit Triggern kombinieren — eine Funktion kann gleichzeitig sowohl ein Tool (von KI-Agenten aufrufbar) als auch durch Ereignisse (Cron, Datenbankereignisse, Routen) ausgelöst werden. + + +**Schreiben Sie eine gute `description`.** KI-Agenten verlassen sich auf das `description`-Feld der Funktion, um zu entscheiden, wann das Tool verwendet werden soll. Seien Sie konkret darin, was das Tool tut und wann es aufgerufen werden soll. + + +### Frontend-Komponenten + +Frontend-Komponenten ermöglichen es Ihnen, benutzerdefinierte React-Komponenten zu erstellen, die innerhalb der Twenty-UI gerendert werden. Verwenden Sie `defineFrontComponent()`, um Komponenten mit eingebauter Validierung zu definieren: + +```typescript +// src/front-components/my-widget.tsx +import { defineFrontComponent } from 'twenty-sdk'; + +const MyWidget = () => { + return ( +
+

My Custom Widget

+

This is a custom front component for Twenty.

+
+ ); +}; + +export default defineFrontComponent({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'my-widget', + description: 'A custom widget component', + component: MyWidget, +}); +``` + +Hauptpunkte: + +* Frontend-Komponenten sind React-Komponenten, die in isolierten Kontexten innerhalb von Twenty gerendert werden. +* Das Feld `component` verweist auf Ihre React-Komponente. +* Komponenten werden während `yarn twenty app:dev` automatisch gebaut und synchronisiert. + +Sie können neue Frontend-Komponenten auf zwei Arten erstellen: + +* **Generiert**: Führen Sie `yarn twenty entity:add` aus und wählen Sie die Option zum Hinzufügen einer neuen Frontend-Komponente. +* **Manuell**: Erstellen Sie eine neue `.tsx`-Datei und verwenden Sie `defineFrontComponent()` nach demselben Muster. + +### Fähigkeiten + +Skills definieren wiederverwendbare Anweisungen und Fähigkeiten, die KI-Agenten in Ihrem Arbeitsbereich verwenden können. Verwenden Sie `defineSkill()`, um Skills mit eingebauter Validierung zu definieren: + +```typescript +// src/skills/example-skill.ts +import { defineSkill } from 'twenty-sdk'; + +export default defineSkill({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'sales-outreach', + label: 'Sales Outreach', + description: 'Guides the AI agent through a structured sales outreach process', + icon: 'IconBrain', + content: `You are a sales outreach assistant. When reaching out to a prospect: +1. Research the company and recent news +2. Identify the prospect's role and likely pain points +3. Draft a personalized message referencing specific details +4. Keep the tone professional but conversational`, +}); +``` + +Hauptpunkte: + +* `name` ist eine eindeutige Kennung (als Zeichenfolge) für den Skill (kebab-case empfohlen). +* `label` ist der menschenlesbare Anzeigename, der in der UI angezeigt wird. +* `content` enthält die Skill-Anweisungen — dies ist der Text, den der KI-Agent verwendet. +* `icon` (optional) legt das in der UI angezeigte Symbol fest. +* `description` (optional) liefert zusätzlichen Kontext zum Zweck des Skills. + +Sie können neue Skills auf zwei Arten erstellen: + +* **Generiert**: Führen Sie `yarn twenty entity:add` aus und wählen Sie die Option zum Hinzufügen eines neuen Skills. +* **Manuell**: Erstellen Sie eine neue Datei und verwenden Sie `defineSkill()` nach demselben Muster. + +### Generierte typisierte Clients + +Zwei typisierte Clients werden von `yarn twenty app:dev` automatisch generiert und basierend auf Ihrem Arbeitsbereichs-Schema in `node_modules/twenty-sdk/generated` gespeichert: + +* **`CoreApiClient`** — fragt den `/graphql`-Endpunkt nach Arbeitsbereichsdaten ab +* **`MetadataApiClient`** — ruft über den Endpunkt `/metadata` die Arbeitsbereichskonfiguration und Datei-Uploads ab. + +```typescript +import { CoreApiClient, MetadataApiClient } from 'twenty-sdk/generated'; + +const client = new CoreApiClient(); +const { me } = await client.query({ me: { id: true, displayName: true } }); + +const metadataClient = new MetadataApiClient(); +const { currentWorkspace } = await metadataClient.query({ currentWorkspace: { id: true } }); +``` + +Beide Clients werden von `yarn twenty app:dev` automatisch neu generiert, sobald sich Ihre Objekte oder Felder ändern. + +#### Laufzeit-Anmeldedaten in Logikfunktionen + +Wenn Ihre Funktion auf Twenty läuft, injiziert die Plattform vor der Ausführung Ihres Codes Anmeldedaten als Umgebungsvariablen: + +* `TWENTY_API_URL`: Basis-URL der Twenty-API, auf die Ihre App abzielt. +* `TWENTY_API_KEY`: Kurzlebiger Schlüssel, der auf die Standard-Funktionsrolle Ihrer Anwendung begrenzt ist. + +Notizen: + +* Sie müssen dem generierten Client weder URL noch API-Schlüssel übergeben. Er liest `TWENTY_API_URL` und `TWENTY_API_KEY` zur Laufzeit aus process.env. +* Die Berechtigungen des API-Schlüssels werden durch die Rolle bestimmt, auf die in Ihrer `application-config.ts` über `defaultRoleUniversalIdentifier` verwiesen wird. Dies ist die Standardrolle, die von den Logikfunktionen Ihrer Anwendung verwendet wird. +* Anwendungen können Rollen definieren, um das Least-Privilege-Prinzip einzuhalten. Gewähren Sie nur die Berechtigungen, die Ihre Funktionen benötigen, und verweisen Sie dann mit `defaultRoleUniversalIdentifier` auf den universellen Bezeichner dieser Rolle. + +#### Dateien hochladen + +Der generierte `MetadataApiClient` enthält eine Methode `uploadFile`, um Dateien an Felder des Typs Datei in Ihren Arbeitsbereichsobjekten anzuhängen. Da Standard-GraphQL-Clients Multipart-Datei-Uploads nicht nativ unterstützen, stellt der Client diese dedizierte Methode bereit, die unter der Haube die [GraphQL-Multipart-Anfragespezifikation](https://github.com/jaydenseric/graphql-multipart-request-spec) implementiert. + +```typescript +import { MetadataApiClient } from 'twenty-sdk/generated'; +import * as fs from 'fs'; + +const metadataClient = new MetadataApiClient(); + +const fileBuffer = fs.readFileSync('./invoice.pdf'); + +const uploadedFile = await metadataClient.uploadFile( + fileBuffer, // file contents as a Buffer + 'invoice.pdf', // filename + 'application/pdf', // MIME type (defaults to 'application/octet-stream') + '58a0a314-d7ea-4865-9850-7fb84e72f30b', // field universal identifier +); + +console.log(uploadedFile); +// { id: '...', path: '...', size: 12345, createdAt: '...', url: 'https://...' } +``` + +Die Methodensignatur: + +```typescript +uploadFile( + fileBuffer: Buffer, + filename: string, + contentType: string, + fieldMetadataUniversalIdentifier: string, +): Promise<{ id: string; path: string; size: number; createdAt: string; url: string }> +``` + +| Parameter | Typ | Beschreibung | +| ---------------------------------- | -------- | ------------------------------------------------------------------------------- | +| `fileBuffer` | `Buffer` | Der Rohinhalt der Datei | +| `filename` | `string` | Der Name der Datei (wird für Speicherung und Anzeige verwendet) | +| `contentType` | `string` | MIME-Typ der Datei (standardmäßig `application/octet-stream`, wenn weggelassen) | +| `fieldMetadataUniversalIdentifier` | `string` | Der `universalIdentifier` des Dateityp-Felds in Ihrem Objekt | + +Hauptpunkte: + +* Die Methode `uploadFile` ist auf dem `MetadataApiClient` verfügbar, weil die Upload-Mutation vom Endpunkt `/metadata` aufgelöst wird. +* Sie verwendet den `universalIdentifier` des Feldes (nicht dessen arbeitsbereichsspezifische ID), sodass Ihr Upload-Code in jedem Arbeitsbereich funktioniert, in dem Ihre App installiert ist — im Einklang damit, wie Apps Felder überall sonst referenzieren. +* Die zurückgegebene `url` ist eine signierte URL, mit der Sie auf die hochgeladene Datei zugreifen können. + +### Hello-World-Beispiel + +Ein minimales End-to-End-Beispiel, das Objekte, Logikfunktionen, Frontend-Komponenten und mehrere Trigger demonstriert, finden Sie [hier](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/hello-world). diff --git a/packages/twenty-docs/l/de/developers/extend/apps/getting-started.mdx b/packages/twenty-docs/l/de/developers/extend/apps/getting-started.mdx new file mode 100644 index 0000000000..9fa92f19f7 --- /dev/null +++ b/packages/twenty-docs/l/de/developers/extend/apps/getting-started.mdx @@ -0,0 +1,233 @@ +--- +title: Erste Schritte +description: Create your first Twenty app in minutes. +--- + + +Apps befinden sich derzeit in der Alpha-Testphase. Die Funktion ist funktionsfähig, entwickelt sich jedoch noch weiter. + + +Apps let you extend Twenty with custom objects, fields, logic functions, AI skills, and UI components — all managed as code. + +**Was Sie heute tun können:** + +* Benutzerdefinierte Objekte und Felder als Code definieren (verwaltetes Datenmodell) +* Build logic functions with custom triggers (HTTP routes, cron, database events) +* Fähigkeiten für KI-Agenten definieren +* Build front components that render inside Twenty's UI +* Dieselbe App in mehreren Workspaces bereitstellen + +## Voraussetzungen + +* Node.js 24+ und Yarn 4 +* Ein Twenty-Workspace und ein API-Schlüssel (unter https://app.twenty.com/settings/api-webhooks erstellen) + +## Erste Schritte + +Erstellen Sie mit dem offiziellen Scaffolder eine neue App, authentifizieren Sie sich und beginnen Sie mit der Entwicklung: + +```bash filename="Terminal" +# Scaffold a new app (includes all examples by default) +npx create-twenty-app@latest my-twenty-app +cd my-twenty-app + +# Start dev mode: automatically syncs local changes to your workspace +yarn twenty app:dev +``` + +Das Scaffolding-Tool unterstützt zwei Modi, um zu steuern, welche Beispieldateien enthalten sind: + +```bash filename="Terminal" +# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item, skill) +npx create-twenty-app@latest my-app + +# Minimal: only core files (application-config.ts and default-role.ts) +npx create-twenty-app@latest my-app --minimal +``` + +Von hier aus können Sie: + +```bash filename="Terminal" +# Add a new entity to your application (guided) +yarn twenty entity:add + +# Watch your application's function logs +yarn twenty function:logs + +# Execute a function by name +yarn twenty function:execute -n my-function -p '{"name": "test"}' + +# Execute the pre-install function +yarn twenty function:execute --preInstall + +# Execute the post-install function +yarn twenty function:execute --postInstall + +# Uninstall the application from the current workspace +yarn twenty app:uninstall + +# Display commands' help +yarn twenty help +``` + +Siehe auch: die CLI-Referenzseiten für [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) und [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk). + +## Projektstruktur (vom Scaffolder erzeugt) + +Wenn Sie `npx create-twenty-app@latest my-twenty-app` ausführen, erledigt der Scaffolder Folgendes: + +* Kopiert eine minimale Basisanwendung nach `my-twenty-app/` +* Fügt eine lokale `twenty-sdk`-Abhängigkeit und die Yarn-4-Konfiguration hinzu +* Erstellt Konfigurationsdateien und Skripte, die an die `twenty`-CLI angebunden sind +* Erzeugt Kerndateien (Anwendungskonfiguration, Standardrolle für Logikfunktionen, Pre-Installations- und Post-Installationsfunktionen) sowie Beispieldateien entsprechend dem Scaffolding-Modus + +Eine frisch erstellte App mit dem Standardmodus `--exhaustive` sieht so aus: + +```text filename="my-twenty-app/" +my-twenty-app/ + package.json + yarn.lock + .gitignore + .nvmrc + .yarnrc.yml + .yarn/ + install-state.gz + .oxlintrc.json + tsconfig.json + README.md + public/ # Public assets folder (images, fonts, etc.) + src/ + ├── application-config.ts # Required - main application configuration + ├── roles/ + │ └── default-role.ts # Default role for logic functions + ├── objects/ + │ └── example-object.ts # Example custom object definition + ├── fields/ + │ └── example-field.ts # Example standalone field definition + ├── logic-functions/ + │ ├── hello-world.ts # Example logic function + │ ├── pre-install.ts # Pre-install logic function + │ └── post-install.ts # Post-install logic function + ├── front-components/ + │ └── hello-world.tsx # Example front component + ├── views/ + │ └── example-view.ts # Example saved view definition + ├── navigation-menu-items/ + │ └── example-navigation-menu-item.ts # Example sidebar navigation link + └── skills/ + └── example-skill.ts # Example AI agent skill definition +``` + +Mit `--minimal` werden nur die Kerndateien erstellt (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` und `logic-functions/post-install.ts`). + +Auf hoher Ebene: + +* **package.json**: Deklariert den App-Namen, die Version und die Engines (Node 24+, Yarn 4) und fügt `twenty-sdk` sowie ein `twenty`-Skript hinzu, das an die lokale `twenty`-CLI delegiert. Führen Sie `yarn twenty help` aus, um alle verfügbaren Befehle aufzulisten. +* **.gitignore**: Ignoriert übliche Artefakte wie `node_modules`, `.yarn`, `generated/` (typisierter Client), `dist/`, `build/`, Coverage-Ordner, Logdateien und `.env*`-Dateien. +* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Fixieren und konfigurieren die vom Projekt verwendete Yarn-4-Toolchain. +* **.nvmrc**: Legt die vom Projekt erwartete Node.js-Version fest. +* **.oxlintrc.json** und **tsconfig.json**: Stellen Linting und TypeScript-Konfiguration für die TypeScript-Quellen Ihrer App bereit. +* **README.md**: Ein kurzes README im App-Root mit grundlegenden Anweisungen. +* **public/**: Ein Ordner zum Speichern öffentlicher Assets (Bilder, Schriftarten, statische Dateien), die zusammen mit Ihrer Anwendung bereitgestellt werden. Hier abgelegte Dateien werden während der Synchronisierung hochgeladen und sind zur Laufzeit zugänglich. +* **src/**: Der Hauptort, an dem Sie Ihre Anwendung als Code definieren + +### Entitätserkennung + +Das SDK erkennt Entitäten, indem es Ihre TypeScript-Dateien nach Aufrufen von **`export default define({...})`** parst. Für jeden Entitätstyp gibt es eine entsprechende Hilfsfunktion, die aus `twenty-sdk` exportiert wird: + +| Hilfsfunktion | Entitätstyp | +| -------------------------------- | ------------------------------------------------------------------------ | +| `defineObject` | Benutzerdefinierte Objektdefinitionen | +| `defineLogicFunction` | Definitionen von Logikfunktionen | +| `definePreInstallLogicFunction` | Pre-Installations-Logikfunktion (wird vor der Installation ausgeführt) | +| `definePostInstallLogicFunction` | Post-Installations-Logikfunktion (wird nach der Installation ausgeführt) | +| `defineFrontComponent` | Definitionen von Frontend-Komponenten | +| `defineRole` | Rollendefinitionen | +| `defineField` | Felderweiterungen für bestehende Objekte | +| `defineView` | Gespeicherte View-Definitionen | +| `defineNavigationMenuItem` | Definitionen von Navigationsmenüeinträgen | +| `defineSkill` | Skill-Definitionen für KI-Agenten | + + +**Dateibenennung ist flexibel.** Die Entitätserkennung ist AST-basiert — das SDK durchsucht Ihre Quelldateien nach dem Muster `export default define({...})`. Sie können Ihre Dateien und Ordner nach Belieben organisieren. Die Gruppierung nach Entitätstyp (z. B. `logic-functions/`, `roles/`) ist lediglich eine Konvention zur Codeorganisation, keine Voraussetzung. + + +Beispiel für eine erkannte Entität: + +```typescript +// This file can be named anything and placed anywhere in src/ +import { defineObject, FieldType } from 'twenty-sdk'; + +export default defineObject({ + universalIdentifier: '...', + nameSingular: 'postCard', + // ... rest of config +}); +``` + +Spätere Befehle fügen weitere Dateien und Ordner hinzu: + +* `yarn twenty app:dev` generiert automatisch zwei typisierte API-Clients in `node_modules/twenty-sdk/generated`: `CoreApiClient` (für Arbeitsbereichsdaten über `/graphql`) und `MetadataApiClient` (für Arbeitsbereichskonfiguration und Datei-Uploads über `/metadata`). +* `yarn twenty entity:add` fügt unter `src/` Entitätsdefinitionsdateien für Ihre benutzerdefinierten Objekte, Funktionen, Frontend-Komponenten, Rollen, Skills und mehr hinzu. + +## Authentifizierung + +Wenn Sie `yarn twenty auth:login` zum ersten Mal ausführen, werden Sie nach Folgendem gefragt: + +* API-URL (standardmäßig http://localhost:3000 oder Ihr aktuelles Workspace-Profil) +* API-Schlüssel + +Ihre Anmeldedaten werden pro Benutzer in `~/.twenty/config.json` gespeichert. Sie können mehrere Profile verwalten und zwischen ihnen wechseln. + +### Arbeitsbereiche verwalten + +```bash filename="Terminal" +# Login interactively (recommended) +yarn twenty auth:login + +# Login to a specific workspace profile +yarn twenty auth:login --workspace my-custom-workspace + +# List all configured workspaces +yarn twenty auth:list + +# Switch the default workspace (interactive) +yarn twenty auth:switch + +# Switch to a specific workspace +yarn twenty auth:switch production + +# Check current authentication status +yarn twenty auth:status +``` + +Sobald Sie mit `yarn twenty auth:switch` den Arbeitsbereich gewechselt haben, verwenden alle nachfolgenden Befehle standardmäßig diesen Arbeitsbereich. Sie können es weiterhin vorübergehend mit `--workspace ` überschreiben. + +## Manuelle Einrichtung (ohne Scaffolder) + +Wir empfehlen zwar `create-twenty-app` für das beste Einstiegserlebnis, Sie können ein Projekt aber auch manuell einrichten. Installieren Sie die CLI nicht global. Fügen Sie stattdessen `twenty-sdk` als lokale Abhängigkeit hinzu und binden Sie ein einzelnes Skript in Ihrer package.json ein: + +```bash filename="Terminal" +yarn add -D twenty-sdk +``` + +Fügen Sie dann ein `twenty`-Skript hinzu: + +```json filename="package.json" +{ + "scripts": { + "twenty": "twenty" + } +} +``` + +Jetzt können Sie alle Befehle über `yarn twenty ` ausführen, z. B. `yarn twenty app:dev`, `yarn twenty help` usw. + +## Fehlerbehebung + +* Authentifizierungsfehler: Führen Sie `yarn twenty auth:login` aus und stellen Sie sicher, dass Ihr API-Schlüssel die erforderlichen Berechtigungen hat. +* Verbindung zum Server nicht möglich: Überprüfen Sie die API-URL und dass der Twenty-Server erreichbar ist. +* Typen oder Client fehlen/veraltet: Starten Sie `yarn twenty app:dev` neu — der typisierte Client wird automatisch generiert. +* Dev-Modus synchronisiert nicht: Stellen Sie sicher, dass `yarn twenty app:dev` läuft und dass Änderungen von Ihrer Umgebung nicht ignoriert werden. + +Discord-Hilfekanal: https://discord.com/channels/1130383047699738754/1130386664812982322 diff --git a/packages/twenty-docs/l/de/developers/extend/apps/publishing.mdx b/packages/twenty-docs/l/de/developers/extend/apps/publishing.mdx new file mode 100644 index 0000000000..d9f0634aff --- /dev/null +++ b/packages/twenty-docs/l/de/developers/extend/apps/publishing.mdx @@ -0,0 +1,119 @@ +--- +title: Publishing +description: Distribute your Twenty app to the marketplace or deploy it internally. +--- + + +Apps befinden sich derzeit in der Alpha-Testphase. Die Funktion ist funktionsfähig, entwickelt sich jedoch noch weiter. + + +## Übersicht + +Once your app is [built and tested locally](/l/de/developers/extend/apps/building), you have two paths for distributing it: + +* **Publish to npm** — list your app in the Twenty marketplace for any workspace to discover and install. +* **Push a tarball** — deploy your app to a specific Twenty server for internal use without making it publicly available. + +## Publishing to npm + +Publishing to npm makes your app discoverable in the Twenty marketplace. Any Twenty workspace can browse, install, and upgrade marketplace apps directly from the UI. + +### Requirements + +* An [npm](https://www.npmjs.com) account +* Your package name **must** use the `twenty-app-` prefix (e.g., `twenty-app-postcard-sender`) + +### Schritte + +1. **Build your app** — the CLI compiles your TypeScript sources and generates the application manifest: + +```bash filename="Terminal" +yarn twenty app:build +``` + +2. **Publish to npm** — push the built package to the npm registry: + +```bash filename="Terminal" +npx twenty app:publish +``` + +### Auto-discovery + +Packages with the `twenty-app-` prefix are automatically discovered by the Twenty marketplace catalog. Once published, your app appears in the marketplace within a few minutes — no manual registration or approval required. + +### CI publishing + +The scaffolded project includes a GitHub Actions workflow that publishes on every release. It runs `app:build`, then `npm publish --provenance` from the build output: + +```yaml filename=".github/workflows/publish.yml" +name: Publish +on: + release: + types: [published] + +permissions: + contents: read + id-token: write + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "24" + registry-url: https://registry.npmjs.org + - run: yarn install --immutable + - run: npx twenty app:build + - run: npm publish --provenance --access public + working-directory: .twenty/output + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} +``` + +For other CI systems (GitLab CI, CircleCI, etc.), the same three commands apply: `yarn install`, `npx twenty app:build`, then `npm publish` from `.twenty/output`. + + +**npm provenance** is optional but recommended. Publishing with `--provenance` adds a trust badge to your npm listing, letting users verify the package was built from a specific commit in a public CI pipeline. See the [npm provenance docs](https://docs.npmjs.com/generating-provenance-statements) for setup instructions. + + +## Internal distribution + +For apps you don't want publicly available — proprietary tools, enterprise-only integrations, or experimental builds — you can push a tarball directly to a Twenty server. + +### Push a tarball + +Build your app and deploy it to a specific server in one step: + +```bash filename="Terminal" +npx twenty app:publish --server +``` + +Any workspace on that server can then install and upgrade the app from the **Applications** settings page. + +### Version management + +To release an update: + +1. Bump the `version` field in your `package.json` +2. Push a new tarball with `npx twenty app:publish --server ` +3. Workspaces on that server will see the upgrade available in their settings + + +Internal apps are scoped to the server they're pushed to. They won't appear in the public marketplace and can't be installed by workspaces on other servers. + + +## App categories + +Twenty organizes apps into three categories based on how they're distributed: + +| Kategorie | Wie es funktioniert | Visible in marketplace? | +| --------------- | ------------------------------------------------------------------------------------------------------------ | ----------------------- | +| **Entwicklung** | Local dev mode apps running via `yarn twenty app:dev`. Used for building and testing. | Nein | +| **Published** | Apps published to npm with the `twenty-app-` prefix. Listed in the marketplace for any workspace to install. | Ja | +| **Internal** | Apps deployed via tarball to a specific server. Available only to workspaces on that server. | Nein | + + +Start in **Development** mode while building your app. When it's ready, choose **Published** (npm) for broad distribution or **Internal** (tarball) for private deployment. + diff --git a/packages/twenty-docs/l/de/developers/extend/extend.mdx b/packages/twenty-docs/l/de/developers/extend/extend.mdx index cd234e6c65..f38eb0aabe 100644 --- a/packages/twenty-docs/l/de/developers/extend/extend.mdx +++ b/packages/twenty-docs/l/de/developers/extend/extend.mdx @@ -1,7 +1,6 @@ --- title: Erweitern description: Erweitern Sie die Funktionalität von Twenty mit APIs, Webhooks und benutzerdefinierten Apps. -redirect: /developers/introduction --- @@ -16,18 +15,18 @@ Twenty ist darauf ausgelegt, erweiterbar zu sein. Verwenden Sie unsere APIs, Web * **APIs**: Abfragen und ändern Sie Ihre CRM-Daten programmatisch mit REST oder GraphQL * **Webhooks**: Erhalten Sie Benachrichtigungen in Echtzeit, wenn Ereignisse in Twenty auftreten -* **Apps**: Erstellen Sie benutzerdefinierte Anwendungen, die die Funktionalität von Twenty erweitern - Demnächst verfügbar! +* **Apps**: Build custom applications that extend Twenty's capabilities ## Erste Schritte - + Verbinden Sie sich programmgesteuert mit Twenty - + Erhalten Sie Benachrichtigungen über Ereignisse in Echtzeit - - Erstellen Sie Anpassungen als Code (Alpha) + + Build customizations as code diff --git a/packages/twenty-docs/l/de/developers/extend/webhooks.mdx b/packages/twenty-docs/l/de/developers/extend/webhooks.mdx new file mode 100644 index 0000000000..9354918d54 --- /dev/null +++ b/packages/twenty-docs/l/de/developers/extend/webhooks.mdx @@ -0,0 +1,116 @@ +--- +title: Webhooks +description: Erhalten Sie Benachrichtigungen in Echtzeit, wenn Ereignisse in Ihrem CRM auftreten. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +Webhooks übermitteln Daten in Echtzeit an Ihre Systeme, wenn Ereignisse in Twenty auftreten — kein Polling erforderlich. Verwenden Sie sie, um externe Systeme synchron zu halten, Automatisierungen auszulösen oder Benachrichtigungen zu senden. + +## Webhook erstellen + +1. Gehen Sie zu **Einstellungen → APIs & Webhooks → Webhooks** +2. Klicken Sie auf **+ Webhook erstellen** +3. Geben Sie Ihre Webhook-URL ein (muss öffentlich zugänglich sein) +4. Klicken Sie auf **Speichern** + +Der Webhook wird sofort aktiviert und beginnt, Benachrichtigungen zu senden. + + + +### Webhooks verwalten + +**Bearbeiten**: Klicken Sie auf den Webhook → URL aktualisieren → **Speichern** + +**Löschen**: Klicken Sie auf den Webhook → **Löschen** → Bestätigen + +## Ereignisse + +Twenty sendet Webhooks für diese Ereignistypen: + +| Ereignis | Beispiel | +| -------------------------- | ---------------------------------------------------------- | +| **Datensatz erstellt** | `person.created`, `company.created`, `note.created` | +| **Datensatz aktualisiert** | `person.updated`, `company.updated`, `opportunity.updated` | +| **Datensatz gelöscht** | `person.deleted`, `company.deleted` | + +Alle Ereignistypen werden an Ihre Webhook-URL gesendet. Eine Ereignisfilterung kann in zukünftigen Versionen hinzugefügt werden. + +## Payload-Format + +Jeder Webhook sendet eine HTTP-POST-Anfrage mit einem JSON-Body: + +```json +{ + "event": "person.created", + "data": { + "id": "abc12345", + "firstName": "Alice", + "lastName": "Doe", + "email": "alice@example.com", + "createdAt": "2025-02-10T15:30:45Z", + "createdBy": "user_123" + }, + "timestamp": "2025-02-10T15:30:50Z" +} +``` + +| Feld | Beschreibung | +| ----------- | -------------------------------------------------------------------- | +| `event` | Was passiert ist (z. B. `person.created`) | +| `data` | Der vollständige Datensatz, der erstellt/aktualisiert/gelöscht wurde | +| `timestamp` | Wann das Ereignis auftrat (UTC) | + + +Antworten Sie mit einem **2xx-HTTP-Status** (200-299), um den Empfang zu bestätigen. Nicht-2xx-Antworten werden als Zustellfehler protokolliert. + + +## Webhook-Validierung + +Twenty signiert jede Webhook-Anfrage zu Sicherheitszwecken. Validieren Sie die Signaturen, um sicherzustellen, dass die Anfragen authentisch sind. + +### Header + +| Header | Beschreibung | +| ---------------------------- | ----------------------- | +| `X-Twenty-Webhook-Signature` | HMAC-SHA256-Signatur | +| `X-Twenty-Webhook-Timestamp` | Zeitstempel der Anfrage | + +### Validierungsschritte + +1. Den Zeitstempel aus `X-Twenty-Webhook-Timestamp` abrufen +2. Zeichenfolge erstellen: `{timestamp}:{JSON payload}` +3. Den HMAC-SHA256-Hash mit Ihrem Webhook-Geheimnis berechnen +4. Mit `X-Twenty-Webhook-Signature` vergleichen + +### Beispiel (Node.js) + +```javascript +const crypto = require("crypto"); + +const timestamp = req.headers["x-twenty-webhook-timestamp"]; +const payload = JSON.stringify(req.body); +const secret = "your-webhook-secret"; + +const stringToSign = `${timestamp}:${payload}`; +const expectedSignature = crypto + .createHmac("sha256", secret) + .update(stringToSign) + .digest("hex"); + +const receivedSignature = req.headers["x-twenty-webhook-signature"]; +const isValid = crypto.timingSafeEqual( + Buffer.from(expectedSignature, "hex"), + Buffer.from(receivedSignature, "hex") +); +``` + +## Webhooks vs Workflows + +| Methode | Richtung | Anwendungsfall | +| ---------------------------- | -------- | -------------------------------------------------------------------------------- | +| **Webhooks** | OUT | Externe Systeme automatisch über jede Datensatzänderung benachrichtigen | +| **Workflow + HTTP-Anfrage** | OUT | Daten mit benutzerdefinierter Logik (Filter, Transformationen) nach außen senden | +| **Workflow-Webhook-Trigger** | IN | Daten aus externen Systemen in Twenty empfangen | + +Für den Empfang externer Daten siehe [Webhook-Trigger einrichten](/l/de/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger). diff --git a/packages/twenty-docs/l/de/developers/introduction.mdx b/packages/twenty-docs/l/de/developers/introduction.mdx index ea8d287a30..d9b37c2174 100644 --- a/packages/twenty-docs/l/de/developers/introduction.mdx +++ b/packages/twenty-docs/l/de/developers/introduction.mdx @@ -5,28 +5,18 @@ description: Willkommen in der Twenty-Entwicklerdokumentation, Ihren Ressourcen import { CardTitle } from "/snippets/card-title.mdx" - - - API - Abfragen und modifizieren Sie Ihre CRM-Daten mit REST oder GraphQL. + + + Erweitern + Erstellen Sie Integrationen mit APIs, Webhooks und benutzerdefinierten Apps. - - Webhooks - Erhalten Sie Echtzeit-Benachrichtigungen bei Ereignissen. - - - - Apps - Erstellen Sie benutzerdefinierte Anwendungen, die die Möglichkeiten von Twenty erweitern. - - - + Selbst hosten Stellen Sie Twenty auf Ihrer eigenen Infrastruktur bereit und verwalten Sie es. - + Mitwirken Treten Sie unserer Open-Source-Community bei und tragen Sie zu Twenty bei. diff --git a/packages/twenty-docs/l/de/user-guide/data-migration/how-tos/export-your-data.mdx b/packages/twenty-docs/l/de/user-guide/data-migration/how-tos/export-your-data.mdx index 95d340260c..933436c031 100644 --- a/packages/twenty-docs/l/de/user-guide/data-migration/how-tos/export-your-data.mdx +++ b/packages/twenty-docs/l/de/user-guide/data-migration/how-tos/export-your-data.mdx @@ -24,7 +24,7 @@ Exportieren Sie die Daten Ihres Arbeitsbereichs als CSV für Backups, Berichte o * Nur **sichtbare Spalten** werden exportiert * Nur **gefilterte Datensätze** werden exportiert (basierend auf Ihrer aktuellen Ansicht) -Für größere Exporte (mehr als 20.000 Datensätze) verwenden Sie Filter, um stapelweise zu exportieren, oder nutzen Sie die [API](/l/de/developers/api). +Für größere Exporte (mehr als 20.000 Datensätze) verwenden Sie Filter, um stapelweise zu exportieren, oder nutzen Sie die [API](/l/de/developers/extend/api). ### Berechtigungen @@ -148,7 +148,7 @@ Die API hat kein Datensatzlimit: 2. Verwenden Sie die GraphQL-API, um Datensätze abzufragen 3. Verarbeiten Sie die Ergebnisse in Ihrer Anwendung -Siehe: [API-Dokumentation](/l/de/developers/api) +Siehe: [API-Dokumentation](/l/de/developers/extend/api) ## Tipps und Best Practices @@ -206,4 +206,4 @@ Exportierte Dateien können sensible Daten enthalten: * [So aktualisieren Sie vorhandene Datensätze](/l/de/user-guide/data-migration/how-tos/update-existing-records-via-import) — bearbeiten Sie Ihren Export und importieren Sie ihn erneut * [So importieren Sie Daten über die API](/l/de/user-guide/data-migration/how-tos/import-data-via-api) — für große Datensätze -* [API-Dokumentation](/l/de/developers/api) — erstellen Sie benutzerdefinierte Export-Workflows +* [API-Dokumentation](/l/de/developers/extend/api) — erstellen Sie benutzerdefinierte Export-Workflows diff --git a/packages/twenty-docs/l/de/user-guide/data-migration/how-tos/import-data-via-api.mdx b/packages/twenty-docs/l/de/user-guide/data-migration/how-tos/import-data-via-api.mdx index adc8e45b4a..989a912d44 100644 --- a/packages/twenty-docs/l/de/user-guide/data-migration/how-tos/import-data-via-api.mdx +++ b/packages/twenty-docs/l/de/user-guide/data-migration/how-tos/import-data-via-api.mdx @@ -57,10 +57,10 @@ Jeder, der Ihren API-Schlüssel besitzt, kann auf die Daten Ihres Arbeitsbereich Twenty unterstützt zwei API-Typen: -| API | Am besten geeignet für | Dokumentation | -| ----------- | ---------------------------------------------------------------- | --------------------------------------------------------- | -| **GraphQL** | Flexible Abfragen, Abruf verknüpfter Daten, komplexe Operationen | [API-Dokumentation](/l/de/developers/api) | -| **REST** | Einfache CRUD-Operationen, vertraute REST-Muster | [API-Dokumentation](/l/de/developers/api) | +| API | Am besten geeignet für | Dokumentation | +| ----------- | ---------------------------------------------------------------- | ------------------------------------------- | +| **GraphQL** | Flexible Abfragen, Abruf verknüpfter Daten, komplexe Operationen | [API-Dokumentation](/l/de/developers/extend/api) | +| **REST** | Einfache CRUD-Operationen, vertraute REST-Muster | [API-Dokumentation](/l/de/developers/extend/api) | Beide APIs unterstützen: @@ -173,4 +173,4 @@ Kontaktieren Sie uns unter [contact@twenty.com](mailto:contact@twenty.com) oder Für vollständige Implementierungsdetails, Codebeispiele und Schema-Referenz: -* [API-Dokumentation](/l/de/developers/api) +* [API-Dokumentation](/l/de/developers/extend/api) diff --git a/packages/twenty-docs/l/de/user-guide/getting-started/capabilities/what-is-twenty.mdx b/packages/twenty-docs/l/de/user-guide/getting-started/capabilities/what-is-twenty.mdx index 48cf5127b2..65e6ed692e 100644 --- a/packages/twenty-docs/l/de/user-guide/getting-started/capabilities/what-is-twenty.mdx +++ b/packages/twenty-docs/l/de/user-guide/getting-started/capabilities/what-is-twenty.mdx @@ -35,7 +35,7 @@ Open-Source ist das Fundament unseres Ansatzes, das sicherstellt, dass Twenty si * **Dashboards:** Verfolgen Sie die Leistung mit benutzerdefinierten Berichten und Visualisierungen. [Dashboards anzeigen](/l/de/user-guide/dashboards/overview). * **Berechtigungen & Zugriff:** Steuern Sie mithilfe rollenbasierter Berechtigungen, wer Ihre Daten anzeigen, bearbeiten und verwalten kann. [Zugriff konfigurieren](/l/de/user-guide/permissions-access/overview). * **Notizen & Aufgaben:** Erstellen Sie Notizen und Aufgaben, die mit Ihren Datensätzen verknüpft sind, für eine bessere Zusammenarbeit. -* **API & Webhooks:** Verbinden Sie sich mit anderen Apps und erstellen Sie benutzerdefinierte Integrationen. [Integration starten](/l/de/developers/api). +* **API & Webhooks:** Verbinden Sie sich mit anderen Apps und erstellen Sie benutzerdefinierte Integrationen. [Integration starten](/l/de/developers/extend/api). ## Jetzt beitreten diff --git a/packages/twenty-docs/l/de/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx b/packages/twenty-docs/l/de/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx index 649afdc53a..0ddbaa07fc 100644 --- a/packages/twenty-docs/l/de/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx +++ b/packages/twenty-docs/l/de/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx @@ -95,7 +95,7 @@ Erstellen Sie die Zielfelder in **Settings → Data Model → Opportunities**: * Unternehmensgröße: `{{searchRecords[0].employees}}` -**Einschränkung bei Aufgaben und Notizen**: Beziehungen bei Aufgaben und Notizen sind fest als Viele-zu-Viele implementiert und stehen in Workflow-Auslösern oder -Aktionen noch nicht zur Verfügung. Um auf diese Beziehungen zuzugreifen, verwenden Sie stattdessen die [API](/l/de/developers/api). +**Einschränkung bei Aufgaben und Notizen**: Beziehungen bei Aufgaben und Notizen sind fest als Viele-zu-Viele implementiert und stehen in Workflow-Auslösern oder -Aktionen noch nicht zur Verfügung. Um auf diese Beziehungen zuzugreifen, verwenden Sie stattdessen die [API](/l/de/developers/extend/api). ## Bidirektionale Synchronisierung diff --git a/packages/twenty-docs/l/it/developers/contribute/capabilities/frontend-development/frontend-commands.mdx b/packages/twenty-docs/l/it/developers/contribute/capabilities/frontend-development/frontend-commands.mdx index 77ea6146b3..30fb17f7be 100644 --- a/packages/twenty-docs/l/it/developers/contribute/capabilities/frontend-development/frontend-commands.mdx +++ b/packages/twenty-docs/l/it/developers/contribute/capabilities/frontend-development/frontend-commands.mdx @@ -77,7 +77,7 @@ Per evitare [re-render](/l/it/developers/contribute/capabilities/frontend-develo ### Gestione dello stato -[Jotai](https://jotai.org/) gestisce lo stato. +[Jotai](https://jotai.org/) handles state management. Vedi [best practices](/l/it/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) per ulteriori informazioni sulla gestione dello stato. diff --git a/packages/twenty-docs/l/it/developers/extend/api.mdx b/packages/twenty-docs/l/it/developers/extend/api.mdx new file mode 100644 index 0000000000..0cca51af44 --- /dev/null +++ b/packages/twenty-docs/l/it/developers/extend/api.mdx @@ -0,0 +1,147 @@ +--- +title: API +description: Interroga e modifica i dati del tuo CRM in modo programmatico usando REST o GraphQL. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +Twenty è stato progettato per essere adatto agli sviluppatori, offrendo potenti API che si adattano al tuo modello di dati personalizzato. Forniamo quattro tipi distinti di API per soddisfare diverse esigenze di integrazione. + +## Approccio incentrato sullo sviluppatore + +Twenty genera API specifiche per il tuo modello di dati: + +* **Nessun ID lungo richiesto**: Utilizza direttamente i nomi degli oggetti e dei campi negli endpoint +* **Oggetti standard e personalizzati trattati allo stesso modo**: I tuoi oggetti personalizzati ricevono lo stesso trattamento API di quelli predefiniti +* **Endpoint dedicati**: Ogni oggetto e campo ottiene il proprio endpoint API +* **Documentazione personalizzata**: Generata specificamente per il modello di dati del tuo workspace + + +La documentazione personalizzata delle tue API è disponibile in **Impostazioni → API & Webhooks** dopo aver creato una chiave API. Poiché Twenty genera API che corrispondono al tuo modello di dati personalizzato, la documentazione è unica per il tuo workspace. + + +## I due tipi di API + +### Core API + +Accessibile su `/rest/` o `/graphql/` + +Lavora con i tuoi **record** reali (i dati): + +* Crea, leggi, aggiorna, elimina Persone, Aziende, Opportunità, ecc. +* Interroga e filtra i dati +* Gestisci le relazioni tra i record + +### Metadata API + +Accessibile su `/rest/metadata/` o `/metadata/` + +Gestisci il tuo **workspace e il modello di dati**: + +* Crea, modifica o elimina oggetti e campi +* Configura le impostazioni del workspace +* Definisci le relazioni tra oggetti + +## REST vs GraphQL + +Sia le API Core che le API Metadata sono disponibili nei formati REST e GraphQL: + +| Formato | Operazioni disponibili | +| ----------- | ------------------------------------------------------------------------------------- | +| **REST** | CRUD, operazioni batch, upsert | +| **GraphQL** | Stesse funzionalità + **upsert in batch**, query sulle relazioni in un'unica chiamata | + +Scegli in base alle tue esigenze — entrambi i formati accedono agli stessi dati. + +## Endpoint API + +| Ambiente | URL di base | +| ----------------- | ------------------------- | +| **Cloud** | `https://api.twenty.com/` | +| **Auto-ospitato** | `https://{your-domain}/` | + +## Autenticazione + +Ogni richiesta API richiede una chiave API nell'intestazione: + +``` +Authorization: Bearer YOUR_API_KEY +``` + +### Crea una chiave API + +1. Vai a **Impostazioni → APIs & Webhooks** +2. Fai clic su **+ Crea chiave** +3. Configura: + * **Nome**: Nome descrittivo per la chiave + * **Data di scadenza**: Quando la chiave scade +4. Fai clic su **Salva** +5. **Copia subito** — la chiave viene mostrata una sola volta + + + + +La tua chiave API concede l'accesso a dati sensibili. Non condividerla con servizi non affidabili. Se compromessa, disabilitala immediatamente e generane una nuova. + + +### Assegna un ruolo a una chiave API + +Per una maggiore sicurezza, assegna un ruolo specifico per limitare l'accesso: + +1. Vai a **Impostazioni → Ruoli** +2. Fai clic sul ruolo da assegnare +3. Apri la scheda **Assegnazione** +4. In **Chiavi API**, fai clic su **+ Assegna alla chiave API** +5. Seleziona la chiave API + +La chiave erediterà le autorizzazioni di quel ruolo. Vedi [Autorizzazioni](/l/it/user-guide/permissions-access/capabilities/permissions) per i dettagli. + +### Gestisci chiavi API + +**Rigenera**: Impostazioni → APIs & Webhooks → Fai clic sulla chiave → **Rigenera** + +**Elimina**: Impostazioni → APIs & Webhooks → Fai clic sulla chiave → **Elimina** + +## Playground API + +Testa le tue API direttamente nel browser con il nostro playground integrato — disponibile sia per **REST** sia per **GraphQL**. + +### Accedi al Playground + +1. Vai a **Impostazioni → APIs & Webhooks** +2. Crea una chiave API (obbligatorio) +3. Fai clic su **REST API** o **GraphQL API** per aprire il playground + +### Cosa ottieni + +* **Documentazione interattiva**: Generata per il tuo specifico modello di dati +* **Test in tempo reale**: Esegui chiamate API reali sul tuo workspace +* **Esploratore dello schema**: Sfoglia gli oggetti, i campi e le relazioni disponibili +* **Generatore di richieste**: Crea query con completamento automatico + +Il playground riflette i tuoi oggetti e campi personalizzati, quindi la documentazione è sempre accurata per il tuo workspace. + +## Operazioni Batch + +Sia REST che GraphQL supportano operazioni batch: + +* **Dimensione batch**: Fino a 60 record per richiesta +* **Operazioni**: Creare, aggiornare, eliminare più record + +**Funzionalità esclusive di GraphQL:** + +* **Upsert in batch**: Crea o aggiorna in un'unica chiamata +* Usa nomi oggetto al plurale (ad es. `CreateCompanies` invece di `CreateCompany`) + +## Limiti di frequenza delle API + +Le richieste API sono limitate per garantire la stabilità della piattaforma: + +| Limite | Valore | +| -------------------- | ---------------------- | +| **Richieste** | 100 chiamate al minuto | +| **Dimensione batch** | 60 record per chiamata | + + +Usa le operazioni batch per massimizzare il throughput — elabora fino a 60 record in una singola chiamata API invece di effettuare richieste individuali. + diff --git a/packages/twenty-docs/l/it/developers/extend/apps/building.mdx b/packages/twenty-docs/l/it/developers/extend/apps/building.mdx new file mode 100644 index 0000000000..b92c486b6f --- /dev/null +++ b/packages/twenty-docs/l/it/developers/extend/apps/building.mdx @@ -0,0 +1,689 @@ +--- +title: Creazione di app +description: Definisci oggetti, funzioni logiche, componenti front-end e molto altro con il Twenty SDK. +--- + + +Le app sono attualmente in fase alfa. La funzionalità è funzionante ma ancora in evoluzione. + + +## Usa le risorse dell'SDK (tipi e configurazione) + +Il pacchetto twenty-sdk fornisce blocchi tipizzati e funzioni helper da usare nella tua app. Di seguito gli elementi principali con cui interagirai più spesso. + +### Funzioni helper + +L'SDK fornisce funzioni helper per definire le entità della tua app. Come descritto in [Rilevamento delle entità](/l/it/developers/extend/apps/getting-started#entity-detection), devi usare `export default define({...})` affinché le tue entità vengano rilevate: + +| Funzione | Scopo | +| -------------------------------- | ----------------------------------------------------------------------- | +| `defineApplication` | Configura i metadati dell'applicazione (obbligatorio, uno per app) | +| `defineObject` | Definisci oggetti personalizzati con campi | +| `defineLogicFunction` | Definisci funzioni logiche con handler | +| `definePreInstallLogicFunction` | Definisci una funzione logica di pre-installazione (una per app) | +| `definePostInstallLogicFunction` | Definisci una funzione logica di post-installazione (una per app) | +| `defineFrontComponent` | Definisci componenti front-end per un'interfaccia utente personalizzata | +| `defineRole` | Configura i permessi dei ruoli e l'accesso agli oggetti | +| `defineField` | Estendi gli oggetti esistenti con campi aggiuntivi | +| `defineView` | Definisci viste salvate per gli oggetti | +| `defineNavigationMenuItem` | Definisci i link di navigazione della barra laterale | +| `defineSkill` | Definisci le competenze dell'agente IA | + +Queste funzioni convalidano la configurazione in fase di build e offrono il completamento automatico nell'IDE e la sicurezza dei tipi. + +### Definizione degli oggetti + +Gli oggetti personalizzati descrivono sia lo schema sia il comportamento per i record nel tuo spazio di lavoro. Usa `defineObject()` per definire oggetti con convalida integrata: + +```typescript +// src/app/postCard.object.ts +import { defineObject, FieldType } from 'twenty-sdk'; + +enum PostCardStatus { + DRAFT = 'DRAFT', + SENT = 'SENT', + DELIVERED = 'DELIVERED', + RETURNED = 'RETURNED', +} + +export default defineObject({ + universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05', + nameSingular: 'postCard', + namePlural: 'postCards', + labelSingular: 'Post Card', + labelPlural: 'Post Cards', + description: 'A post card object', + icon: 'IconMail', + fields: [ + { + universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b', + name: 'content', + type: FieldType.TEXT, + label: 'Content', + description: "Postcard's content", + icon: 'IconAbc', + }, + { + universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac', + name: 'recipientName', + type: FieldType.FULL_NAME, + label: 'Recipient name', + icon: 'IconUser', + }, + { + universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266', + name: 'recipientAddress', + type: FieldType.ADDRESS, + label: 'Recipient address', + icon: 'IconHome', + }, + { + universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e', + name: 'status', + type: FieldType.SELECT, + label: 'Status', + icon: 'IconSend', + defaultValue: `'${PostCardStatus.DRAFT}'`, + options: [ + { value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' }, + { value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' }, + { value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' }, + { value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' }, + ], + }, + { + universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433', + name: 'deliveredAt', + type: FieldType.DATE_TIME, + label: 'Delivered at', + icon: 'IconCheck', + isNullable: true, + defaultValue: null, + }, + ], +}); +``` + +Punti chiave: + +* Usa `defineObject()` per una convalida integrata e un migliore supporto IDE. +* Il `universalIdentifier` deve essere univoco e stabile tra i deployment. +* Ogni campo richiede un `name`, `type`, `label` e il proprio `universalIdentifier` stabile. +* L'array `fields` è facoltativo: puoi definire oggetti senza campi personalizzati. +* Puoi generare nuovi oggetti con `yarn twenty entity:add`, che ti guida nella denominazione, nei campi e nelle relazioni. + + +**I campi base vengono creati automaticamente.** Quando definisci un oggetto personalizzato, Twenty aggiunge automaticamente i campi standard +come `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` e `deletedAt`. +Non è necessario definirli nel tuo array `fields` — aggiungi solo i tuoi campi personalizzati. +Puoi sovrascrivere i campi predefiniti definendo un campo con lo stesso nome nel tuo array `fields`, +ma non è consigliato. + + +### Configurazione dell'applicazione (application-config.ts) + +Ogni app ha un singolo file `application-config.ts` che descrive: + +* **Identità dell'app**: identificatori, nome visualizzato e descrizione. +* **Come vengono eseguite le sue funzioni**: quale ruolo usano per i permessi. +* **Variabili (opzionali)**: coppie chiave–valore esposte alle funzioni come variabili d'ambiente. +* **(Opzionale) funzione di pre-installazione**: una funzione logica che viene eseguita prima che l'app venga installata. +* **(Opzionale) funzione post-installazione**: una funzione logica che viene eseguita dopo l'installazione dell'app. + +Usa `defineApplication()` per definire la configurazione della tua applicazione: + +```typescript +// src/application-config.ts +import { defineApplication } from 'twenty-sdk'; +import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role'; + +export default defineApplication({ + universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7', + displayName: 'My Twenty App', + description: 'My first Twenty app', + icon: 'IconWorld', + applicationVariables: { + DEFAULT_RECIPIENT_NAME: { + universalIdentifier: '19e94e59-d4fe-4251-8981-b96d0a9f74de', + description: 'Default recipient name for postcards', + value: 'Jane Doe', + isSecret: false, + }, + }, + defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, +}); +``` + +Note: + +* I campi `universalIdentifier` sono ID deterministici sotto il tuo controllo; generali una volta e mantienili stabili tra le sincronizzazioni. +* `applicationVariables` diventano variabili d'ambiente per le tue funzioni (ad esempio, `DEFAULT_RECIPIENT_NAME` è disponibile come `process.env.DEFAULT_RECIPIENT_NAME`). +* `defaultRoleUniversalIdentifier` deve corrispondere al file del ruolo (vedi sotto). +* Le funzioni di pre-installazione e post-installazione vengono rilevate automaticamente durante la build del manifesto. Vedi [Funzioni di pre-installazione](#pre-install-functions) e [Funzioni di post-installazione](#post-install-functions). + +#### Ruoli e permessi + +Le applicazioni possono definire ruoli che incapsulano i permessi sugli oggetti e sulle azioni del tuo spazio di lavoro. Il campo `defaultRoleUniversalIdentifier` in `application-config.ts` indica il ruolo predefinito utilizzato dalle funzioni logiche della tua app. + +* La chiave API di runtime iniettata come `TWENTY_API_KEY` è derivata da questo ruolo funzione predefinito. +* Il client tipizzato sarà limitato ai permessi concessi a quel ruolo. +* Segui il principio del privilegio minimo: crea un ruolo dedicato con solo i permessi necessari alle tue funzioni, quindi fai riferimento al suo identificatore universale. + +##### Ruolo funzione predefinito (*.role.ts) + +Quando generi una nuova app con lo scaffolder, la CLI crea anche un file di ruolo predefinito. Usa `defineRole()` per definire ruoli con convalida integrata: + +```typescript +// src/roles/default-role.ts +import { defineRole, PermissionFlag } from 'twenty-sdk'; + +export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = + 'b648f87b-1d26-4961-b974-0908fd991061'; + +export default defineRole({ + universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, + label: 'Default function role', + description: 'Default role for function Twenty client', + canReadAllObjectRecords: false, + canUpdateAllObjectRecords: false, + canSoftDeleteAllObjectRecords: false, + canDestroyAllObjectRecords: false, + canUpdateAllSettings: false, + canBeAssignedToAgents: false, + canBeAssignedToUsers: false, + canBeAssignedToApiKeys: false, + objectPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + canReadObjectRecords: true, + canUpdateObjectRecords: true, + canSoftDeleteObjectRecords: false, + canDestroyObjectRecords: false, + }, + ], + fieldPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + fieldUniversalIdentifier: 'b2c37dc0-8ae7-470e-96cd-1476b47dfaff', + canReadFieldValue: false, + canUpdateFieldValue: false, + }, + ], + permissionFlags: [PermissionFlag.APPLICATIONS], +}); +``` + +L'`universalIdentifier` di questo ruolo viene quindi referenziato in `application-config.ts` come `defaultRoleUniversalIdentifier`. In altre parole: + +* **\*.role.ts** definisce ciò che il ruolo funzione predefinito può fare. +* **application-config.ts** punta a quel ruolo in modo che le tue funzioni ne ereditino i permessi. + +Note: + +* Parti dal ruolo generato dallo scaffolder, quindi restringilo progressivamente seguendo il principio del privilegio minimo. +* Sostituisci `objectPermissions` e `fieldPermissions` con gli oggetti/campi di cui le tue funzioni hanno bisogno. +* `permissionFlags` controllano l'accesso alle funzionalità a livello di piattaforma. Mantienili al minimo; aggiungi solo ciò che ti serve. +* Vedi un esempio funzionante nell'app Hello World: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). + +### Configurazione e punto di ingresso della funzione logica + +Ogni file di funzione usa `defineLogicFunction()` per esportare una configurazione con un handler e trigger opzionali. + +```typescript +// src/app/createPostCard.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk'; +import { CoreApiClient, type Person } from 'twenty-sdk/generated'; + +const handler = async (params: RoutePayload) => { + const client = new CoreApiClient(); + const name = 'name' in params.queryStringParameters + ? params.queryStringParameters.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world' + : 'Hello world'; + + const result = await client.mutation({ + createPostCard: { + __args: { data: { name } }, + id: true, + name: true, + }, + }); + return result; +}; + +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'create-new-post-card', + timeoutSeconds: 2, + handler, + triggers: [ + // Public HTTP route trigger '/s/post-card/create' + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/post-card/create', + httpMethod: 'GET', + isAuthRequired: false, + }, + // Cron trigger (CRON pattern) + // { + // universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2', + // type: 'cron', + // pattern: '0 0 1 1 *', + // }, + // Database event trigger + // { + // universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156', + // type: 'databaseEvent', + // eventName: 'person.updated', + // updatedFields: ['name'], + // }, + ], +}); +``` + +Tipi di trigger comuni: + +* **route**: Espone la funzione su un percorso e metodo HTTP **sotto l'endpoint `/s/`**: + +> es. `path: '/post-card/create',` -> chiamata su `/s/post-card/create` + +* **cron**: Esegue la tua funzione secondo una pianificazione utilizzando un'espressione CRON. +* **databaseEvent**: Viene eseguito sugli eventi del ciclo di vita degli oggetti dello spazio di lavoro. Quando l'operazione dell'evento è `updated`, è possibile specificare campi specifici da monitorare nell'array `updatedFields`. Se lasciato non definito o vuoto, qualsiasi aggiornamento attiverà la funzione. + +> es. `person.updated` + +Note: + +* L'array `triggers` è facoltativo. Le funzioni senza trigger possono essere utilizzate come funzioni di utilità richiamate da altre funzioni. +* Puoi combinare più tipi di trigger in un'unica funzione. + +### Funzioni di pre-installazione + +Una funzione di pre-installazione è una funzione logica che viene eseguita automaticamente prima che la tua app venga installata in uno spazio di lavoro. È utile per attività di convalida, controlli dei prerequisiti o per preparare lo stato dello spazio di lavoro prima che proceda l'installazione principale. + +Quando esegui lo scaffolding di una nuova app con `create-twenty-app`, viene generata una funzione di pre-installazione in `src/logic-functions/pre-install.ts`: + +```typescript +// src/logic-functions/pre-install.ts +import { definePreInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Pre install logic function executed successfully!', payload.previousVersion); +}; + +export default definePreInstallLogicFunction({ + universalIdentifier: '', + name: 'pre-install', + description: 'Runs before installation to prepare the application.', + timeoutSeconds: 300, + handler, +}); +``` + +Puoi anche eseguire manualmente la funzione di pre-installazione in qualsiasi momento utilizzando la CLI: + +```bash filename="Terminal" +yarn twenty function:execute --preInstall +``` + +Punti chiave: + +* Le funzioni di pre-installazione utilizzano `definePreInstallLogicFunction()` — una variante specializzata che omette le impostazioni dei trigger (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`). +* L'handler riceve un `InstallLogicFunctionPayload` con `{ previousVersion: string }` — la versione dell'app precedentemente installata (oppure una stringa vuota per nuove installazioni). +* È consentita una sola funzione di pre-installazione per applicazione. La build del manifesto genererà un errore se ne viene rilevata più di una. +* L'`universalIdentifier` della funzione viene impostato automaticamente come `preInstallLogicFunctionUniversalIdentifier` nel manifesto dell'applicazione durante la build — non è necessario farvi riferimento in `defineApplication()`. +* Il timeout predefinito è impostato a 300 secondi (5 minuti) per consentire attività di preparazione più lunghe. +* Le funzioni di pre-installazione non necessitano di trigger — vengono invocate dalla piattaforma prima dell'installazione o manualmente tramite `function:execute --preInstall`. + +### Funzioni post-installazione + +Una funzione post-installazione è una funzione logica che viene eseguita automaticamente dopo che la tua app è stata installata in uno spazio di lavoro. Questo è utile per attività di configurazione una tantum come il popolamento di dati predefiniti, la creazione di record iniziali o la configurazione delle impostazioni dello spazio di lavoro. + +Quando esegui lo scaffolding di una nuova app con `create-twenty-app`, viene generata automaticamente una funzione di post-installazione in `src/logic-functions/post-install.ts`: + +```typescript +// src/logic-functions/post-install.ts +import { definePostInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Post install logic function executed successfully!', payload.previousVersion); +}; + +export default definePostInstallLogicFunction({ + universalIdentifier: '', + name: 'post-install', + description: 'Runs after installation to set up the application.', + timeoutSeconds: 300, + handler, +}); +``` + +Puoi anche eseguire manualmente la funzione di post-installazione in qualsiasi momento utilizzando la CLI: + +```bash filename="Terminal" +yarn twenty function:execute --postInstall +``` + +Punti chiave: + +* Le funzioni di post-installazione utilizzano `definePostInstallLogicFunction()` — una variante specializzata che omette le impostazioni dei trigger (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`). +* L'handler riceve un `InstallLogicFunctionPayload` con `{ previousVersion: string }` — la versione dell'app precedentemente installata (oppure una stringa vuota per nuove installazioni). +* È consentita una sola funzione di post-installazione per applicazione. La build del manifesto genererà un errore se ne viene rilevata più di una. +* L'`universalIdentifier` della funzione viene impostato automaticamente come `postInstallLogicFunctionUniversalIdentifier` nel manifesto dell'applicazione durante la build — non è necessario farvi riferimento in `defineApplication()`. +* Il timeout predefinito è impostato a 300 secondi (5 minuti) per consentire attività di configurazione più lunghe, come il popolamento dei dati. +* Le funzioni di post-installazione non necessitano di trigger — vengono invocate dalla piattaforma durante l'installazione o manualmente tramite `function:execute --postInstall`. + +### Payload del trigger di route + + +**Modifica non retrocompatibile (v1.16, gennaio 2026):** Il formato del payload del trigger di route è cambiato. Prima della v1.16, i parametri di query, i parametri di percorso e il corpo venivano inviati direttamente come payload. A partire dalla v1.16, sono annidati all'interno di un oggetto `RoutePayload` strutturato. + +**Prima della v1.16:** +```typescript +const handler = async (params) => { + const { param1, param2 } = params; // Direct access +}; +``` + +**Dopo la v1.16:** +```typescript +const handler = async (event: RoutePayload) => { + const { param1, param2 } = event.body; // Access via .body + const { queryParam } = event.queryStringParameters; + const { id } = event.pathParameters; +}; +``` + +**Per migrare le funzioni esistenti:** Aggiorna l'handler per estrarre i dati da `event.body`, `event.queryStringParameters` o `event.pathParameters` invece che direttamente dall'oggetto `params`. + + +Quando un trigger di route invoca la tua funzione logica, questa riceve un oggetto `RoutePayload` che segue il formato AWS HTTP API v2. Importa il tipo da `twenty-sdk`: + +```typescript +import { defineLogicFunction, type RoutePayload } from 'twenty-sdk'; + +const handler = async (event: RoutePayload) => { + // Access request data + const { headers, queryStringParameters, pathParameters, body } = event; + + // HTTP method and path are available in requestContext + const { method, path } = event.requestContext.http; + + return { message: 'Success' }; +}; +``` + +Il tipo `RoutePayload` ha la seguente struttura: + +| Proprietà | Tipo | Descrizione | +| ---------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `headers` | `Record` | Intestazioni HTTP (solo quelle elencate in `forwardedRequestHeaders`) | +| `queryStringParameters` | `Record` | Parametri della query string (valori multipli uniti da virgole) | +| `pathParameters` | `Record` | Parametri di percorso estratti dal pattern della route (ad es., `/users/:id` → `{ id: '123' }`) | +| `body` | `object \| null` | Corpo della richiesta analizzato (JSON) | +| `isBase64Encoded` | `boolean` | Indica se il corpo è codificato in base64 | +| `requestContext.http.method` | `string` | Metodo HTTP (GET, POST, PUT, PATCH, DELETE) | +| `requestContext.http.path` | `string` | Percorso della richiesta non elaborato | + +### Inoltro delle intestazioni HTTP + +Per impostazione predefinita, le intestazioni HTTP delle richieste in ingresso **non** vengono passate alla tua funzione logica per motivi di sicurezza. Per accedere a intestazioni specifiche, elencale esplicitamente nell'array `forwardedRequestHeaders`: + +```typescript +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'webhook-handler', + handler, + triggers: [ + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/webhook', + httpMethod: 'POST', + isAuthRequired: false, + forwardedRequestHeaders: ['x-webhook-signature', 'content-type'], + }, + ], +}); +``` + +Nel tuo handler, puoi quindi accedere a queste intestazioni: + +```typescript +const handler = async (event: RoutePayload) => { + const signature = event.headers['x-webhook-signature']; + const contentType = event.headers['content-type']; + + // Validate webhook signature... + return { received: true }; +}; +``` + + + I nomi delle intestazioni vengono normalizzati in minuscolo. Accedile usando chiavi in minuscolo (ad esempio, `event.headers['content-type']`). + + +Puoi creare nuove funzioni in due modi: + +* **Generata dallo scaffolder**: Esegui `yarn twenty entity:add` e scegli l'opzione per aggiungere una nuova funzione logica. Questo genera un file iniziale con un handler e una configurazione. +* **Manuale**: Crea un nuovo file `*.logic-function.ts` e usa `defineLogicFunction()`, seguendo lo stesso schema. + +### Contrassegnare una funzione logica come strumento + +Le funzioni logiche possono essere esposte come **strumenti** per gli agenti di IA e i flussi di lavoro. Quando una funzione è contrassegnata come strumento, diventa individuabile dalle funzionalità di IA di Twenty e può essere selezionata come passaggio nelle automazioni dei flussi di lavoro. + +Per contrassegnare una funzione logica come strumento, imposta `isTool: true` e fornisci un `toolInputSchema` che descriva i parametri di input attesi utilizzando [JSON Schema](https://json-schema.org/): + +```typescript +// src/logic-functions/enrich-company.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import { CoreApiClient } from 'twenty-sdk/generated'; + +const handler = async (params: { companyName: string; domain?: string }) => { + const client = new CoreApiClient(); + + const result = await client.mutation({ + createTask: { + __args: { + data: { + title: `Enrich data for ${params.companyName}`, + body: `Domain: ${params.domain ?? 'unknown'}`, + }, + }, + id: true, + }, + }); + + return { taskId: result.createTask.id }; +}; + +export default defineLogicFunction({ + universalIdentifier: 'f47ac10b-58cc-4372-a567-0e02b2c3d479', + name: 'enrich-company', + description: 'Enrich a company record with external data', + timeoutSeconds: 10, + handler, + isTool: true, + toolInputSchema: { + type: 'object', + properties: { + companyName: { + type: 'string', + description: 'The name of the company to enrich', + }, + domain: { + type: 'string', + description: 'The company website domain (optional)', + }, + }, + required: ['companyName'], + }, +}); +``` + +Punti chiave: + +* **`isTool`** (`boolean`, predefinito: `false`): Quando impostato su `true`, la funzione viene registrata come strumento e diventa disponibile per gli agenti IA e le automazioni dei flussi di lavoro. +* **`toolInputSchema`** (`object`, opzionale): Un oggetto JSON Schema che descrive i parametri accettati dalla funzione. Gli agenti IA utilizzano questo schema per capire quali input si aspetta lo strumento e per convalidare le chiamate. Se omesso, lo schema assume il valore predefinito `{ type: 'object', properties: {} }` (nessun parametro). +* Le funzioni con `isTool: false` (o non impostato) **non** vengono esposte come strumenti. Possono comunque essere eseguite direttamente o chiamate da altre funzioni, ma non compariranno nell'individuazione degli strumenti. +* **Denominazione dello strumento**: Quando esposta come strumento, il nome della funzione viene normalizzato automaticamente in `logic_function_` (in minuscolo, i caratteri non alfanumerici vengono sostituiti da trattini bassi). Ad esempio, `enrich-company` diventa `logic_function_enrich_company`. +* È possibile combinare `isTool` con i trigger — una funzione può essere sia uno strumento (invocabile dagli agenti IA) sia attivata da eventi (cron, eventi del database, routes) contemporaneamente. + + +**Scrivi una buona `description`.** Gli agenti IA fanno affidamento sul campo `description` della funzione per decidere quando usare lo strumento. Sii specifico su cosa fa lo strumento e quando dovrebbe essere invocato. + + +### Componenti front-end + +I componenti front-end ti consentono di creare componenti React personalizzati che vengono renderizzati all'interno dell'interfaccia di Twenty. Usa `defineFrontComponent()` per definire componenti con convalida integrata: + +```typescript +// src/front-components/my-widget.tsx +import { defineFrontComponent } from 'twenty-sdk'; + +const MyWidget = () => { + return ( +
+

My Custom Widget

+

This is a custom front component for Twenty.

+
+ ); +}; + +export default defineFrontComponent({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'my-widget', + description: 'A custom widget component', + component: MyWidget, +}); +``` + +Punti chiave: + +* I componenti front-end sono componenti React che eseguono il rendering in contesti isolati all'interno di Twenty. +* Il campo `component` fa riferimento al tuo componente React. +* I componenti vengono compilati e sincronizzati automaticamente durante `yarn twenty app:dev`. + +Puoi creare nuovi componenti front-end in due modi: + +* **Generata dallo scaffolder**: Esegui `yarn twenty entity:add` e scegli l'opzione per aggiungere un nuovo componente front-end. +* **Manuale**: Crea un nuovo file `.tsx` e usa `defineFrontComponent()`, seguendo lo stesso schema. + +### Abilità + +Le skill definiscono istruzioni e capacità riutilizzabili che gli agenti IA possono utilizzare all'interno del tuo spazio di lavoro. Usa `defineSkill()` per definire skill con convalida integrata: + +```typescript +// src/skills/example-skill.ts +import { defineSkill } from 'twenty-sdk'; + +export default defineSkill({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'sales-outreach', + label: 'Sales Outreach', + description: 'Guides the AI agent through a structured sales outreach process', + icon: 'IconBrain', + content: `You are a sales outreach assistant. When reaching out to a prospect: +1. Research the company and recent news +2. Identify the prospect's role and likely pain points +3. Draft a personalized message referencing specific details +4. Keep the tone professional but conversational`, +}); +``` + +Punti chiave: + +* `name` è una stringa identificativa univoca per la skill (kebab-case consigliato). +* `label` è il nome di visualizzazione leggibile mostrato nell'UI. +* `content` contiene le istruzioni della skill — questo è il testo che l'agente IA utilizza. +* `icon` (opzionale) imposta l'icona visualizzata nell'UI. +* `description` (opzionale) fornisce contesto aggiuntivo sullo scopo della skill. + +Puoi creare nuove skill in due modi: + +* **Generata dallo scaffolder**: Esegui `yarn twenty entity:add` e scegli l'opzione per aggiungere una nuova skill. +* **Manuale**: Crea un nuovo file e usa `defineSkill()`, seguendo lo stesso schema. + +### Client tipizzati generati + +Due client tipizzati sono generati automaticamente da `yarn twenty app:dev` e salvati in `node_modules/twenty-sdk/generated` in base allo schema del tuo spazio di lavoro: + +* **`CoreApiClient`** — interroga l'endpoint `/graphql` per i dati dello spazio di lavoro +* **`MetadataApiClient`** — interroga l'endpoint `/metadata` per la configurazione dello spazio di lavoro e il caricamento dei file + +```typescript +import { CoreApiClient, MetadataApiClient } from 'twenty-sdk/generated'; + +const client = new CoreApiClient(); +const { me } = await client.query({ me: { id: true, displayName: true } }); + +const metadataClient = new MetadataApiClient(); +const { currentWorkspace } = await metadataClient.query({ currentWorkspace: { id: true } }); +``` + +Entrambi i client vengono rigenerati automaticamente da `yarn twenty app:dev` ogni volta che i tuoi oggetti o campi cambiano. + +#### Credenziali di runtime nelle funzioni logiche + +Quando la tua funzione viene eseguita su Twenty, la piattaforma inietta le credenziali come variabili d'ambiente prima dell'esecuzione del tuo codice: + +* `TWENTY_API_URL`: URL di base dell'API Twenty a cui punta la tua app. +* `TWENTY_API_KEY`: Chiave a breve durata con ambito al ruolo funzione predefinito della tua applicazione. + +Note: + +* Non è necessario passare URL o chiave API al client generato. Legge `TWENTY_API_URL` e `TWENTY_API_KEY` da process.env in fase di esecuzione. +* I permessi della chiave API sono determinati dal ruolo referenziato nel tuo `application-config.ts` tramite `defaultRoleUniversalIdentifier`. Questo è il ruolo predefinito utilizzato dalle funzioni logiche della tua applicazione. +* Le applicazioni possono definire ruoli per seguire il principio del privilegio minimo. Concedi solo i permessi necessari alle tue funzioni, quindi punta `defaultRoleUniversalIdentifier` all'identificatore universale di quel ruolo. + +#### Caricamento dei file + +Il `MetadataApiClient` generato include un metodo `uploadFile` per allegare file ai campi di tipo file sugli oggetti del tuo spazio di lavoro. Poiché i client GraphQL standard non supportano nativamente il caricamento di file multipart, il client fornisce questo metodo dedicato che implementa la [specifica della richiesta GraphQL multipart](https://github.com/jaydenseric/graphql-multipart-request-spec) dietro le quinte. + +```typescript +import { MetadataApiClient } from 'twenty-sdk/generated'; +import * as fs from 'fs'; + +const metadataClient = new MetadataApiClient(); + +const fileBuffer = fs.readFileSync('./invoice.pdf'); + +const uploadedFile = await metadataClient.uploadFile( + fileBuffer, // file contents as a Buffer + 'invoice.pdf', // filename + 'application/pdf', // MIME type (defaults to 'application/octet-stream') + '58a0a314-d7ea-4865-9850-7fb84e72f30b', // field universal identifier +); + +console.log(uploadedFile); +// { id: '...', path: '...', size: 12345, createdAt: '...', url: 'https://...' } +``` + +La firma del metodo: + +```typescript +uploadFile( + fileBuffer: Buffer, + filename: string, + contentType: string, + fieldMetadataUniversalIdentifier: string, +): Promise<{ id: string; path: string; size: number; createdAt: string; url: string }> +``` + +| Parametro | Tipo | Descrizione | +| ---------------------------------- | -------- | ------------------------------------------------------------------------ | +| `fileBuffer` | `Buffer` | Il contenuto grezzo del file | +| `filename` | `string` | Il nome del file (utilizzato per l'archiviazione e la visualizzazione) | +| `contentType` | `string` | Tipo MIME del file (predefinito su `application/octet-stream` se omesso) | +| `fieldMetadataUniversalIdentifier` | `string` | L'`universalIdentifier` del campo di tipo file nel tuo oggetto | + +Punti chiave: + +* Il metodo `uploadFile` è disponibile su `MetadataApiClient` perché la mutazione di upload viene risolta dall'endpoint `/metadata`. +* Usa l'`universalIdentifier` del campo (non il suo ID specifico dello spazio di lavoro), quindi il tuo codice di upload funziona in qualsiasi spazio di lavoro in cui la tua app è installata — coerentemente con il modo in cui le app fanno riferimento ai campi altrove. +* L'`url` restituito è un URL firmato che puoi usare per accedere al file caricato. + +### Esempio Hello World + +Esplora un esempio minimale end-to-end che dimostra oggetti, funzioni logiche, componenti front-end e trigger multipli [qui](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/hello-world). diff --git a/packages/twenty-docs/l/it/developers/extend/apps/getting-started.mdx b/packages/twenty-docs/l/it/developers/extend/apps/getting-started.mdx new file mode 100644 index 0000000000..6c21e093a5 --- /dev/null +++ b/packages/twenty-docs/l/it/developers/extend/apps/getting-started.mdx @@ -0,0 +1,233 @@ +--- +title: Per iniziare +description: Crea la tua prima app Twenty in pochi minuti. +--- + + +Le app sono attualmente in fase alfa. La funzionalità è funzionante ma ancora in evoluzione. + + +Le app ti permettono di estendere Twenty con oggetti, campi, funzioni logiche, competenze IA e componenti UI personalizzati — il tutto gestito come codice. + +**Cosa puoi fare oggi:** + +* Definisci oggetti e campi personalizzati come codice (modello dati gestito) +* Crea funzioni logiche con trigger personalizzati (route HTTP, cron, eventi del database) +* Definisci le abilità per gli agenti IA +* Crea componenti front-end che vengono renderizzati all'interno della UI di Twenty +* Distribuisci la stessa app su più spazi di lavoro + +## Prerequisiti + +* Node.js 24+ e Yarn 4 +* Uno spazio di lavoro Twenty e una chiave API (creane una su https://app.twenty.com/settings/api-webhooks) + +## Per iniziare + +Crea una nuova app utilizzando lo scaffolder ufficiale, quindi autenticati e inizia a sviluppare: + +```bash filename="Terminal" +# Scaffold a new app (includes all examples by default) +npx create-twenty-app@latest my-twenty-app +cd my-twenty-app + +# Start dev mode: automatically syncs local changes to your workspace +yarn twenty app:dev +``` + +Lo strumento di scaffolding supporta due modalità per controllare quali file di esempio vengono inclusi: + +```bash filename="Terminal" +# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item, skill) +npx create-twenty-app@latest my-app + +# Minimal: only core files (application-config.ts and default-role.ts) +npx create-twenty-app@latest my-app --minimal +``` + +Da qui puoi: + +```bash filename="Terminal" +# Add a new entity to your application (guided) +yarn twenty entity:add + +# Watch your application's function logs +yarn twenty function:logs + +# Execute a function by name +yarn twenty function:execute -n my-function -p '{"name": "test"}' + +# Execute the pre-install function +yarn twenty function:execute --preInstall + +# Execute the post-install function +yarn twenty function:execute --postInstall + +# Uninstall the application from the current workspace +yarn twenty app:uninstall + +# Display commands' help +yarn twenty help +``` + +Vedi anche: le pagine di riferimento della CLI per [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) e [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk). + +## Struttura del progetto (generata dallo scaffolder) + +Quando esegui `npx create-twenty-app@latest my-twenty-app`, lo scaffolder: + +* Copia un'applicazione base minimale in `my-twenty-app/` +* Aggiunge una dipendenza locale `twenty-sdk` e la configurazione di Yarn 4 +* Crea file di configurazione e script collegati alla CLI `twenty` +* Genera i file principali (configurazione dell'applicazione, ruolo predefinito per le funzioni logiche, funzioni di pre-installazione e post-installazione) più i file di esempio in base alla modalità di scaffolding + +Un'app appena creata con la modalità predefinita `--exhaustive` si presenta così: + +```text filename="my-twenty-app/" +my-twenty-app/ + package.json + yarn.lock + .gitignore + .nvmrc + .yarnrc.yml + .yarn/ + install-state.gz + .oxlintrc.json + tsconfig.json + README.md + public/ # Public assets folder (images, fonts, etc.) + src/ + ├── application-config.ts # Required - main application configuration + ├── roles/ + │ └── default-role.ts # Default role for logic functions + ├── objects/ + │ └── example-object.ts # Example custom object definition + ├── fields/ + │ └── example-field.ts # Example standalone field definition + ├── logic-functions/ + │ ├── hello-world.ts # Example logic function + │ ├── pre-install.ts # Pre-install logic function + │ └── post-install.ts # Post-install logic function + ├── front-components/ + │ └── hello-world.tsx # Example front component + ├── views/ + │ └── example-view.ts # Example saved view definition + ├── navigation-menu-items/ + │ └── example-navigation-menu-item.ts # Example sidebar navigation link + └── skills/ + └── example-skill.ts # Example AI agent skill definition +``` + +Con `--minimal`, vengono creati solo i file principali (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` e `logic-functions/post-install.ts`). + +A livello generale: + +* **package.json**: Dichiara il nome dell'app, la versione, i motori (Node 24+, Yarn 4) e aggiunge `twenty-sdk` più uno script `twenty` che delega alla CLI locale `twenty`. Esegui `yarn twenty help` per elencare tutti i comandi disponibili. +* **.gitignore**: Ignora i file generati comuni come `node_modules`, `.yarn`, `generated/` (client tipizzato), `dist/`, `build/`, cartelle di coverage, file di log e file `.env*`. +* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Bloccano e configurano la toolchain Yarn 4 utilizzata dal progetto. +* **.nvmrc**: Fissa la versione di Node.js prevista dal progetto. +* **.oxlintrc.json** e **tsconfig.json**: Forniscono linting e configurazione TypeScript per i sorgenti TypeScript della tua app. +* **README.md**: Un breve README nella radice dell'app con istruzioni di base. +* **public/**: Una cartella per archiviare risorse pubbliche (immagini, font, file statici) che saranno servite con la tua applicazione. I file collocati qui vengono caricati durante la sincronizzazione e sono accessibili in fase di esecuzione. +* **src/**: Il luogo principale in cui definisci la tua applicazione come codice + +### Rilevamento delle entità + +L'SDK rileva le entità analizzando i tuoi file TypeScript alla ricerca di chiamate **`export default define({...})`**. Ogni tipo di entità ha una corrispondente funzione helper esportata da `twenty-sdk`: + +| Funzione helper | Tipo di entità | +| -------------------------------- | ------------------------------------------------------------------------------ | +| `defineObject` | Definizioni di oggetti personalizzati | +| `defineLogicFunction` | Definizioni di funzioni logiche | +| `definePreInstallLogicFunction` | Funzione logica di pre-installazione (viene eseguita prima dell'installazione) | +| `definePostInstallLogicFunction` | Funzione logica di post-installazione (viene eseguita dopo l'installazione) | +| `defineFrontComponent` | Definizioni dei componenti front-end | +| `defineRole` | Definizioni di ruoli | +| `defineField` | Estensioni di campo per oggetti esistenti | +| `defineView` | Definizioni di viste salvate | +| `defineNavigationMenuItem` | Definizioni delle voci del menu di navigazione | +| `defineSkill` | Definizioni delle competenze degli agenti IA | + + +**La denominazione dei file è flessibile.** Il rilevamento delle entità è basato sull'AST — l'SDK esegue la scansione dei file sorgente alla ricerca del pattern `export default define({...})`. Puoi organizzare file e cartelle come preferisci. Raggruppare per tipo di entità (ad es., `logic-functions/`, `roles/`) è solo una convenzione per l'organizzazione del codice, non un requisito. + + +Esempio di entità rilevata: + +```typescript +// This file can be named anything and placed anywhere in src/ +import { defineObject, FieldType } from 'twenty-sdk'; + +export default defineObject({ + universalIdentifier: '...', + nameSingular: 'postCard', + // ... rest of config +}); +``` + +Comandi successivi aggiungeranno altri file e cartelle: + +* `yarn twenty app:dev` genererà automaticamente due client API tipizzati in `node_modules/twenty-sdk/generated`: `CoreApiClient` (per i dati dell'area di lavoro tramite `/graphql`) e `MetadataApiClient` (per la configurazione dell'area di lavoro e il caricamento di file tramite `/metadata`). +* `yarn twenty entity:add` aggiungerà file di definizione delle entità sotto `src/` per i tuoi oggetti, funzioni, componenti front-end, ruoli, competenze e altro ancora. + +## Autenticazione + +La prima volta che esegui `yarn twenty auth:login`, ti verranno richiesti: + +* URL dell'API (predefinito a http://localhost:3000 o al profilo dello spazio di lavoro corrente) +* Chiave API + +Le tue credenziali sono archiviate per utente in `~/.twenty/config.json`. Puoi mantenere più profili e passare da uno all'altro. + +### Gestione delle aree di lavoro + +```bash filename="Terminal" +# Login interactively (recommended) +yarn twenty auth:login + +# Login to a specific workspace profile +yarn twenty auth:login --workspace my-custom-workspace + +# List all configured workspaces +yarn twenty auth:list + +# Switch the default workspace (interactive) +yarn twenty auth:switch + +# Switch to a specific workspace +yarn twenty auth:switch production + +# Check current authentication status +yarn twenty auth:status +``` + +Una volta che hai cambiato area di lavoro con `yarn twenty auth:switch`, tutti i comandi successivi utilizzeranno quell'area di lavoro per impostazione predefinita. Puoi comunque sovrascriverla temporaneamente con `--workspace `. + +## Configurazione manuale (senza lo scaffolder) + +Sebbene consigliamo di utilizzare `create-twenty-app` per la migliore esperienza iniziale, puoi anche configurare un progetto manualmente. Non installare la CLI globalmente. Invece, aggiungi `twenty-sdk` come dipendenza locale e collega un unico script nel tuo package.json: + +```bash filename="Terminal" +yarn add -D twenty-sdk +``` + +Quindi aggiungi uno script `twenty`: + +```json filename="package.json" +{ + "scripts": { + "twenty": "twenty" + } +} +``` + +Ora puoi eseguire tutti i comandi tramite `yarn twenty `, ad es. `yarn twenty app:dev`, `yarn twenty help`, ecc. + +## Risoluzione dei problemi + +* Errori di autenticazione: esegui `yarn twenty auth:login` e assicurati che la tua chiave API abbia i permessi richiesti. +* Impossibile connettersi al server: verifica l'URL dell'API e che il server Twenty sia raggiungibile. +* Tipi o client mancanti/obsoleti: riavvia `yarn twenty app:dev` — genera automaticamente il client tipizzato. +* Modalità di sviluppo non sincronizzata: assicurati che `yarn twenty app:dev` sia in esecuzione e che le modifiche non vengano ignorate dal tuo ambiente. + +Canale di supporto su Discord: https://discord.com/channels/1130383047699738754/1130386664812982322 diff --git a/packages/twenty-docs/l/it/developers/extend/apps/publishing.mdx b/packages/twenty-docs/l/it/developers/extend/apps/publishing.mdx new file mode 100644 index 0000000000..9f194c5e84 --- /dev/null +++ b/packages/twenty-docs/l/it/developers/extend/apps/publishing.mdx @@ -0,0 +1,119 @@ +--- +title: Pubblicazione +description: Distribuisci la tua app Twenty nel marketplace oppure distribuiscila internamente. +--- + + +Le app sono attualmente in fase alfa. La funzionalità è funzionante ma ancora in evoluzione. + + +## Panoramica + +Una volta che la tua app è stata [compilata e testata localmente](/l/it/developers/extend/apps/building), hai due modalità per distribuirla: + +* **Pubblica su npm** — elenca la tua app nel marketplace di Twenty affinché qualsiasi spazio di lavoro possa scoprirla e installarla. +* **Esegui il push di un tarball** — distribuisci la tua app su un server Twenty specifico per uso interno senza renderla pubblicamente disponibile. + +## Pubblicazione su npm + +La pubblicazione su npm rende la tua app scopribile nel marketplace di Twenty. Qualsiasi spazio di lavoro Twenty può sfogliare, installare e aggiornare le app del marketplace direttamente dall'interfaccia utente. + +### Requisiti + +* Un account [npm](https://www.npmjs.com) +* Il nome del tuo pacchetto **deve** usare il prefisso `twenty-app-` (es. `twenty-app-postcard-sender`) + +### Passaggi + +1. **Compila la tua app** — la CLI compila i tuoi sorgenti TypeScript e genera il manifest dell'applicazione: + +```bash filename="Terminal" +yarn twenty app:build +``` + +2. **Pubblica su npm** — esegui il push del pacchetto compilato al registro npm: + +```bash filename="Terminal" +npx twenty app:publish +``` + +### Rilevamento automatico + +I pacchetti con il prefisso `twenty-app-` vengono rilevati automaticamente dal catalogo del marketplace di Twenty. Una volta pubblicata, la tua app compare nel marketplace entro pochi minuti — non è richiesta alcuna registrazione o approvazione manuale. + +### Pubblicazione con CI + +Il progetto generato include un workflow di GitHub Actions che pubblica a ogni release. Esegue `app:build`, quindi `npm publish --provenance` dall'output di build: + +```yaml filename=".github/workflows/publish.yml" +name: Publish +on: + release: + types: [published] + +permissions: + contents: read + id-token: write + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "24" + registry-url: https://registry.npmjs.org + - run: yarn install --immutable + - run: npx twenty app:build + - run: npm publish --provenance --access public + working-directory: .twenty/output + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} +``` + +Per altri sistemi CI (GitLab CI, CircleCI, ecc.), si applicano gli stessi tre comandi: `yarn install`, `npx twenty app:build`, quindi `npm publish` da `.twenty/output`. + + +**npm provenance** è opzionale ma consigliata. La pubblicazione con `--provenance` aggiunge un badge di attendibilità alla tua scheda npm, consentendo agli utenti di verificare che il pacchetto sia stato creato a partire da uno specifico commit in una pipeline CI pubblica. Consulta la [documentazione su npm provenance](https://docs.npmjs.com/generating-provenance-statements) per le istruzioni di configurazione. + + +## Distribuzione interna + +Per le app che non vuoi rendere pubbliche — strumenti proprietari, integrazioni solo per l'azienda o build sperimentali — puoi eseguire il push di un tarball direttamente su un server Twenty. + +### Push di un tarball + +Compila la tua app e distribuiscila su un server specifico in un solo passaggio: + +```bash filename="Terminal" +npx twenty app:publish --server +``` + +Qualsiasi spazio di lavoro su quel server può quindi installare e aggiornare l'app dalla pagina delle impostazioni **Applicazioni**. + +### Gestione delle versioni + +Per rilasciare un aggiornamento: + +1. Incrementa il campo `version` nel tuo `package.json` +2. Esegui il push di un nuovo tarball con `npx twenty app:publish --server ` +3. Gli spazi di lavoro su quel server vedranno l'aggiornamento disponibile nelle proprie impostazioni + + +Le app interne sono limitate al server su cui vengono caricate. Non compariranno nel marketplace pubblico e non potranno essere installate dagli spazi di lavoro su altri server. + + +## Categorie di app + +Twenty organizza le app in tre categorie in base a come vengono distribuite: + +| Categoria | Come funziona | Visibile nel marketplace? | +| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | +| **Sviluppo** | App in modalità di sviluppo locale eseguite tramite `yarn twenty app:dev`. Usate per la compilazione e i test. | No | +| **Pubblicata** | App pubblicate su npm con il prefisso `twenty-app-`. Elencate nel marketplace per l'installazione da parte di qualsiasi spazio di lavoro. | Sì | +| **Interna** | App distribuite tramite tarball su un server specifico. Disponibili solo per gli spazi di lavoro su quel server. | No | + + +Inizia in modalità **Sviluppo** mentre crei la tua app. Quando è pronta, scegli **Pubblicata** (npm) per un'ampia distribuzione oppure **Interna** (tarball) per una distribuzione privata. + diff --git a/packages/twenty-docs/l/it/developers/extend/extend.mdx b/packages/twenty-docs/l/it/developers/extend/extend.mdx index 4f1166475d..333f152657 100644 --- a/packages/twenty-docs/l/it/developers/extend/extend.mdx +++ b/packages/twenty-docs/l/it/developers/extend/extend.mdx @@ -1,7 +1,6 @@ --- title: Estendi description: Estendi le funzionalità di Twenty con API, webhook e app personalizzate. -redirect: /developers/introduction --- @@ -16,18 +15,18 @@ Twenty è progettato per essere estensibile. Usa le nostre API, i webhook e il f * **API**: Interroga e modifica i dati del tuo CRM in modo programmatico usando REST o GraphQL * **Webhook**: Ricevi notifiche in tempo reale quando si verificano eventi in Twenty -* **App**: Crea applicazioni personalizzate che estendono le capacità di Twenty - In arrivo! +* **App**: Crea applicazioni personalizzate che estendono le capacità di Twenty ## Per iniziare - + Connettiti a Twenty in modo programmatico - + Ricevi notifiche sugli eventi in tempo reale - - Crea personalizzazioni come codice (Alpha) + + Crea personalizzazioni come codice diff --git a/packages/twenty-docs/l/it/developers/extend/webhooks.mdx b/packages/twenty-docs/l/it/developers/extend/webhooks.mdx new file mode 100644 index 0000000000..bed2ad4010 --- /dev/null +++ b/packages/twenty-docs/l/it/developers/extend/webhooks.mdx @@ -0,0 +1,116 @@ +--- +title: Webhooks +description: Ricevi notifiche in tempo reale quando si verificano eventi nel tuo CRM. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +I webhook inviano dati ai tuoi sistemi in tempo reale quando si verificano eventi in Twenty — senza necessità di polling. Usali per mantenere sincronizzati i sistemi esterni, attivare automazioni o inviare avvisi. + +## Crea un Webhook + +1. Vai a **Impostazioni → API e Webhook → Webhook** +2. Clicca su **+ Crea webhook** +3. Inserisci l'URL del tuo webhook (deve essere pubblicamente accessibile) +4. Clicca su **Salva** + +Il webhook si attiva immediatamente e inizia a inviare notifiche. + + + +### Gestisci Webhook + +**Modifica**: Fai clic sul webhook → Aggiorna URL → **Salva** + +**Elimina**: Fai clic sul webhook → **Elimina** → Conferma + +## Eventi + +Twenty invia webhook per questi tipi di eventi: + +| Evento | Esempio | +| --------------------- | ---------------------------------------------------------- | +| **Record creato** | `person.created`, `company.created`, `note.created` | +| **Record aggiornato** | `person.updated`, `company.updated`, `opportunity.updated` | +| **Record eliminato** | `person.deleted`, `company.deleted` | + +Tutti i tipi di eventi vengono inviati all'URL del tuo webhook. Il filtraggio degli eventi potrebbe essere aggiunto nelle versioni future. + +## Formato del payload + +Ogni webhook invia una richiesta HTTP POST con un corpo JSON: + +```json +{ + "event": "person.created", + "data": { + "id": "abc12345", + "firstName": "Alice", + "lastName": "Doe", + "email": "alice@example.com", + "createdAt": "2025-02-10T15:30:45Z", + "createdBy": "user_123" + }, + "timestamp": "2025-02-10T15:30:50Z" +} +``` + +| Campo | Descrizione | +| ----------- | ---------------------------------------------------------- | +| `event` | Cosa è successo (ad es., `person.created`) | +| `data` | Il record completo che è stato creato/aggiornato/eliminato | +| `timestamp` | Quando si è verificato l'evento (UTC) | + + +Rispondi con uno **status HTTP 2xx** (200-299) per confermare la ricezione. Le risposte non 2xx vengono registrate come errori di consegna. + + +## Convalida del Webhook + +Twenty firma ogni richiesta webhook per motivi di sicurezza. Convalida le firme per assicurarti che le richieste siano autentiche. + +### Intestazioni + +| Intestazione | Descrizione | +| ---------------------------- | ------------------------- | +| `X-Twenty-Webhook-Signature` | Firma HMAC SHA256 | +| `X-Twenty-Webhook-Timestamp` | Timestamp della richiesta | + +### Passaggi di convalida + +1. Ottieni il timestamp da `X-Twenty-Webhook-Timestamp` +2. Crea la stringa: `{timestamp}:{JSON payload}` +3. Calcola HMAC SHA256 usando il segreto del tuo webhook +4. Confronta con `X-Twenty-Webhook-Signature` + +### Esempio (Node.js) + +```javascript +const crypto = require("crypto"); + +const timestamp = req.headers["x-twenty-webhook-timestamp"]; +const payload = JSON.stringify(req.body); +const secret = "your-webhook-secret"; + +const stringToSign = `${timestamp}:${payload}`; +const expectedSignature = crypto + .createHmac("sha256", secret) + .update(stringToSign) + .digest("hex"); + +const receivedSignature = req.headers["x-twenty-webhook-signature"]; +const isValid = crypto.timingSafeEqual( + Buffer.from(expectedSignature, "hex"), + Buffer.from(receivedSignature, "hex") +); +``` + +## Webhooks vs Workflows + +| Metodo | Direzione | Caso d'uso | +| -------------------------------- | --------- | ------------------------------------------------------------------------ | +| **Webhooks** | OUT | Notifica automaticamente ai sistemi esterni qualsiasi modifica ai record | +| **Workflow + HTTP Request** | OUT | Invia dati in uscita con logica personalizzata (filtri, trasformazioni) | +| **Trigger webhook del Workflow** | IN | Ricevi dati in Twenty da sistemi esterni | + +Per la ricezione di dati esterni, vedi [Configura un trigger webhook](/l/it/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger). diff --git a/packages/twenty-docs/l/it/developers/introduction.mdx b/packages/twenty-docs/l/it/developers/introduction.mdx index c8a0e734d8..4c73b89570 100644 --- a/packages/twenty-docs/l/it/developers/introduction.mdx +++ b/packages/twenty-docs/l/it/developers/introduction.mdx @@ -5,28 +5,18 @@ description: Benvenuto nella documentazione per sviluppatori di Twenty, le tue r import { CardTitle } from "/snippets/card-title.mdx" - - - API - Interroga e modifica i dati del tuo CRM con REST o GraphQL. + + + Estendi + Crea integrazioni con API, webhook e app personalizzate. - - Webhooks - Ricevi notifiche in tempo reale quando si verificano eventi. - - - - Apps - Crea applicazioni personalizzate che estendono le capacità di Twenty. - - - + Self-hosting Distribuisci e gestisci Twenty sulla tua infrastruttura. - + Contribuisci Unisciti alla nostra community open source e contribuisci a Twenty. diff --git a/packages/twenty-docs/l/it/user-guide/data-migration/how-tos/export-your-data.mdx b/packages/twenty-docs/l/it/user-guide/data-migration/how-tos/export-your-data.mdx index cf93b4540b..96bd708815 100644 --- a/packages/twenty-docs/l/it/user-guide/data-migration/how-tos/export-your-data.mdx +++ b/packages/twenty-docs/l/it/user-guide/data-migration/how-tos/export-your-data.mdx @@ -24,7 +24,7 @@ Esporta i dati del tuo spazio di lavoro in CSV per backup, reportistica o migraz * Vengono esportate solo le **colonne visibili** * Vengono esportati solo i **record filtrati** (in base alla vista corrente) -Per esportazioni più grandi (oltre 20.000 record), usa i filtri per esportare a lotti oppure usa le [API](/l/it/developers/api). +Per esportazioni più grandi (oltre 20.000 record), usa i filtri per esportare a lotti oppure usa le [API](/l/it/developers/extend/api). ### Permessi @@ -148,7 +148,7 @@ Le API non hanno un limite di record: 2. Usa le API GraphQL per interrogare i record 3. Elabora i risultati nella tua applicazione -Vedi: [Documentazione API](/l/it/developers/api) +Vedi: [Documentazione API](/l/it/developers/extend/api) ## Suggerimenti e buone pratiche @@ -206,4 +206,4 @@ I file esportati possono contenere dati sensibili: * [Come aggiornare i record esistenti](/l/it/user-guide/data-migration/how-tos/update-existing-records-via-import) — modifica e reimporta la tua esportazione * [Come importare i dati tramite API](/l/it/user-guide/data-migration/how-tos/import-data-via-api) — per set di dati di grandi dimensioni -* [Documentazione API](/l/it/developers/api) — crea flussi di lavoro di esportazione personalizzati +* [Documentazione API](/l/it/developers/extend/api) — crea flussi di lavoro di esportazione personalizzati diff --git a/packages/twenty-docs/l/it/user-guide/data-migration/how-tos/import-data-via-api.mdx b/packages/twenty-docs/l/it/user-guide/data-migration/how-tos/import-data-via-api.mdx index 821df86135..fbd8857162 100644 --- a/packages/twenty-docs/l/it/user-guide/data-migration/how-tos/import-data-via-api.mdx +++ b/packages/twenty-docs/l/it/user-guide/data-migration/how-tos/import-data-via-api.mdx @@ -57,10 +57,10 @@ Chiunque abbia la tua chiave API può accedere ai dati del tuo spazio di lavoro Twenty supporta due tipi di API: -| API | Ideale per | Documentazione | -| ----------- | ------------------------------------------------------------------ | ---------------------------------------------------------- | -| **GraphQL** | Query flessibili, recupero di dati correlati, operazioni complesse | [Documentazione API](/l/it/developers/api) | -| **REST** | Operazioni CRUD semplici, pattern REST familiari | [Documentazione API](/l/it/developers/api) | +| API | Ideale per | Documentazione | +| ----------- | ------------------------------------------------------------------ | -------------------------------------------- | +| **GraphQL** | Query flessibili, recupero di dati correlati, operazioni complesse | [Documentazione API](/l/it/developers/extend/api) | +| **REST** | Operazioni CRUD semplici, pattern REST familiari | [Documentazione API](/l/it/developers/extend/api) | Entrambe le API supportano: @@ -173,4 +173,4 @@ Contattaci a [contact@twenty.com](mailto:contact@twenty.com) oppure scopri i nos Per i dettagli completi di implementazione, esempi di codice e riferimento allo schema: -* [Documentazione API](/l/it/developers/api) +* [Documentazione API](/l/it/developers/extend/api) diff --git a/packages/twenty-docs/l/it/user-guide/getting-started/capabilities/what-is-twenty.mdx b/packages/twenty-docs/l/it/user-guide/getting-started/capabilities/what-is-twenty.mdx index c8625dcaf0..f5d9519246 100644 --- a/packages/twenty-docs/l/it/user-guide/getting-started/capabilities/what-is-twenty.mdx +++ b/packages/twenty-docs/l/it/user-guide/getting-started/capabilities/what-is-twenty.mdx @@ -35,7 +35,7 @@ L'open-source è la base del nostro approccio, garantendo che Twenty evolva con * **Dashboard:** Monitora le prestazioni con report e visualizzazioni personalizzati. [Visualizza le dashboard](/l/it/user-guide/dashboards/overview). * **Autorizzazioni e accesso:** Controlla chi può visualizzare, modificare e gestire i tuoi dati con autorizzazioni basate sui ruoli. [Configura l'accesso](/l/it/user-guide/permissions-access/overview). * **Note e attività:** Crea note e attività collegate ai tuoi record per una collaborazione migliore. -* **API e Webhooks:** Connettiti ad altre app e crea integrazioni personalizzate. [Inizia a integrare](/l/it/developers/api). +* **API e Webhooks:** Connettiti ad altre app e crea integrazioni personalizzate. [Inizia a integrare](/l/it/developers/extend/api). ## Unisciti ora diff --git a/packages/twenty-docs/l/it/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx b/packages/twenty-docs/l/it/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx index 1b8c46a699..7bd47a6d73 100644 --- a/packages/twenty-docs/l/it/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx +++ b/packages/twenty-docs/l/it/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx @@ -95,7 +95,7 @@ Crea i campi di destinazione in **Impostazioni → Modello dati → Opportunità * Dimensione aziendale: `{{searchRecords[0].employees}}` -**Limitazione di Attività e Note**: Le relazioni su Attività e Note sono codificate come molte-a-molte e non sono ancora disponibili nei trigger o nelle azioni dei flussi di lavoro. Per accedere a queste relazioni, usa invece le [API](/l/it/developers/api). +**Limitazione di Attività e Note**: Le relazioni su Attività e Note sono codificate come molte-a-molte e non sono ancora disponibili nei trigger o nelle azioni dei flussi di lavoro. Per accedere a queste relazioni, usa invece le [API](/l/it/developers/extend/api). ## Sincronizzazione bidirezionale diff --git a/packages/twenty-docs/l/pt/developers/contribute/capabilities/frontend-development/frontend-commands.mdx b/packages/twenty-docs/l/pt/developers/contribute/capabilities/frontend-development/frontend-commands.mdx index 31c274ae2b..9743a94c47 100644 --- a/packages/twenty-docs/l/pt/developers/contribute/capabilities/frontend-development/frontend-commands.mdx +++ b/packages/twenty-docs/l/pt/developers/contribute/capabilities/frontend-development/frontend-commands.mdx @@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/pt/developers/contribute/capabilities/front ### Gerenciamento de Estado -[Jotai](https://jotai.org/) gerencia o estado. +[Jotai](https://jotai.org/) handles state management. Veja [melhores práticas](/l/pt/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) para mais informações sobre gerenciamento de estado. diff --git a/packages/twenty-docs/l/pt/developers/extend/api.mdx b/packages/twenty-docs/l/pt/developers/extend/api.mdx new file mode 100644 index 0000000000..6764200946 --- /dev/null +++ b/packages/twenty-docs/l/pt/developers/extend/api.mdx @@ -0,0 +1,147 @@ +--- +title: APIs +description: Consulte e modifique seus dados de CRM programaticamente usando REST ou GraphQL. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +O Twenty foi desenvolvido para ser amigável ao desenvolvedor, oferecendo APIs poderosas que se adaptam ao seu modelo de dados personalizado. Oferecemos quatro tipos distintos de API para atender diferentes necessidades de integração. + +## Abordagem Focada no Desenvolvedor + +Twenty gera APIs especificamente para o seu modelo de dados: + +* **Nenhum ID longo necessário**: Use os nomes dos seus objetos e campos diretamente nos endpoints +* **Objetos padrão e personalizados tratados igualmente**: Seus objetos personalizados recebem o mesmo tratamento de API que os incorporados +* **Endpoints dedicados**: Cada objeto e campo tem seu próprio endpoint de API +* **Documentação personalizada**: Gerada especificamente para o modelo de dados do seu workspace + + +Sua documentação de API personalizada fica disponível em **Configurações → API & Webhooks** após criar uma chave de API. Como o Twenty gera APIs que correspondem ao seu modelo de dados personalizado, a documentação é exclusiva do seu workspace. + + +## Os dois tipos de API + +### Core API + +Acessada em `/rest/` ou `/graphql/` + +Trabalhe com seus **registros** (os dados): + +* Criar, ler, atualizar e excluir Pessoas, Empresas, Oportunidades, etc. +* Consultar e filtrar dados +* Gerenciar relações de registros + +### Metadata API + +Acessada em `/rest/metadata/` ou `/metadata/` + +Gerencie seu **workspace e modelo de dados**: + +* Criar, modificar ou excluir objetos e campos +* Configurar as configurações do workspace +* Defina relacionamentos entre objetos + +## REST vs GraphQL + +As APIs Core e Metadata estão disponíveis nos formatos REST e GraphQL: + +| Formato | Operações disponíveis | +| ----------- | --------------------------------------------------------------------------------- | +| **REST** | CRUD, operações em lote, upserts | +| **GraphQL** | Os mesmos + **upserts em lote**, consultas de relacionamento em uma única chamada | + +Escolha com base nas suas necessidades — ambos os formatos acessam os mesmos dados. + +## Endpoints de API + +| Ambiente | URL base | +| ------------------ | ------------------------- | +| **Nuvem** | `https://api.twenty.com/` | +| **Auto-hospedado** | `https://{your-domain}/` | + +## Autenticação + +Toda solicitação de API requer uma chave de API no cabeçalho: + +``` +Authorization: Bearer YOUR_API_KEY +``` + +### Criar uma Chave de API + +1. Vá para **Configurações → APIs & Webhooks** +2. Clique em **+ Criar chave** +3. Configurar: + * **Nome**: Nome descritivo para a chave + * **Data de expiração**: Quando a chave expira +4. Clique em **Salvar** +5. **Copie imediatamente** — a chave é exibida apenas uma vez + + + + +Sua chave de API concede acesso a dados confidenciais. Não a compartilhe com serviços não confiáveis. Se for comprometida, desative-a imediatamente e gere uma nova. + + +### Atribuir uma função a uma chave de API + +Para maior segurança, atribua uma função específica para limitar o acesso: + +1. Vá para **Configurações → Funções** +2. Clique na função que deseja atribuir +3. Abra a aba de **Atribuição** +4. Em **Chaves de API**, clique em **+ Atribuir à chave de API** +5. Selecione a chave de API + +A chave herdará as permissões dessa função. Veja [Permissões](/l/pt/user-guide/permissions-access/capabilities/permissions) para obter detalhes. + +### Gerenciar Chaves de API + +**Regenerar**: Configurações → APIs & Webhooks → Clique na chave → **Regenerar** + +**Excluir**: Configurações → APIs & Webhooks → Clique na chave → **Excluir** + +## Playground de API + +Teste suas APIs diretamente no navegador com nosso playground integrado — disponível tanto para **REST** quanto para **GraphQL**. + +### Acesse o Playground + +1. Vá para **Configurações → APIs & Webhooks** +2. Crie uma chave de API (obrigatório) +3. Clique em **REST API** ou **GraphQL API** para abrir o playground + +### O que você obtém + +* **Documentação interativa**: Gerada para o seu modelo de dados específico +* **Testes ao vivo**: Execute chamadas de API reais no seu workspace +* **Explorador de esquema**: Navegue pelos objetos, campos e relacionamentos disponíveis +* **Construtor de solicitações**: Construa consultas com preenchimento automático + +O playground reflete seus objetos e campos personalizados, portanto, a documentação está sempre precisa para o seu workspace. + +## Operações em Lote + +Tanto REST quanto GraphQL suportam operações em lote: + +* **Tamanho do lote**: Até 60 registros por requisição +* **Operações**: Criar, atualizar e excluir vários registros + +**Recursos exclusivos do GraphQL:** + +* **Upsert em lote**: Criar ou atualizar em uma única chamada +* Use nomes de objetos no plural (por exemplo, `CreateCompanies` em vez de `CreateCompany`) + +## Limites de taxa + +As solicitações de API são limitadas para garantir a estabilidade da plataforma: + +| Limite | Valor | +| ------------------- | ------------------------ | +| **Solicitações** | 100 chamadas por minuto | +| **Tamanho do lote** | 60 registros por chamada | + + +Use operações em lote para maximizar a taxa de transferência — processe até 60 registros em uma única chamada de API em vez de fazer solicitações individuais. + diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/building.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/building.mdx new file mode 100644 index 0000000000..8d312c23e7 --- /dev/null +++ b/packages/twenty-docs/l/pt/developers/extend/apps/building.mdx @@ -0,0 +1,689 @@ +--- +title: Criando aplicativos +description: Defina objetos, funções de lógica, componentes de front-end e muito mais com o SDK da Twenty. +--- + + +Os aplicativos estão atualmente em testes alfa. O recurso é funcional, mas ainda está evoluindo. + + +## Use os recursos do SDK (tipos e configuração) + +O twenty-sdk fornece blocos de construção tipados e funções utilitárias que você usa dentro do seu aplicativo. A seguir estão as partes principais que você usará com mais frequência. + +### Funções utilitárias + +O SDK fornece funções utilitárias para definir as entidades do seu app. Conforme descrito em [Detecção de entidades](/l/pt/developers/extend/apps/getting-started#entity-detection), você deve usar `export default define({...})` para que suas entidades sejam detectadas: + +| Função | Finalidade | +| -------------------------------- | ------------------------------------------------------------------ | +| `defineApplication` | Configurar metadados do aplicativo (obrigatório, um por app) | +| `defineObject` | Define objetos personalizados com campos | +| `defineLogicFunction` | Defina funções de lógica com handlers | +| `definePreInstallLogicFunction` | Defina uma função de lógica de pré-instalação (uma por aplicativo) | +| `definePostInstallLogicFunction` | Defina uma função de lógica de pós-instalação (uma por aplicativo) | +| `defineFrontComponent` | Definir componentes de front-end para UI personalizada | +| `defineRole` | Configura permissões de papéis e acesso a objetos | +| `defineField` | Estender objetos existentes com campos adicionais | +| `defineView` | Define visualizações salvas para objetos | +| `defineNavigationMenuItem` | Define links de navegação da barra lateral | +| `defineSkill` | Define habilidades de agente de IA | + +Essas funções validam sua configuração em tempo de compilação e oferecem autocompletar na IDE e segurança de tipos. + +### Definindo objetos + +Objetos personalizados descrevem tanto o esquema quanto o comportamento de registros no seu espaço de trabalho. Use `defineObject()` para definir objetos com validação integrada: + +```typescript +// src/app/postCard.object.ts +import { defineObject, FieldType } from 'twenty-sdk'; + +enum PostCardStatus { + DRAFT = 'DRAFT', + SENT = 'SENT', + DELIVERED = 'DELIVERED', + RETURNED = 'RETURNED', +} + +export default defineObject({ + universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05', + nameSingular: 'postCard', + namePlural: 'postCards', + labelSingular: 'Post Card', + labelPlural: 'Post Cards', + description: 'A post card object', + icon: 'IconMail', + fields: [ + { + universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b', + name: 'content', + type: FieldType.TEXT, + label: 'Content', + description: "Postcard's content", + icon: 'IconAbc', + }, + { + universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac', + name: 'recipientName', + type: FieldType.FULL_NAME, + label: 'Recipient name', + icon: 'IconUser', + }, + { + universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266', + name: 'recipientAddress', + type: FieldType.ADDRESS, + label: 'Recipient address', + icon: 'IconHome', + }, + { + universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e', + name: 'status', + type: FieldType.SELECT, + label: 'Status', + icon: 'IconSend', + defaultValue: `'${PostCardStatus.DRAFT}'`, + options: [ + { value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' }, + { value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' }, + { value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' }, + { value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' }, + ], + }, + { + universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433', + name: 'deliveredAt', + type: FieldType.DATE_TIME, + label: 'Delivered at', + icon: 'IconCheck', + isNullable: true, + defaultValue: null, + }, + ], +}); +``` + +Pontos-chave: + +* Use `defineObject()` para validação integrada e melhor suporte na IDE. +* O `universalIdentifier` deve ser exclusivo e estável entre implantações. +* Cada campo requer `name`, `type`, `label` e seu próprio `universalIdentifier` estável. +* O array `fields` é opcional — você pode definir objetos sem campos personalizados. +* Você pode criar novos objetos usando `yarn twenty entity:add`, que orienta você sobre nomeação, campos e relacionamentos. + + +**Os campos base são criados automaticamente.** Quando você define um objeto personalizado, o Twenty adiciona automaticamente campos padrão +como `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` e `deletedAt`. +Você não precisa definir esses no seu array `fields` — adicione apenas seus campos personalizados. +Você pode substituir os campos padrão definindo um campo com o mesmo nome no seu array `fields`, +mas isso não é recomendado. + + +### Configuração do aplicativo (application-config.ts) + +Todo aplicativo tem um único arquivo `application-config.ts` que descreve: + +* **O que é o aplicativo**: identificadores, nome de exibição e descrição. +* **Como suas funções são executadas**: qual papel usam para permissões. +* **Variáveis (opcional)**: pares chave–valor expostos às suas funções como variáveis de ambiente. +* **(Opcional) função de pré-instalação**: uma função de lógica que é executada antes da instalação do aplicativo. +* **(Opcional) função de pós-instalação**: uma função de lógica que é executada após a instalação do aplicativo. + +Use `defineApplication()` para definir a configuração do seu aplicativo: + +```typescript +// src/application-config.ts +import { defineApplication } from 'twenty-sdk'; +import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role'; + +export default defineApplication({ + universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7', + displayName: 'My Twenty App', + description: 'My first Twenty app', + icon: 'IconWorld', + applicationVariables: { + DEFAULT_RECIPIENT_NAME: { + universalIdentifier: '19e94e59-d4fe-4251-8981-b96d0a9f74de', + description: 'Default recipient name for postcards', + value: 'Jane Doe', + isSecret: false, + }, + }, + defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, +}); +``` + +Notas: + +* `universalIdentifier` são IDs determinísticos que você controla; gere-os uma vez e mantenha-os estáveis entre sincronizações. +* `applicationVariables` tornam-se variáveis de ambiente para suas funções (por exemplo, `DEFAULT_RECIPIENT_NAME` fica disponível como `process.env.DEFAULT_RECIPIENT_NAME`). +* `defaultRoleUniversalIdentifier` deve corresponder ao arquivo do papel (veja abaixo). +* As funções de pré-instalação e pós-instalação são detectadas automaticamente durante a geração do manifesto. Consulte [Funções de pré-instalação](#pre-install-functions) e [Funções de pós-instalação](#post-install-functions). + +#### Papéis e permissões + +Os aplicativos podem definir papéis que encapsulam permissões sobre os objetos e ações do seu espaço de trabalho. O campo `defaultRoleUniversalIdentifier` em `application-config.ts` designa o papel padrão usado pelas funções de lógica do seu app. + +* A chave de API em tempo de execução, injetada como `TWENTY_API_KEY`, é derivada desse papel padrão de função. +* O cliente tipado ficará restrito às permissões concedidas a esse papel. +* Siga o princípio do menor privilégio: crie um papel dedicado com apenas as permissões de que suas funções precisam e, em seguida, faça referência ao seu identificador universal. + +##### Papel de função padrão (*.role.ts) + +Ao criar um novo aplicativo com o scaffold, a CLI também cria um arquivo de papel padrão. Use `defineRole()` para definir papéis com validação integrada: + +```typescript +// src/roles/default-role.ts +import { defineRole, PermissionFlag } from 'twenty-sdk'; + +export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = + 'b648f87b-1d26-4961-b974-0908fd991061'; + +export default defineRole({ + universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, + label: 'Default function role', + description: 'Default role for function Twenty client', + canReadAllObjectRecords: false, + canUpdateAllObjectRecords: false, + canSoftDeleteAllObjectRecords: false, + canDestroyAllObjectRecords: false, + canUpdateAllSettings: false, + canBeAssignedToAgents: false, + canBeAssignedToUsers: false, + canBeAssignedToApiKeys: false, + objectPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + canReadObjectRecords: true, + canUpdateObjectRecords: true, + canSoftDeleteObjectRecords: false, + canDestroyObjectRecords: false, + }, + ], + fieldPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + fieldUniversalIdentifier: 'b2c37dc0-8ae7-470e-96cd-1476b47dfaff', + canReadFieldValue: false, + canUpdateFieldValue: false, + }, + ], + permissionFlags: [PermissionFlag.APPLICATIONS], +}); +``` + +O `universalIdentifier` desse papel é então referenciado em `application-config.ts` como `defaultRoleUniversalIdentifier`. Em outras palavras: + +* **\*.role.ts** define o que o papel de função padrão pode fazer. +* **application-config.ts** aponta para esse papel para que suas funções herdem suas permissões. + +Notas: + +* Comece pelo papel gerado pelo scaffold e depois restrinja-o progressivamente seguindo o princípio do menor privilégio. +* Substitua `objectPermissions` e `fieldPermissions` pelos objetos/campos de que suas funções precisam. +* `permissionFlags` controlam o acesso a recursos em nível de plataforma. Mantenha-os mínimos; adicione apenas o que for necessário. +* Veja um exemplo funcional no app Hello World: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). + +### Configuração de função de lógica e ponto de entrada + +Cada arquivo de função usa `defineLogicFunction()` para exportar uma configuração com um handler e gatilhos opcionais. + +```typescript +// src/app/createPostCard.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk'; +import { CoreApiClient, type Person } from 'twenty-sdk/generated'; + +const handler = async (params: RoutePayload) => { + const client = new CoreApiClient(); + const name = 'name' in params.queryStringParameters + ? params.queryStringParameters.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world' + : 'Hello world'; + + const result = await client.mutation({ + createPostCard: { + __args: { data: { name } }, + id: true, + name: true, + }, + }); + return result; +}; + +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'create-new-post-card', + timeoutSeconds: 2, + handler, + triggers: [ + // Public HTTP route trigger '/s/post-card/create' + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/post-card/create', + httpMethod: 'GET', + isAuthRequired: false, + }, + // Cron trigger (CRON pattern) + // { + // universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2', + // type: 'cron', + // pattern: '0 0 1 1 *', + // }, + // Database event trigger + // { + // universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156', + // type: 'databaseEvent', + // eventName: 'person.updated', + // updatedFields: ['name'], + // }, + ], +}); +``` + +Tipos de gatilho comuns: + +* **route**: Expõe sua função em um caminho e método HTTP **no endpoint `/s/`**: + +> por exemplo, `path: '/post-card/create',` -> chamar em `/s/post-card/create` + +* **cron**: Executa sua função em um agendamento usando uma expressão CRON. +* **databaseEvent**: Executa em eventos do ciclo de vida de objetos do espaço de trabalho. Quando a operação do evento é `updated`, campos específicos a serem observados podem ser especificados no array `updatedFields`. Se deixar indefinido ou vazio, qualquer atualização acionará a função. + +> por exemplo, `person.updated` + +Notas: + +* O array `triggers` é opcional. Funções sem gatilhos podem ser usadas como funções utilitárias chamadas por outras funções. +* Você pode misturar vários tipos de gatilho em uma única função. + +### Funções de pré-instalação + +Uma função de pré-instalação é uma função de lógica que é executada automaticamente antes de o seu aplicativo ser instalado em um espaço de trabalho. Isso é útil para tarefas de validação, verificações de pré-requisitos ou para preparar o estado do espaço de trabalho antes que a instalação principal prossiga. + +Ao criar a estrutura de um novo app com `create-twenty-app`, uma função de pré-instalação é gerada para você em `src/logic-functions/pre-install.ts`: + +```typescript +// src/logic-functions/pre-install.ts +import { definePreInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Pre install logic function executed successfully!', payload.previousVersion); +}; + +export default definePreInstallLogicFunction({ + universalIdentifier: '', + name: 'pre-install', + description: 'Runs before installation to prepare the application.', + timeoutSeconds: 300, + handler, +}); +``` + +Você também pode executar manualmente a função de pré-instalação a qualquer momento usando a CLI: + +```bash filename="Terminal" +yarn twenty function:execute --preInstall +``` + +Pontos-chave: + +* As funções de pré-instalação usam `definePreInstallLogicFunction()` — uma variante especializada que omite as configurações de gatilho (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`). +* O manipulador recebe um `InstallLogicFunctionPayload` com `{ previousVersion: string }` — a versão do app que foi instalada anteriormente (ou uma string vazia para instalações novas). +* É permitida apenas uma função de pré-instalação por app. A geração do manifesto apresentará erro se mais de uma for detectada. +* O `universalIdentifier` da função é definido automaticamente como `preInstallLogicFunctionUniversalIdentifier` no manifesto do aplicativo durante a geração — você não precisa referenciá-lo em `defineApplication()`. +* O tempo limite padrão é definido como 300 segundos (5 minutos) para permitir tarefas de preparação mais longas. +* As funções de pré-instalação não precisam de gatilhos — elas são invocadas pela plataforma antes da instalação ou manualmente via `function:execute --preInstall`. + +### Funções de pós-instalação + +Uma função de pós-instalação é uma função de lógica que é executada automaticamente após o seu aplicativo ser instalado em um espaço de trabalho. Isso é útil para tarefas de configuração únicas, como preencher dados padrão, criar registros iniciais ou configurar as configurações do espaço de trabalho. + +Ao criar a estrutura de um novo app com `create-twenty-app`, uma função de pós-instalação é gerada para você em `src/logic-functions/post-install.ts`: + +```typescript +// src/logic-functions/post-install.ts +import { definePostInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Post install logic function executed successfully!', payload.previousVersion); +}; + +export default definePostInstallLogicFunction({ + universalIdentifier: '', + name: 'post-install', + description: 'Runs after installation to set up the application.', + timeoutSeconds: 300, + handler, +}); +``` + +Você também pode executar manualmente a função de pós-instalação a qualquer momento usando a CLI: + +```bash filename="Terminal" +yarn twenty function:execute --postInstall +``` + +Pontos-chave: + +* As funções de pós-instalação usam `definePostInstallLogicFunction()` — uma variante especializada que omite as configurações de gatilho (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`). +* O manipulador recebe um `InstallLogicFunctionPayload` com `{ previousVersion: string }` — a versão do app que foi instalada anteriormente (ou uma string vazia para instalações novas). +* É permitida apenas uma função de pós-instalação por app. A geração do manifesto apresentará erro se mais de uma for detectada. +* O `universalIdentifier` da função é definido automaticamente como `postInstallLogicFunctionUniversalIdentifier` no manifesto do aplicativo durante a geração — você não precisa referenciá-lo em `defineApplication()`. +* O tempo limite padrão é definido como 300 segundos (5 minutos) para permitir tarefas de configuração mais longas, como o pré-carregamento de dados. +* As funções de pós-instalação não precisam de gatilhos — elas são invocadas pela plataforma durante a instalação ou manualmente via `function:execute --postInstall`. + +### Payload de gatilho de rota + + +**Alteração incompatível (v1.16, janeiro de 2026):** O formato do payload de gatilho de rota mudou. Antes da v1.16, os parâmetros de consulta, parâmetros de caminho e corpo eram enviados diretamente como o payload. A partir da v1.16, eles ficam aninhados dentro de um objeto estruturado `RoutePayload`. + +**Antes da v1.16:** +```typescript +const handler = async (params) => { + const { param1, param2 } = params; // Direct access +}; +``` + +**Depois da v1.16:** +```typescript +const handler = async (event: RoutePayload) => { + const { param1, param2 } = event.body; // Access via .body + const { queryParam } = event.queryStringParameters; + const { id } = event.pathParameters; +}; +``` + +**Para migrar funções existentes:** Atualize seu handler para desestruturar de `event.body`, `event.queryStringParameters` ou `event.pathParameters` em vez de diretamente do objeto de parâmetros. + + +Quando um gatilho de rota invoca sua função de lógica, ela recebe um objeto `RoutePayload` que segue o formato do AWS HTTP API v2. Importe o tipo de `twenty-sdk`: + +```typescript +import { defineLogicFunction, type RoutePayload } from 'twenty-sdk'; + +const handler = async (event: RoutePayload) => { + // Access request data + const { headers, queryStringParameters, pathParameters, body } = event; + + // HTTP method and path are available in requestContext + const { method, path } = event.requestContext.http; + + return { message: 'Success' }; +}; +``` + +O tipo `RoutePayload` tem a seguinte estrutura: + +| Propriedade | Tipo | Descrição | +| ---------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `headers` | `Record` | Cabeçalhos HTTP (apenas aqueles listados em `forwardedRequestHeaders`) | +| `queryStringParameters` | `Record` | Parâmetros de query string (valores múltiplos unidos por vírgulas) | +| `pathParameters` | `Record` | Parâmetros de caminho extraídos do padrão de rota (por exemplo, `/users/:id` → `{ id: '123' }`) | +| `body` | `object \| null` | Corpo da requisição analisado (JSON) | +| `isBase64Encoded` | `boolean` | Se o corpo está codificado em base64 | +| `requestContext.http.method` | `string` | Método HTTP (GET, POST, PUT, PATCH, DELETE) | +| `requestContext.http.path` | `string` | Caminho bruto da requisição | + +### Encaminhamento de cabeçalhos HTTP + +Por padrão, os cabeçalhos HTTP das requisições recebidas **não** são repassados para sua função de lógica por motivos de segurança. Para acessar cabeçalhos específicos, liste-os explicitamente no array `forwardedRequestHeaders`: + +```typescript +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'webhook-handler', + handler, + triggers: [ + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/webhook', + httpMethod: 'POST', + isAuthRequired: false, + forwardedRequestHeaders: ['x-webhook-signature', 'content-type'], + }, + ], +}); +``` + +No seu handler, você pode então acessar esses cabeçalhos: + +```typescript +const handler = async (event: RoutePayload) => { + const signature = event.headers['x-webhook-signature']; + const contentType = event.headers['content-type']; + + // Validate webhook signature... + return { received: true }; +}; +``` + + + Os nomes dos cabeçalhos são normalizados para minúsculas. Acesse-os usando chaves em minúsculas (por exemplo, `event.headers['content-type']`). + + +Você pode criar novas funções de duas formas: + +* **Gerado automaticamente**: Execute `yarn twenty entity:add` e escolha a opção para adicionar uma nova função de lógica. Isso gera um arquivo inicial com um handler e configuração. +* **Manual**: Crie um novo arquivo `*.logic-function.ts` e use `defineLogicFunction()`, seguindo o mesmo padrão. + +### Marcar uma função lógica como ferramenta + +Funções lógicas podem ser expostas como **ferramentas** para agentes de IA e fluxos de trabalho. Quando uma função é marcada como ferramenta, ela fica disponível para os recursos de IA do Twenty e pode ser selecionada como uma etapa em automações de fluxos de trabalho. + +Para marcar uma função lógica como ferramenta, defina `isTool: true` e forneça um `toolInputSchema` descrevendo os parâmetros de entrada esperados usando [JSON Schema](https://json-schema.org/): + +```typescript +// src/logic-functions/enrich-company.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import { CoreApiClient } from 'twenty-sdk/generated'; + +const handler = async (params: { companyName: string; domain?: string }) => { + const client = new CoreApiClient(); + + const result = await client.mutation({ + createTask: { + __args: { + data: { + title: `Enrich data for ${params.companyName}`, + body: `Domain: ${params.domain ?? 'unknown'}`, + }, + }, + id: true, + }, + }); + + return { taskId: result.createTask.id }; +}; + +export default defineLogicFunction({ + universalIdentifier: 'f47ac10b-58cc-4372-a567-0e02b2c3d479', + name: 'enrich-company', + description: 'Enrich a company record with external data', + timeoutSeconds: 10, + handler, + isTool: true, + toolInputSchema: { + type: 'object', + properties: { + companyName: { + type: 'string', + description: 'The name of the company to enrich', + }, + domain: { + type: 'string', + description: 'The company website domain (optional)', + }, + }, + required: ['companyName'], + }, +}); +``` + +Pontos-chave: + +* **`isTool`** (`boolean`, padrão: `false`): Quando definido como `true`, a função é registrada como uma ferramenta e fica disponível para agentes de IA e automações de fluxos de trabalho. +* **`toolInputSchema`** (`object`, opcional): Um objeto JSON Schema que descreve os parâmetros que sua função aceita. Os agentes de IA usam esse esquema para entender quais entradas a ferramenta espera e para validar as chamadas. Se omitido, o esquema tem como padrão `{ type: 'object', properties: {} }` (sem parâmetros). +* Funções com `isTool: false` (ou não definido) **não** são expostas como ferramentas. Elas ainda podem ser executadas diretamente ou chamadas por outras funções, mas não aparecerão na descoberta de ferramentas. +* **Nomenclatura de ferramentas**: Quando exposta como uma ferramenta, o nome da função é automaticamente normalizado para `logic_function_` (em minúsculas, caracteres não alfanuméricos substituídos por sublinhados). Por exemplo, `enrich-company` torna-se `logic_function_enrich_company`. +* Você pode combinar `isTool` com gatilhos — uma função pode ser ao mesmo tempo uma ferramenta (chamável por agentes de IA) e acionada por eventos (cron, eventos de banco de dados, rotas) simultaneamente. + + +**Escreva uma boa `description`.** Os agentes de IA dependem do campo `description` da função para decidir quando usar a ferramenta. Seja específico sobre o que a ferramenta faz e quando ela deve ser chamada. + + +### Componentes de front-end + +Componentes de front-end permitem criar componentes React personalizados que são renderizados na UI do Twenty. Use `defineFrontComponent()` para definir componentes com validação integrada: + +```typescript +// src/front-components/my-widget.tsx +import { defineFrontComponent } from 'twenty-sdk'; + +const MyWidget = () => { + return ( +
+

My Custom Widget

+

This is a custom front component for Twenty.

+
+ ); +}; + +export default defineFrontComponent({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'my-widget', + description: 'A custom widget component', + component: MyWidget, +}); +``` + +Pontos-chave: + +* Componentes de front-end são componentes React que renderizam em contextos isolados dentro do Twenty. +* O campo `component` faz referência ao seu componente React. +* Os componentes são compilados e sincronizados automaticamente durante `yarn twenty app:dev`. + +Você pode criar novos componentes de front-end de duas formas: + +* **Gerado automaticamente**: Execute `yarn twenty entity:add` e escolha a opção para adicionar um novo componente de front-end. +* **Manual**: Crie um novo arquivo `.tsx` e use `defineFrontComponent()`, seguindo o mesmo padrão. + +### Habilidades + +As habilidades definem instruções e capacidades reutilizáveis que os agentes de IA podem usar no seu espaço de trabalho. Use `defineSkill()` para definir habilidades com validação integrada: + +```typescript +// src/skills/example-skill.ts +import { defineSkill } from 'twenty-sdk'; + +export default defineSkill({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'sales-outreach', + label: 'Sales Outreach', + description: 'Guides the AI agent through a structured sales outreach process', + icon: 'IconBrain', + content: `You are a sales outreach assistant. When reaching out to a prospect: +1. Research the company and recent news +2. Identify the prospect's role and likely pain points +3. Draft a personalized message referencing specific details +4. Keep the tone professional but conversational`, +}); +``` + +Pontos-chave: + +* `name` é uma string de identificador exclusivo para a habilidade (recomenda-se kebab-case). +* `label` é o nome de exibição legível por humanos mostrado na UI. +* `content` contém as instruções da habilidade — este é o texto que o agente de IA usa. +* `icon` (opcional) define o ícone exibido na UI. +* `description` (opcional) fornece contexto adicional sobre a finalidade da habilidade. + +Você pode criar novas habilidades de duas formas: + +* **Gerado automaticamente**: Execute `yarn twenty entity:add` e escolha a opção para adicionar uma nova habilidade. +* **Manual**: Crie um novo arquivo e use `defineSkill()`, seguindo o mesmo padrão. + +### Clientes tipados gerados + +Dois clientes tipados são gerados automaticamente pelo `yarn twenty app:dev` e armazenados em `node_modules/twenty-sdk/generated` com base no esquema do seu espaço de trabalho: + +* **`CoreApiClient`** — consulta o endpoint `/graphql` para dados do espaço de trabalho +* **`MetadataApiClient`** — consulta o endpoint `/metadata` para obter a configuração do espaço de trabalho e o carregamento de arquivos + +```typescript +import { CoreApiClient, MetadataApiClient } from 'twenty-sdk/generated'; + +const client = new CoreApiClient(); +const { me } = await client.query({ me: { id: true, displayName: true } }); + +const metadataClient = new MetadataApiClient(); +const { currentWorkspace } = await metadataClient.query({ currentWorkspace: { id: true } }); +``` + +Ambos os clientes são regenerados automaticamente pelo `yarn twenty app:dev` sempre que seus objetos ou campos forem alterados. + +#### Credenciais em tempo de execução em funções de lógica + +Quando sua função é executada no Twenty, a plataforma injeta credenciais como variáveis de ambiente antes da execução do seu código: + +* `TWENTY_API_URL`: URL base da API do Twenty que seu aplicativo usa como alvo. +* `TWENTY_API_KEY`: Chave de curta duração com escopo para o papel de função padrão do seu aplicativo. + +Notas: + +* Você não precisa passar a URL ou a chave de API para o cliente gerado. Ele lê `TWENTY_API_URL` e `TWENTY_API_KEY` de process.env em tempo de execução. +* As permissões da chave de API são determinadas pelo papel referenciado no seu `application-config.ts` via `defaultRoleUniversalIdentifier`. Este é o papel padrão usado pelas funções de lógica do seu app. +* Os aplicativos podem definir papéis para seguir o princípio do menor privilégio. Conceda apenas as permissões de que suas funções precisam e, em seguida, aponte `defaultRoleUniversalIdentifier` para o identificador universal desse papel. + +#### Carregamento de arquivos + +O `MetadataApiClient` gerado inclui um método `uploadFile` para anexar arquivos a campos do tipo arquivo nos objetos do seu espaço de trabalho. Como os clientes GraphQL padrão não suportam nativamente o carregamento de arquivos multipart, o cliente fornece este método dedicado que implementa, nos bastidores, a [especificação de solicitações multipart do GraphQL](https://github.com/jaydenseric/graphql-multipart-request-spec). + +```typescript +import { MetadataApiClient } from 'twenty-sdk/generated'; +import * as fs from 'fs'; + +const metadataClient = new MetadataApiClient(); + +const fileBuffer = fs.readFileSync('./invoice.pdf'); + +const uploadedFile = await metadataClient.uploadFile( + fileBuffer, // file contents as a Buffer + 'invoice.pdf', // filename + 'application/pdf', // MIME type (defaults to 'application/octet-stream') + '58a0a314-d7ea-4865-9850-7fb84e72f30b', // field universal identifier +); + +console.log(uploadedFile); +// { id: '...', path: '...', size: 12345, createdAt: '...', url: 'https://...' } +``` + +A assinatura do método: + +```typescript +uploadFile( + fileBuffer: Buffer, + filename: string, + contentType: string, + fieldMetadataUniversalIdentifier: string, +): Promise<{ id: string; path: string; size: number; createdAt: string; url: string }> +``` + +| Parâmetro | Tipo | Descrição | +| ---------------------------------- | -------- | ------------------------------------------------------------------------ | +| `fileBuffer` | `Buffer` | O conteúdo bruto do arquivo | +| `filename` | `string` | O nome do arquivo (usado para armazenamento e exibição) | +| `contentType` | `string` | Tipo MIME do arquivo (padrão para `application/octet-stream` se omitido) | +| `fieldMetadataUniversalIdentifier` | `string` | O `universalIdentifier` do campo do tipo arquivo no seu objeto | + +Pontos-chave: + +* O método `uploadFile` está disponível no `MetadataApiClient` porque a mutação de upload é resolvida pelo endpoint `/metadata`. +* Ele usa o `universalIdentifier` do campo (não o ID específico do espaço de trabalho), de modo que seu código de upload funcione em qualquer espaço de trabalho onde seu app esteja instalado — consistente com a forma como os apps referenciam campos em qualquer outro lugar. +* A `url` retornada é um URL assinado que você pode usar para acessar o arquivo enviado. + +### Exemplo Hello World + +Explore um exemplo mínimo de ponta a ponta que demonstra objetos, funções de lógica, componentes de front-end e vários gatilhos [aqui](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/hello-world). diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/getting-started.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/getting-started.mdx new file mode 100644 index 0000000000..c3a2db10d8 --- /dev/null +++ b/packages/twenty-docs/l/pt/developers/extend/apps/getting-started.mdx @@ -0,0 +1,233 @@ +--- +title: Primeiros passos +description: Crie seu primeiro app do Twenty em minutos. +--- + + +Os aplicativos estão atualmente em testes alfa. O recurso é funcional, mas ainda está evoluindo. + + +Os apps permitem que você estenda o Twenty com objetos, campos, funções de lógica, habilidades de IA e componentes de UI personalizados — tudo gerenciado como código. + +**O que você pode fazer hoje:** + +* Defina objetos e campos personalizados como código (modelo de dados gerenciado) +* Crie funções de lógica com gatilhos personalizados (rotas HTTP, cron, eventos de banco de dados) +* Defina habilidades para agentes de IA +* Crie componentes de front-end que renderizam dentro da UI do Twenty +* Implemente o mesmo aplicativo em vários espaços de trabalho + +## Pré-requisitos + +* Node.js 24+ e Yarn 4 +* Um espaço de trabalho do Twenty e uma chave de API (crie uma em https://app.twenty.com/settings/api-webhooks) + +## Primeiros passos + +Crie um novo aplicativo usando o gerador oficial, depois autentique-se e comece a desenvolver: + +```bash filename="Terminal" +# Scaffold a new app (includes all examples by default) +npx create-twenty-app@latest my-twenty-app +cd my-twenty-app + +# Start dev mode: automatically syncs local changes to your workspace +yarn twenty app:dev +``` + +O gerador de estrutura oferece suporte a dois modos para controlar quais arquivos de exemplo são incluídos: + +```bash filename="Terminal" +# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item, skill) +npx create-twenty-app@latest my-app + +# Minimal: only core files (application-config.ts and default-role.ts) +npx create-twenty-app@latest my-app --minimal +``` + +A partir daqui você pode: + +```bash filename="Terminal" +# Add a new entity to your application (guided) +yarn twenty entity:add + +# Watch your application's function logs +yarn twenty function:logs + +# Execute a function by name +yarn twenty function:execute -n my-function -p '{"name": "test"}' + +# Execute the pre-install function +yarn twenty function:execute --preInstall + +# Execute the post-install function +yarn twenty function:execute --postInstall + +# Uninstall the application from the current workspace +yarn twenty app:uninstall + +# Display commands' help +yarn twenty help +``` + +Veja também: as páginas de referência da CLI para [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) e [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk). + +## Estrutura do projeto (com scaffold) + +Ao executar `npx create-twenty-app@latest my-twenty-app`, o gerador: + +* Copia um aplicativo base mínimo para `my-twenty-app/` +* Adiciona uma dependência local `twenty-sdk` e a configuração do Yarn 4 +* Cria arquivos de configuração e scripts conectados à CLI `twenty` +* Gera arquivos principais (configuração da aplicação, papel padrão para funções de lógica, funções de pré-instalação e pós-instalação) além de arquivos de exemplo com base no modo de geração de estrutura + +Um app recém-criado com o modo padrão `--exhaustive` fica assim: + +```text filename="my-twenty-app/" +my-twenty-app/ + package.json + yarn.lock + .gitignore + .nvmrc + .yarnrc.yml + .yarn/ + install-state.gz + .oxlintrc.json + tsconfig.json + README.md + public/ # Public assets folder (images, fonts, etc.) + src/ + ├── application-config.ts # Required - main application configuration + ├── roles/ + │ └── default-role.ts # Default role for logic functions + ├── objects/ + │ └── example-object.ts # Example custom object definition + ├── fields/ + │ └── example-field.ts # Example standalone field definition + ├── logic-functions/ + │ ├── hello-world.ts # Example logic function + │ ├── pre-install.ts # Pre-install logic function + │ └── post-install.ts # Post-install logic function + ├── front-components/ + │ └── hello-world.tsx # Example front component + ├── views/ + │ └── example-view.ts # Example saved view definition + ├── navigation-menu-items/ + │ └── example-navigation-menu-item.ts # Example sidebar navigation link + └── skills/ + └── example-skill.ts # Example AI agent skill definition +``` + +Com `--minimal`, apenas os arquivos principais são criados (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` e `logic-functions/post-install.ts`). + +Em alto nível: + +* **package.json**: Declara o nome do app, versão, engines (Node 24+, Yarn 4), e adiciona `twenty-sdk` além de um script `twenty` que delega para a CLI `twenty` local. Execute `yarn twenty help` para listar todos os comandos disponíveis. +* **.gitignore**: Ignora artefatos comuns como `node_modules`, `.yarn`, `generated/` (cliente tipado), `dist/`, `build/`, pastas de cobertura, arquivos de log e arquivos `.env*`. +* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Bloqueiam e configuram a ferramenta Yarn 4 usada pelo projeto. +* **.nvmrc**: Fixa a versão do Node.js esperada pelo projeto. +* **.oxlintrc.json** e **tsconfig.json**: Fornecem lint e configuração do TypeScript para os fontes TypeScript do seu aplicativo. +* **README.md**: Um README curto na raiz do aplicativo com instruções básicas. +* **public/**: Uma pasta para armazenar recursos públicos (imagens, fontes, arquivos estáticos) que serão servidos com sua aplicação. Os arquivos colocados aqui são enviados durante a sincronização e ficam acessíveis em tempo de execução. +* **src/**: O local principal onde você define seu aplicativo como código + +### Detecção de entidades + +O SDK detecta entidades analisando seus arquivos TypeScript em busca de chamadas **`export default define({...})`**. Cada tipo de entidade tem uma função utilitária correspondente exportada de `twenty-sdk`: + +| Função utilitária | Tipo de entidade | +| -------------------------------- | -------------------------------------------------------------------- | +| `defineObject` | Definições de objetos personalizados | +| `defineLogicFunction` | Definições de funções de lógica | +| `definePreInstallLogicFunction` | Função de lógica de pré-instalação (é executada antes da instalação) | +| `definePostInstallLogicFunction` | Função de lógica de pós-instalação (é executada após a instalação) | +| `defineFrontComponent` | Definições de componentes de front-end | +| `defineRole` | Definições de papéis | +| `defineField` | Extensões de campos para objetos existentes | +| `defineView` | Definições de visualizações salvas | +| `defineNavigationMenuItem` | Definições de itens do menu de navegação | +| `defineSkill` | Definições de habilidades de agente de IA | + + +**A nomeação de arquivos é flexível.** A detecção de entidades é baseada em AST — o SDK varre seus arquivos fonte em busca do padrão `export default define({...})`. Você pode organizar seus arquivos e pastas como quiser. Agrupar por tipo de entidade (por exemplo, `logic-functions/`, `roles/`) é apenas uma convenção para organização do código, não um requisito. + + +Exemplo de uma entidade detectada: + +```typescript +// This file can be named anything and placed anywhere in src/ +import { defineObject, FieldType } from 'twenty-sdk'; + +export default defineObject({ + universalIdentifier: '...', + nameSingular: 'postCard', + // ... rest of config +}); +``` + +Comandos posteriores adicionarão mais arquivos e pastas: + +* `yarn twenty app:dev` irá gerar automaticamente dois clientes de API tipados em `node_modules/twenty-sdk/generated`: `CoreApiClient` (para dados do espaço de trabalho via `/graphql`) e `MetadataApiClient` (para configuração do espaço de trabalho e envio de arquivos via `/metadata`). +* `yarn twenty entity:add` adicionará arquivos de definição de entidade em `src/` para seus objetos, funções, componentes de front-end, papéis e habilidades personalizados, entre outros. + +## Autenticação + +Na primeira vez que você executar `yarn twenty auth:login`, será solicitado o seguinte: + +* URL da API (padrão: http://localhost:3000 ou o perfil do seu espaço de trabalho atual) +* Chave de API + +Suas credenciais são armazenadas por usuário em `~/.twenty/config.json`. Você pode manter vários perfis e alternar entre eles. + +### Gerenciando espaços de trabalho + +```bash filename="Terminal" +# Login interactively (recommended) +yarn twenty auth:login + +# Login to a specific workspace profile +yarn twenty auth:login --workspace my-custom-workspace + +# List all configured workspaces +yarn twenty auth:list + +# Switch the default workspace (interactive) +yarn twenty auth:switch + +# Switch to a specific workspace +yarn twenty auth:switch production + +# Check current authentication status +yarn twenty auth:status +``` + +Depois que você alternar os espaços de trabalho com `yarn twenty auth:switch`, todos os comandos subsequentes usarão esse espaço de trabalho por padrão. Você ainda pode substituí-lo temporariamente com `--workspace `. + +## Configuração manual (sem o gerador) + +Embora recomendemos usar `create-twenty-app` para a melhor experiência inicial, você também pode configurar um projeto manualmente. Não instale a CLI globalmente. Em vez disso, adicione `twenty-sdk` como uma dependência local e configure um único script no seu package.json: + +```bash filename="Terminal" +yarn add -D twenty-sdk +``` + +Em seguida, adicione um script `twenty`: + +```json filename="package.json" +{ + "scripts": { + "twenty": "twenty" + } +} +``` + +Agora você pode executar todos os comandos via `yarn twenty `, por exemplo, `yarn twenty app:dev`, `yarn twenty help`, etc. + +## Resolução de Problemas + +* Erros de autenticação: execute `yarn twenty auth:login` e certifique-se de que sua chave de API tenha as permissões necessárias. +* Não é possível conectar ao servidor: verifique a URL da API e se o servidor do Twenty está acessível. +* Tipos ou cliente ausentes/desatualizados: reinicie `yarn twenty app:dev` — ele gera automaticamente o cliente tipado. +* Modo de desenvolvimento não sincronizando: certifique-se de que `yarn twenty app:dev` esteja em execução e de que as alterações não estejam sendo ignoradas pelo seu ambiente. + +Canal de ajuda no Discord: https://discord.com/channels/1130383047699738754/1130386664812982322 diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/publishing.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/publishing.mdx new file mode 100644 index 0000000000..56ccd08087 --- /dev/null +++ b/packages/twenty-docs/l/pt/developers/extend/apps/publishing.mdx @@ -0,0 +1,119 @@ +--- +title: Publicação +description: Distribua seu aplicativo Twenty no Marketplace ou implante-o internamente. +--- + + +Os aplicativos estão atualmente em testes alfa. O recurso é funcional, mas ainda está evoluindo. + + +## Visão Geral + +Depois que seu aplicativo estiver [compilado e testado localmente](/l/pt/developers/extend/apps/building), você tem dois caminhos para distribuí-lo: + +* **Publicar no npm** — liste seu aplicativo no Marketplace da Twenty para que qualquer espaço de trabalho possa descobrir e instalar. +* **Enviar um tarball** — implante seu aplicativo em um servidor Twenty específico para uso interno sem torná-lo público. + +## Publicação no npm + +Publicar no npm torna seu aplicativo descobrível no Marketplace da Twenty. Qualquer espaço de trabalho da Twenty pode navegar, instalar e atualizar aplicativos do Marketplace diretamente pela UI. + +### Requisitos + +* Uma conta no [npm](https://www.npmjs.com) +* O nome do seu pacote **deve** usar o prefixo `twenty-app-` (por exemplo, `twenty-app-postcard-sender`) + +### Etapas + +1. **Compile seu aplicativo** — a CLI compila seus códigos-fonte TypeScript e gera o manifesto do aplicativo: + +```bash filename="Terminal" +yarn twenty app:build +``` + +2. **Publicar no npm** — envie o pacote compilado para o registro do npm: + +```bash filename="Terminal" +npx twenty app:publish +``` + +### Descoberta automática + +Pacotes com o prefixo `twenty-app-` são detectados automaticamente pelo catálogo do Marketplace da Twenty. Depois de publicado, seu aplicativo aparece no Marketplace em poucos minutos — sem necessidade de registro manual ou aprovação. + +### Publicação via CI + +O projeto gerado inclui um workflow do GitHub Actions que publica a cada lançamento. Ele executa `app:build` e depois `npm publish --provenance` a partir da saída do build: + +```yaml filename=".github/workflows/publish.yml" +name: Publish +on: + release: + types: [published] + +permissions: + contents: read + id-token: write + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "24" + registry-url: https://registry.npmjs.org + - run: yarn install --immutable + - run: npx twenty app:build + - run: npm publish --provenance --access public + working-directory: .twenty/output + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} +``` + +Para outros sistemas de CI (GitLab CI, CircleCI etc.), aplicam-se os mesmos três comandos: `yarn install`, `npx twenty app:build` e depois `npm publish` a partir de `.twenty/output`. + + +**Proveniência do npm** é opcional, mas recomendada. Publicar com `--provenance` adiciona um selo de confiança à sua listagem no npm, permitindo que os usuários verifiquem que o pacote foi construído a partir de um commit específico em um pipeline de CI público. Consulte a [documentação de proveniência do npm](https://docs.npmjs.com/generating-provenance-statements) para instruções de configuração. + + +## Distribuição interna + +Para aplicativos que você não quer disponibilizar publicamente — ferramentas proprietárias, integrações apenas para empresas ou builds experimentais — você pode enviar um tarball diretamente para um servidor Twenty. + +### Enviar um tarball + +Compile seu aplicativo e implante-o em um servidor específico em uma única etapa: + +```bash filename="Terminal" +npx twenty app:publish --server +``` + +Qualquer espaço de trabalho nesse servidor pode então instalar e atualizar o aplicativo na página de configurações de **Aplicativos**. + +### Gerenciamento de versões + +Para lançar uma atualização: + +1. Atualize o campo `version` no seu `package.json` +2. Envie um novo tarball com `npx twenty app:publish --server ` +3. Os espaços de trabalho nesse servidor verão a atualização disponível nas suas configurações + + +Aplicativos internos ficam restritos ao servidor para o qual são enviados. Eles não aparecem no Marketplace público e não podem ser instalados por espaços de trabalho em outros servidores. + + +## Categorias de aplicativos + +A Twenty organiza os aplicativos em três categorias com base em como são distribuídos: + +| Categoria | Como Funciona | Visível no Marketplace? | +| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | +| **Desenvolvimento** | Aplicativos em modo de desenvolvimento local executados via `yarn twenty app:dev`. Usados para compilação e testes. | Não | +| **Publicado** | Aplicativos publicados no npm com o prefixo `twenty-app-`. Listados no Marketplace para que qualquer espaço de trabalho possa instalar. | Sim | +| **Interno** | Aplicativos implantados via tarball em um servidor específico. Disponível apenas para espaços de trabalho nesse servidor. | Não | + + +Comece no modo de **Desenvolvimento** enquanto cria seu aplicativo. Quando estiver pronto, escolha **Publicado** (npm) para ampla distribuição ou **Interno** (tarball) para implantação privada. + diff --git a/packages/twenty-docs/l/pt/developers/extend/capabilities/apps.mdx b/packages/twenty-docs/l/pt/developers/extend/capabilities/apps.mdx index ff97d0ac1b..03244d1f76 100644 --- a/packages/twenty-docs/l/pt/developers/extend/capabilities/apps.mdx +++ b/packages/twenty-docs/l/pt/developers/extend/capabilities/apps.mdx @@ -321,11 +321,11 @@ Você pode substituir os campos padrão definindo um campo com o mesmo nome no s mas isso não é recomendado. -### Defining fields on existing objects +### Definindo campos em objetos existentes -Use `defineField()` to add custom fields to existing objects — both standard objects (like `company`, `person`, `opportunity`) and custom objects defined by other apps. Each field lives in its own file and references the target object by its `universalIdentifier`. +Use `defineField()` para adicionar campos personalizados a objetos existentes — tanto objetos padrão (como `company`, `person`, `opportunity`) quanto objetos personalizados definidos por outros aplicativos. Cada campo fica em seu próprio arquivo e faz referência ao objeto de destino por seu `universalIdentifier`. -To reference standard objects, import `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` from `twenty-sdk`. This constant provides stable identifiers for all built-in objects and their fields: +Para fazer referência a objetos padrão, importe `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` de `twenty-sdk`. Essa constante fornece identificadores estáveis para todos os objetos integrados e seus campos: ```typescript // src/fields/apollo-total-funding.field.ts @@ -349,22 +349,22 @@ export default defineField({ Pontos-chave: -* `objectUniversalIdentifier` tells Twenty which object to attach the field to. Use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS..universalIdentifier` for standard objects. -* Each field requires its own stable `universalIdentifier`, a `name`, `type`, `label`, and the target `objectUniversalIdentifier`. -* You can scaffold new fields using `yarn twenty entity:add` and choosing the field option. -* `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` is also exported as `STANDARD_OBJECT` for convenience — both refer to the same constant. +* `objectUniversalIdentifier` indica ao Twenty a qual objeto anexar o campo. Use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS. @@ -16,18 +15,18 @@ O Twenty foi projetado para ser extensível. Use nossas APIs, webhooks e o frame * **APIs**: Consulte e modifique seus dados de CRM programaticamente usando REST ou GraphQL * **Webhooks**: Receba notificações em tempo real quando eventos ocorrerem no Twenty -* **Apps**: Crie aplicativos personalizados que expandem as capacidades do Twenty - Em breve! +* **Apps**: Crie aplicativos personalizados que expandem as capacidades do Twenty ## Primeiros passos - + Conecte-se ao Twenty programaticamente - + Receba notificações de eventos em tempo real - - Crie personalizações como código (Alpha) + + Crie personalizações como código diff --git a/packages/twenty-docs/l/pt/developers/extend/webhooks.mdx b/packages/twenty-docs/l/pt/developers/extend/webhooks.mdx new file mode 100644 index 0000000000..25d669a127 --- /dev/null +++ b/packages/twenty-docs/l/pt/developers/extend/webhooks.mdx @@ -0,0 +1,116 @@ +--- +title: Webhooks +description: Receba notificações em tempo real quando eventos ocorrerem no seu CRM. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +Os webhooks enviam dados para seus sistemas em tempo real quando eventos ocorrem no Twenty — sem necessidade de polling. Use-os para manter sistemas externos em sincronia, acionar automações ou enviar alertas. + +## Criar Webhook + +1. Vá para **Configurações → APIs & Webhooks → Webhooks** +2. Clique em **+ Criar webhook** +3. Insira a URL do seu webhook (deve ser publicamente acessível) +4. Clique em **Salvar** + +O webhook é ativado imediatamente e começa a enviar notificações. + + + +### Gerenciar Webhooks + +**Editar**: Clique no webhook → Atualizar URL → **Salvar** + +**Excluir**: Clique no webhook → **Excluir** → Confirmar + +## Eventos + +O Twenty envia webhooks para estes tipos de eventos: + +| Evento | Exemplo | +| ----------------------- | ---------------------------------------------------------- | +| **Registro criado** | `person.created`, `company.created`, `note.created` | +| **Registro atualizado** | `person.updated`, `company.updated`, `opportunity.updated` | +| **Registro excluído** | `person.deleted`, `company.deleted` | + +Todos os tipos de evento são enviados para a URL do seu webhook. A filtragem de eventos pode ser adicionada em versões futuras. + +## Formato do payload + +Cada webhook envia um HTTP POST com um corpo JSON: + +```json +{ + "event": "person.created", + "data": { + "id": "abc12345", + "firstName": "Alice", + "lastName": "Doe", + "email": "alice@example.com", + "createdAt": "2025-02-10T15:30:45Z", + "createdBy": "user_123" + }, + "timestamp": "2025-02-10T15:30:50Z" +} +``` + +| Campo | Descrição | +| ----------- | ------------------------------------------------------ | +| `event` | O que aconteceu (por exemplo, `person.created`) | +| `data` | O registro completo que foi criado/atualizado/excluído | +| `timestamp` | Quando o evento ocorreu (UTC) | + + +Responda com um **status HTTP 2xx** (200-299) para confirmar o recebimento. Respostas não 2xx são registradas como falhas de entrega. + + +## Validação de Webhook + +O Twenty assina cada solicitação de webhook por segurança. Valide as assinaturas para garantir que as solicitações sejam autênticas. + +### Cabeçalhos + +| Cabeçalho | Descrição | +| ---------------------------- | ------------------------ | +| `X-Twenty-Webhook-Signature` | Assinatura HMAC SHA256 | +| `X-Twenty-Webhook-Timestamp` | Timestamp da solicitação | + +### Etapas de validação + +1. Obtenha o timestamp de `X-Twenty-Webhook-Timestamp` +2. Crie a string: `{timestamp}:{JSON payload}` +3. Calcule o HMAC SHA256 usando o segredo do seu webhook +4. Compare com `X-Twenty-Webhook-Signature` + +### Exemplo (Node.js) + +```javascript +const crypto = require("crypto"); + +const timestamp = req.headers["x-twenty-webhook-timestamp"]; +const payload = JSON.stringify(req.body); +const secret = "your-webhook-secret"; + +const stringToSign = `${timestamp}:${payload}`; +const expectedSignature = crypto + .createHmac("sha256", secret) + .update(stringToSign) + .digest("hex"); + +const receivedSignature = req.headers["x-twenty-webhook-signature"]; +const isValid = crypto.timingSafeEqual( + Buffer.from(expectedSignature, "hex"), + Buffer.from(receivedSignature, "hex") +); +``` + +## Webhooks vs Fluxos de trabalho + +| Método | Direção | Caso de uso | +| ------------------------------------------- | ------- | -------------------------------------------------------------------------------- | +| **Webhooks** | SAÍDA | Notificar automaticamente sistemas externos sobre qualquer alteração de registro | +| **Fluxo de trabalho + Solicitação HTTP** | SAÍDA | Enviar dados para fora com lógica personalizada (filtros, transformações) | +| **Gatilho de webhook de fluxo de trabalho** | ENTRADA | Receber dados no Twenty a partir de sistemas externos | + +Para receber dados externos, consulte [Configurar um gatilho de Webhook](/l/pt/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger). diff --git a/packages/twenty-docs/l/pt/developers/introduction.mdx b/packages/twenty-docs/l/pt/developers/introduction.mdx index 6e3892d6c2..03f4656190 100644 --- a/packages/twenty-docs/l/pt/developers/introduction.mdx +++ b/packages/twenty-docs/l/pt/developers/introduction.mdx @@ -5,28 +5,18 @@ description: Bem-vindo à Documentação para Desenvolvedores da Twenty, seus re import { CardTitle } from "/snippets/card-title.mdx" - - - API - Consulte e modifique os dados do seu CRM com REST ou GraphQL. + + + Estender + Crie integrações com APIs, webhooks e aplicativos personalizados. - - Webhooks - Receba notificações em tempo real quando eventos ocorrerem. - - - - Apps - Crie aplicativos personalizados que estendem as capacidades do Twenty. - - - + Auto-hospedar Implante e gerencie o Twenty na sua própria infraestrutura. - + Contribuir Junte-se à nossa comunidade de código aberto e contribua para o Twenty. diff --git a/packages/twenty-docs/l/pt/user-guide/data-migration/how-tos/export-your-data.mdx b/packages/twenty-docs/l/pt/user-guide/data-migration/how-tos/export-your-data.mdx index f78525460d..489080e067 100644 --- a/packages/twenty-docs/l/pt/user-guide/data-migration/how-tos/export-your-data.mdx +++ b/packages/twenty-docs/l/pt/user-guide/data-migration/how-tos/export-your-data.mdx @@ -24,7 +24,7 @@ Exporte os dados do seu espaço de trabalho para CSV para backups, relatórios o * Apenas **as colunas visíveis** são exportadas * Apenas **os registros filtrados** são exportados (com base na sua visualização atual) -Para exportações maiores (20,000+ registros), use filtros para exportar em lotes ou use a [API](/l/pt/developers/api). +Para exportações maiores (20,000+ registros), use filtros para exportar em lotes ou use a [API](/l/pt/developers/extend/api). ### Permissões @@ -148,7 +148,7 @@ A API não tem limite de registros: 2. Use a API GraphQL para consultar registros 3. Processe os resultados no seu aplicativo -Veja: [Documentação da API](/l/pt/developers/api) +Veja: [Documentação da API](/l/pt/developers/extend/api) ## Dicas e Boas Práticas @@ -206,4 +206,4 @@ Arquivos exportados podem conter dados sensíveis: * [Como Atualizar Registros Existentes](/l/pt/user-guide/data-migration/how-tos/update-existing-records-via-import) — edite e reimporte sua exportação * [Como Importar Dados via API](/l/pt/user-guide/data-migration/how-tos/import-data-via-api) — para conjuntos de dados grandes -* [Documentação da API](/l/pt/developers/api) — crie fluxos de trabalho de exportação personalizados +* [Documentação da API](/l/pt/developers/extend/api) — crie fluxos de trabalho de exportação personalizados diff --git a/packages/twenty-docs/l/pt/user-guide/data-migration/how-tos/import-data-via-api.mdx b/packages/twenty-docs/l/pt/user-guide/data-migration/how-tos/import-data-via-api.mdx index 895f30a581..7d2a2bc123 100644 --- a/packages/twenty-docs/l/pt/user-guide/data-migration/how-tos/import-data-via-api.mdx +++ b/packages/twenty-docs/l/pt/user-guide/data-migration/how-tos/import-data-via-api.mdx @@ -57,10 +57,10 @@ Qualquer pessoa com a sua chave de API pode aceder e modificar os dados do seu e A Twenty suporta dois tipos de API: -| API | Melhor para | Documentação | -| ----------- | ------------------------------------------------------------------------ | ----------------------------------------------------------- | -| **GraphQL** | Consultas flexíveis, obtenção de dados relacionados, operações complexas | [Documentação da API](/l/pt/developers/api) | -| **REST** | Operações CRUD simples, padrões REST familiares | [Documentação da API](/l/pt/developers/api) | +| API | Melhor para | Documentação | +| ----------- | ------------------------------------------------------------------------ | --------------------------------------------- | +| **GraphQL** | Consultas flexíveis, obtenção de dados relacionados, operações complexas | [Documentação da API](/l/pt/developers/extend/api) | +| **REST** | Operações CRUD simples, padrões REST familiares | [Documentação da API](/l/pt/developers/extend/api) | Ambas as APIs suportam: @@ -173,4 +173,4 @@ Contacte-nos em [contact@twenty.com](mailto:contact@twenty.com) ou explore os no Para detalhes completos de implementação, exemplos de código e referência de esquema: -* [Documentação da API](/l/pt/developers/api) +* [Documentação da API](/l/pt/developers/extend/api) diff --git a/packages/twenty-docs/l/pt/user-guide/getting-started/capabilities/what-is-twenty.mdx b/packages/twenty-docs/l/pt/user-guide/getting-started/capabilities/what-is-twenty.mdx index 57df1794cc..766e6b25f2 100644 --- a/packages/twenty-docs/l/pt/user-guide/getting-started/capabilities/what-is-twenty.mdx +++ b/packages/twenty-docs/l/pt/user-guide/getting-started/capabilities/what-is-twenty.mdx @@ -35,7 +35,7 @@ O código aberto é a base da nossa abordagem, garantindo que o Twenty evolua co * **Painéis:** Acompanhe o desempenho com relatórios personalizados e visualizações personalizadas. [Ver painéis](/l/pt/user-guide/dashboards/overview). * **Permissões e Acesso:** Controle quem pode visualizar, editar e gerenciar seus dados com permissões baseadas em funções. [Configurar acesso](/l/pt/user-guide/permissions-access/overview). * **Notas e Tarefas:** Crie notas e tarefas vinculadas aos seus registros para uma melhor colaboração. -* **API e Webhooks:** Conecte-se a outros aplicativos e crie integrações personalizadas. [Comece a integrar](/l/pt/developers/api). +* **API e Webhooks:** Conecte-se a outros aplicativos e crie integrações personalizadas. [Comece a integrar](/l/pt/developers/extend/api). ## Participe agora diff --git a/packages/twenty-docs/l/pt/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx b/packages/twenty-docs/l/pt/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx index 74c8a8e3b7..6257971f87 100644 --- a/packages/twenty-docs/l/pt/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx +++ b/packages/twenty-docs/l/pt/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx @@ -95,7 +95,7 @@ Crie os campos de destino em **Definições → Modelo de Dados → Oportunidade * Tamanho da Empresa: `{{searchRecords[0].employees}}` -**Limitação de Tarefas e Notas**: As relações em Tarefas e Notas são pré-definidas como muitos-para-muitos e ainda não estão disponíveis em gatilhos ou ações de fluxos de trabalho. Para aceder a estas relações, use a [API](/l/pt/developers/api). +**Limitação de Tarefas e Notas**: As relações em Tarefas e Notas são pré-definidas como muitos-para-muitos e ainda não estão disponíveis em gatilhos ou ações de fluxos de trabalho. Para aceder a estas relações, use antes a [API](/l/pt/developers/extend/api). ## Sincronização Bidirecional diff --git a/packages/twenty-docs/l/ro/developers/extend/api.mdx b/packages/twenty-docs/l/ro/developers/extend/api.mdx new file mode 100644 index 0000000000..afd54c34bd --- /dev/null +++ b/packages/twenty-docs/l/ro/developers/extend/api.mdx @@ -0,0 +1,147 @@ +--- +title: API-uri +description: Interogați și modificați programatic datele din CRM folosind REST sau GraphQL. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +Twenty a fost creat pentru a fi prietenos cu dezvoltatorii, oferind API-uri puternice care se adaptează la modelul dvs. de date personalizat. Oferim patru tipuri distincte de API-uri pentru a satisface diferite nevoi de integrare. + +## Abordare orientată către dezvoltatori + +Twenty generează API-uri special pentru modelul dvs. de date: + +* **Nu sunt necesare ID-uri lungi**: Utilizați direct numele obiectelor și câmpurilor în punctele finale +* **Obiectele standard și personalizate tratate în mod egal**: Obiectele dvs. personalizate primesc același tratament API ca și cele încorporate +* **Puncte finale dedicate**: Fiecare obiect și câmp primește propriul său punct final API +* **Documentație personalizată**: Generată special pentru modelul de date al spațiului dvs. de lucru + + +Documentația API personalizată este disponibilă la **Settings → API & Webhooks** după crearea unei chei API. Deoarece Twenty generează API-uri care se potrivesc modelului dvs. de date personalizat, documentația este unică pentru spațiul dvs. de lucru. + + +## Cele două tipuri de API-uri + +### API Core + +Accesibil prin `/rest/` sau `/graphql/` + +Lucrați cu **înregistrările** reale (datele): + +* Creați, citiți, actualizați, ștergeți Persoane, Companii, Oportunități etc. +* Interogați și filtrați datele +* Gestionați relațiile dintre înregistrări + +### API Metadata + +Accesibil prin `/rest/metadata/` sau `/metadata/` + +Gestionați-vă **spațiul de lucru și modelul de date**: + +* Creați, modificați sau ștergeți obiecte și câmpuri +* Configurați setările spațiului de lucru +* Definiți relațiile dintre obiecte + +## REST vs GraphQL + +Atât API-urile Core, cât și API-urile Metadata sunt disponibile în formatele REST și GraphQL: + +| Format | Operațiuni disponibile | +| ----------- | -------------------------------------------------------------------------- | +| **REST** | CRUD, operațiuni de grup, upsert-uri | +| **GraphQL** | La fel + **upsert-uri de grup**, interogări de relații într-un singur apel | + +Alegeți în funcție de nevoi — ambele formate accesează aceleași date. + +## Puncte Finale API + +| Mediu | URL de bază | +| -------------------- | ------------------------- | +| **Cloud** | `https://api.twenty.com/` | +| **Găzduire proprie** | `https://{your-domain}/` | + +## Autentificare + +Fiecare solicitare API necesită o cheie API în antet: + +``` +Authorization: Bearer YOUR_API_KEY +``` + +### Creați o cheie API + +1. Mergeți la **Setări → API-uri & Webhook-uri** +2. Faceți clic pe **+ Create key** +3. Configurați: + * **Name**: Nume descriptiv pentru cheie + * **Expiration Date**: Când expiră cheia +4. Faceți clic pe **Salvare** +5. **Copiați imediat** — cheia este afișată o singură dată + + + + +Cheia dvs. API oferă acces la date sensibile. Nu o partajați cu servicii care nu sunt de încredere. Dacă este compromisă, dezactivați-o imediat și generați una nouă. + + +### Atribuiți un rol unei chei API + +Pentru o securitate sporită, atribuiți un rol specific pentru a limita accesul: + +1. Accesați **Setări → Roluri** +2. Faceți clic pe rolul pe care doriți să-l atribuiți +3. Deschideți fila **Atribuire** +4. În **API Keys**, faceți clic pe **+ Assign to API key** +5. Selectați cheia API + +Cheia va moșteni permisiunile acelui rol. Consultați [Permisiuni](/l/ro/user-guide/permissions-access/capabilities/permissions) pentru detalii. + +### Gestionați cheile API + +**Regenerate**: Settings → APIs & Webhooks → Faceți clic pe cheie → **Regenerate** + +**Delete**: Settings → APIs & Webhooks → Faceți clic pe cheie → **Delete** + +## Platformă de testare API + +Testați API-urile direct în browser cu platforma noastră integrată de testare — disponibilă atât pentru **REST**, cât și pentru **GraphQL**. + +### Accesați platforma de testare + +1. Mergeți la **Setări → API-uri & Webhook-uri** +2. Creați o cheie API (obligatoriu) +3. Faceți clic pe **REST API** sau **GraphQL API** pentru a deschide platforma de testare + +### Ce obțineți + +* **Documentație interactivă**: Generată pentru modelul dvs. de date specific +* **Testare live**: Executați apeluri API reale către spațiul dvs. de lucru +* **Explorator de scheme**: Parcurgeți obiectele, câmpurile și relațiile disponibile +* **Constructor de cereri**: Construiți interogări cu completare automată + +Platforma de testare reflectă obiectele și câmpurile dvs. personalizate, astfel încât documentația este întotdeauna corectă pentru spațiul dvs. de lucru. + +## Operațiuni de grup + +Atât REST, cât și GraphQL suportă operațiuni de grup: + +* **Dimensiunea grupului**: Până la 60 de înregistrări pe cerere +* **Operațiuni**: Creați, actualizați, ștergeți mai multe înregistrări + +**Funcții exclusive GraphQL:** + +* **Upsert de grup**: Creați sau actualizați într-un singur apel +* Folosiți nume de obiecte la plural (de exemplu, `CreateCompanies` în loc de `CreateCompany`) + +## Limitări de rată + +Solicitările API sunt limitate pentru a asigura stabilitatea platformei: + +| Limită | Valoare | +| ----------------------- | -------------------------- | +| **Solicitări** | 100 de apeluri pe minut | +| **Dimensiunea lotului** | 60 de înregistrări pe apel | + + +Utilizați operațiunile de grup pentru a maximiza debitul — procesați până la 60 de înregistrări într-un singur apel API în loc să faceți solicitări individuale. + diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/building.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/building.mdx new file mode 100644 index 0000000000..e224ed294f --- /dev/null +++ b/packages/twenty-docs/l/ro/developers/extend/apps/building.mdx @@ -0,0 +1,689 @@ +--- +title: Crearea aplicațiilor +description: Definiți obiecte, funcții logice, componente front-end și multe altele cu Twenty SDK. +--- + + +Aplicațiile sunt în prezent în testare alfa. Caracteristica funcționează, dar este încă în dezvoltare. + + +## Utilizați resursele SDK (tipuri și configurare) + +Biblioteca twenty-sdk oferă blocuri de bază tipizate și funcții ajutătoare pe care le utilizați în aplicația dvs. Mai jos sunt elementele cheie cu care veți interacționa cel mai des. + +### Funcții ajutătoare + +SDK-ul oferă funcții ajutătoare pentru definirea entităților aplicației. După cum este descris în [Detectarea entităților](/l/ro/developers/extend/apps/getting-started#entity-detection), trebuie să folosiți `export default define({...})` pentru ca entitățile să fie detectate: + +| Funcție | Scop | +| -------------------------------- | ---------------------------------------------------------------------- | +| `defineApplication` | Configurați metadatele aplicației (obligatoriu, una per aplicație) | +| `defineObject` | Definiți obiecte personalizate cu câmpuri | +| `defineLogicFunction` | Definiți funcții de logică cu handleri | +| `definePreInstallLogicFunction` | Definește o funcție logică de pre-instalare (una per aplicație) | +| `definePostInstallLogicFunction` | Definește o funcție logică post-instalare (una per aplicație) | +| `defineFrontComponent` | Definiți componente Front pentru interfața de utilizator personalizată | +| `defineRole` | Configurați permisiunile rolurilor și accesul la obiecte | +| `defineField` | Extindeți obiectele existente cu câmpuri suplimentare | +| `defineView` | Definește vizualizări salvate pentru obiecte | +| `defineNavigationMenuItem` | Definește linkuri de navigare în bara laterală | +| `defineSkill` | Definiți abilități pentru agentul AI | + +Aceste funcții validează configurația în timpul build-ului și oferă completare automată în IDE și siguranța tipurilor. + +### Definirea obiectelor + +Obiectele personalizate descriu atât schema, cât și comportamentul înregistrărilor din spațiul dvs. de lucru. Utilizați `defineObject()` pentru a defini obiecte cu validare încorporată: + +```typescript +// src/app/postCard.object.ts +import { defineObject, FieldType } from 'twenty-sdk'; + +enum PostCardStatus { + DRAFT = 'DRAFT', + SENT = 'SENT', + DELIVERED = 'DELIVERED', + RETURNED = 'RETURNED', +} + +export default defineObject({ + universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05', + nameSingular: 'postCard', + namePlural: 'postCards', + labelSingular: 'Post Card', + labelPlural: 'Post Cards', + description: 'A post card object', + icon: 'IconMail', + fields: [ + { + universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b', + name: 'content', + type: FieldType.TEXT, + label: 'Content', + description: "Postcard's content", + icon: 'IconAbc', + }, + { + universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac', + name: 'recipientName', + type: FieldType.FULL_NAME, + label: 'Recipient name', + icon: 'IconUser', + }, + { + universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266', + name: 'recipientAddress', + type: FieldType.ADDRESS, + label: 'Recipient address', + icon: 'IconHome', + }, + { + universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e', + name: 'status', + type: FieldType.SELECT, + label: 'Status', + icon: 'IconSend', + defaultValue: `'${PostCardStatus.DRAFT}'`, + options: [ + { value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' }, + { value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' }, + { value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' }, + { value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' }, + ], + }, + { + universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433', + name: 'deliveredAt', + type: FieldType.DATE_TIME, + label: 'Delivered at', + icon: 'IconCheck', + isNullable: true, + defaultValue: null, + }, + ], +}); +``` + +Puncte cheie: + +* Folosiți `defineObject()` pentru validare încorporată și suport mai bun în IDE. +* `universalIdentifier` trebuie să fie unic și stabil între implementări. +* Fiecare câmp necesită un `name`, un `type`, un `label` și propriul `universalIdentifier` stabil. +* Matricea `fields` este opțională — puteți defini obiecte fără câmpuri personalizate. +* Puteți genera obiecte noi folosind `yarn twenty entity:add`, care vă ghidează prin denumire, câmpuri și relații. + + +**Câmpurile de bază sunt create automat.** Când definiți un obiect personalizat, Twenty adaugă automat câmpuri standard +precum `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` și `deletedAt`. +Nu trebuie să le definiți în tabloul `fields` — adăugați doar câmpurile personalizate proprii. +Puteți suprascrie câmpurile implicite definind un câmp cu același nume în tabloul `fields`, +dar acest lucru nu este recomandat. + + +### Configurația aplicației (application-config.ts) + +Fiecare aplicație are un singur fișier `application-config.ts` care descrie: + +* **Cine este aplicația**: identificatori, nume de afișare și descriere. +* **Cum rulează funcțiile**: ce rol folosesc pentru permisiuni. +* **(Opțional) variabile**: perechi cheie–valoare expuse funcțiilor ca variabile de mediu. +* **(Opțional) funcție de pre-instalare**: o funcție logică care rulează înainte ca aplicația să fie instalată. +* **(Opțional) funcție post-instalare**: o funcție logică care rulează după instalarea aplicației. + +Folosiți `defineApplication()` pentru a defini configurația aplicației: + +```typescript +// src/application-config.ts +import { defineApplication } from 'twenty-sdk'; +import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role'; + +export default defineApplication({ + universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7', + displayName: 'My Twenty App', + description: 'My first Twenty app', + icon: 'IconWorld', + applicationVariables: { + DEFAULT_RECIPIENT_NAME: { + universalIdentifier: '19e94e59-d4fe-4251-8981-b96d0a9f74de', + description: 'Default recipient name for postcards', + value: 'Jane Doe', + isSecret: false, + }, + }, + defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, +}); +``` + +Notițe: + +* Câmpurile `universalIdentifier` sunt ID-uri deterministe pe care le dețineți; generați-le o singură dată și păstrați-le stabile între sincronizări. +* `applicationVariables` devin variabile de mediu pentru funcțiile dvs. (de exemplu, `DEFAULT_RECIPIENT_NAME` este disponibil ca `process.env.DEFAULT_RECIPIENT_NAME`). +* `defaultRoleUniversalIdentifier` trebuie să corespundă fișierului de rol (vedeți mai jos). +* Funcțiile de pre-instalare și post-instalare sunt detectate automat în timpul construirii manifestului. Vezi [Funcții de pre-instalare](#pre-install-functions) și [Funcții post-instalare](#post-install-functions). + +#### Roluri și permisiuni + +Aplicațiile pot defini roluri care încapsulează permisiuni asupra obiectelor și acțiunilor din spațiul dvs. de lucru. Câmpul `defaultRoleUniversalIdentifier` din `application-config.ts` desemnează rolul implicit utilizat de funcțiile de logică ale aplicației. + +* Cheia API de runtime injectată ca `TWENTY_API_KEY` este derivată din acest rol implicit pentru funcții. +* Clientul tipizat va fi restricționat la permisiunile acordate acelui rol. +* Respectați principiul celui mai mic privilegiu: creați un rol dedicat doar cu permisiunile de care au nevoie funcțiile, apoi referiți identificatorul său universal. + +##### Rol implicit pentru funcții (*.role.ts) + +Când generați o aplicație nouă, CLI creează și un fișier de rol implicit. Folosiți `defineRole()` pentru a defini roluri cu validare încorporată: + +```typescript +// src/roles/default-role.ts +import { defineRole, PermissionFlag } from 'twenty-sdk'; + +export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = + 'b648f87b-1d26-4961-b974-0908fd991061'; + +export default defineRole({ + universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, + label: 'Default function role', + description: 'Default role for function Twenty client', + canReadAllObjectRecords: false, + canUpdateAllObjectRecords: false, + canSoftDeleteAllObjectRecords: false, + canDestroyAllObjectRecords: false, + canUpdateAllSettings: false, + canBeAssignedToAgents: false, + canBeAssignedToUsers: false, + canBeAssignedToApiKeys: false, + objectPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + canReadObjectRecords: true, + canUpdateObjectRecords: true, + canSoftDeleteObjectRecords: false, + canDestroyObjectRecords: false, + }, + ], + fieldPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + fieldUniversalIdentifier: 'b2c37dc0-8ae7-470e-96cd-1476b47dfaff', + canReadFieldValue: false, + canUpdateFieldValue: false, + }, + ], + permissionFlags: [PermissionFlag.APPLICATIONS], +}); +``` + +`universalIdentifier` al acestui rol este apoi referențiat în `application-config.ts` ca `defaultRoleUniversalIdentifier`. Cu alte cuvinte: + +* **\*.role.ts** definește ce poate face rolul implicit pentru funcții. +* **application-config.ts** indică acel rol, astfel încât funcțiile moștenesc permisiunile lui. + +Notițe: + +* Porniți de la rolul generat, apoi restrângeți-l progresiv urmând principiul celui mai mic privilegiu. +* Înlocuiți `objectPermissions` și `fieldPermissions` cu obiectele/câmpurile de care au nevoie funcțiile. +* `permissionFlags` controlează accesul la capabilități la nivelul platformei. Mențineți-le la minimum; adăugați doar ceea ce aveți nevoie. +* Vedeți un exemplu funcțional în aplicația Hello World: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). + +### Configurația funcției de logică și punctul de intrare + +Fiecare fișier de funcție folosește `defineLogicFunction()` pentru a exporta o configurație cu un handler și declanșatoare opționale. + +```typescript +// src/app/createPostCard.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk'; +import { CoreApiClient, type Person } from 'twenty-sdk/generated'; + +const handler = async (params: RoutePayload) => { + const client = new CoreApiClient(); + const name = 'name' in params.queryStringParameters + ? params.queryStringParameters.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world' + : 'Hello world'; + + const result = await client.mutation({ + createPostCard: { + __args: { data: { name } }, + id: true, + name: true, + }, + }); + return result; +}; + +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'create-new-post-card', + timeoutSeconds: 2, + handler, + triggers: [ + // Public HTTP route trigger '/s/post-card/create' + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/post-card/create', + httpMethod: 'GET', + isAuthRequired: false, + }, + // Cron trigger (CRON pattern) + // { + // universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2', + // type: 'cron', + // pattern: '0 0 1 1 *', + // }, + // Database event trigger + // { + // universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156', + // type: 'databaseEvent', + // eventName: 'person.updated', + // updatedFields: ['name'], + // }, + ], +}); +``` + +Tipuri comune de declanșatoare: + +* **route**: Expune funcția pe o rută și metodă HTTP **sub endpoint-ul `/s/`**: + +> de ex. `path: '/post-card/create',` -> apel pe `/s/post-card/create` + +* **cron**: Rulează funcția pe un program folosind o expresie CRON. +* **databaseEvent**: Rulează la evenimentele ciclului de viață ale obiectelor din spațiul de lucru. Când operațiunea evenimentului este `updated`, câmpurile specifice de urmărit pot fi specificate în array-ul `updatedFields`. Dacă este lăsat nedefinit sau gol, orice actualizare va declanșa funcția. + +> de ex. `person.updated` + +Notițe: + +* Matricea `triggers` este opțională. Funcțiile fără declanșatoare pot fi folosite ca funcții utilitare apelate de alte funcții. +* Puteți combina mai multe tipuri de declanșatoare într-o singură funcție. + +### Funcții de pre-instalare + +O funcție de pre-instalare este o funcție logică ce rulează automat înainte ca aplicația ta să fie instalată într-un spațiu de lucru. Aceasta este utilă pentru sarcini de validare, verificări ale condițiilor prealabile sau pregătirea stării spațiului de lucru înainte ca instalarea principală să continue. + +Când creezi scheletul unei aplicații noi cu `create-twenty-app`, ți se generează o funcție de pre-instalare la `src/logic-functions/pre-install.ts`: + +```typescript +// src/logic-functions/pre-install.ts +import { definePreInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Pre install logic function executed successfully!', payload.previousVersion); +}; + +export default definePreInstallLogicFunction({ + universalIdentifier: '', + name: 'pre-install', + description: 'Runs before installation to prepare the application.', + timeoutSeconds: 300, + handler, +}); +``` + +Poți, de asemenea, să execuți manual funcția de pre-instalare oricând folosind CLI: + +```bash filename="Terminal" +yarn twenty function:execute --preInstall +``` + +Puncte cheie: + +* Funcțiile de pre-instalare folosesc `definePreInstallLogicFunction()` — o variantă specializată care omite setările de declanșare (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`). +* Handlerul primește un `InstallLogicFunctionPayload` cu `{ previousVersion: string }` — versiunea aplicației care a fost instalată anterior (sau un șir gol pentru instalări noi). +* Este permisă o singură funcție de pre-instalare per aplicație. Construirea manifestului va genera o eroare dacă este detectată mai mult de una. +* Proprietatea `universalIdentifier` a funcției este setată automat ca `preInstallLogicFunctionUniversalIdentifier` în manifestul aplicației în timpul build-ului — nu este nevoie să o referi în `defineApplication()`. +* Timpul de expirare implicit este setat la 300 de secunde (5 minute) pentru a permite sarcini de pregătire mai lungi. +* Funcțiile de pre-instalare nu au nevoie de declanșatoare — sunt invocate de platformă înainte de instalare sau manual prin `function:execute --preInstall`. + +### Funcții post-instalare + +O funcție post-instalare este o funcție logică care rulează automat după instalarea aplicației într-un spațiu de lucru. Aceasta este utilă pentru sarcini de configurare unice, cum ar fi popularea cu date implicite, crearea înregistrărilor inițiale sau configurarea setărilor spațiului de lucru. + +Când creezi scheletul unei aplicații noi cu `create-twenty-app`, este generată o funcție post-instalare la `src/logic-functions/post-install.ts`: + +```typescript +// src/logic-functions/post-install.ts +import { definePostInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Post install logic function executed successfully!', payload.previousVersion); +}; + +export default definePostInstallLogicFunction({ + universalIdentifier: '', + name: 'post-install', + description: 'Runs after installation to set up the application.', + timeoutSeconds: 300, + handler, +}); +``` + +Poți, de asemenea, să execuți manual funcția post-instalare oricând folosind CLI: + +```bash filename="Terminal" +yarn twenty function:execute --postInstall +``` + +Puncte cheie: + +* Funcțiile de post-instalare folosesc `definePostInstallLogicFunction()` — o variantă specializată care omite setările de declanșare (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`). +* Handlerul primește un `InstallLogicFunctionPayload` cu `{ previousVersion: string }` — versiunea aplicației care a fost instalată anterior (sau un șir gol pentru instalări noi). +* Este permisă o singură funcție de post-instalare per aplicație. Construirea manifestului va genera o eroare dacă este detectată mai mult de una. +* Proprietatea `universalIdentifier` a funcției este setată automat ca `postInstallLogicFunctionUniversalIdentifier` în manifestul aplicației în timpul build-ului — nu este nevoie să o referi în `defineApplication()`. +* Timpul de expirare implicit este setat la 300 de secunde (5 minute) pentru a permite sarcini de configurare mai lungi, cum ar fi popularea datelor. +* Funcțiile post-instalare nu au nevoie de declanșatoare — sunt invocate de platformă în timpul instalării sau manual prin `function:execute --postInstall`. + +### Payload-ul declanșatorului de rută + + +**Modificare incompatibilă (v1.16, ianuarie 2026):** Formatul payload-ului declanșatorului de rută s-a schimbat. Înainte de v1.16, parametrii de interogare (query), parametrii de cale și corpul erau trimiși direct ca payload. Începând cu v1.16, acestea sunt incluse într-un obiect structurat `RoutePayload`. + +**Înainte de v1.16:** +```typescript +const handler = async (params) => { + const { param1, param2 } = params; // Direct access +}; +``` + +**După v1.16:** +```typescript +const handler = async (event: RoutePayload) => { + const { param1, param2 } = event.body; // Access via .body + const { queryParam } = event.queryStringParameters; + const { id } = event.pathParameters; +}; +``` + +**Pentru a migra funcțiile existente:** Actualizează handler-ul pentru a extrage câmpurile din `event.body`, `event.queryStringParameters` sau `event.pathParameters` în loc să le iei direct din obiectul params. + + +Când un declanșator de rută apelează funcția dvs. de logică, aceasta primește un obiect `RoutePayload` care urmează formatul AWS HTTP API v2. Importă tipul din `twenty-sdk`: + +```typescript +import { defineLogicFunction, type RoutePayload } from 'twenty-sdk'; + +const handler = async (event: RoutePayload) => { + // Access request data + const { headers, queryStringParameters, pathParameters, body } = event; + + // HTTP method and path are available in requestContext + const { method, path } = event.requestContext.http; + + return { message: 'Success' }; +}; +``` + +Tipul `RoutePayload` are următoarea structură: + +| Proprietate | Tip | Descriere | +| ---------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------ | +| `headers` | `Record` | Anteturi HTTP (doar cele listate în `forwardedRequestHeaders`) | +| `queryStringParameters` | `Record` | Parametri query string (valorile multiple unite cu virgule) | +| `pathParameters` | `Record` | Parametri de cale extrași din modelul rutei (de ex., `/users/:id` → `{ id: '123' }`) | +| `body` | `object \| null` | Corpul cererii analizat (JSON) | +| `isBase64Encoded` | `boolean` | Indică dacă corpul este codificat în base64 | +| `requestContext.http.method` | `string` | Metoda HTTP (GET, POST, PUT, PATCH, DELETE) | +| `requestContext.http.path` | `string` | Calea brută a cererii | + +### Transmiterea anteturilor HTTP + +În mod implicit, anteturile HTTP din cererile de intrare **nu** sunt transmise funcției dvs. de logică din motive de securitate. Pentru a accesa anumite anteturi, listează-le explicit în array-ul `forwardedRequestHeaders`: + +```typescript +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'webhook-handler', + handler, + triggers: [ + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/webhook', + httpMethod: 'POST', + isAuthRequired: false, + forwardedRequestHeaders: ['x-webhook-signature', 'content-type'], + }, + ], +}); +``` + +În handler, poți apoi accesa aceste anteturi: + +```typescript +const handler = async (event: RoutePayload) => { + const signature = event.headers['x-webhook-signature']; + const contentType = event.headers['content-type']; + + // Validate webhook signature... + return { received: true }; +}; +``` + + + Numele anteturilor sunt normalizate la litere mici. Accesează-le folosind chei cu litere mici (de exemplu, `event.headers['content-type']`). + + +Puteți crea funcții noi în două moduri: + +* **Generat**: Rulați `yarn twenty entity:add` și alegeți opțiunea de a adăuga o funcție logică nouă. Aceasta generează un fișier inițial cu un handler și o configurație. +* **Manual**: Creați un fișier nou `*.logic-function.ts` și folosiți `defineLogicFunction()`, urmând același model. + +### Marcarea unei funcții logice drept instrument + +Funcțiile logice pot fi expuse ca **instrumente** pentru agenți de IA și fluxuri de lucru. Când o funcție este marcată ca instrument, poate fi descoperită de funcționalitățile de IA ale Twenty și poate fi selectată ca pas în automatizări ale fluxurilor de lucru. + +Pentru a marca o funcție logică drept instrument, setați `isTool: true` și furnizați un `toolInputSchema` care descrie parametrii de intrare așteptați folosind [JSON Schema](https://json-schema.org/): + +```typescript +// src/logic-functions/enrich-company.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import { CoreApiClient } from 'twenty-sdk/generated'; + +const handler = async (params: { companyName: string; domain?: string }) => { + const client = new CoreApiClient(); + + const result = await client.mutation({ + createTask: { + __args: { + data: { + title: `Enrich data for ${params.companyName}`, + body: `Domain: ${params.domain ?? 'unknown'}`, + }, + }, + id: true, + }, + }); + + return { taskId: result.createTask.id }; +}; + +export default defineLogicFunction({ + universalIdentifier: 'f47ac10b-58cc-4372-a567-0e02b2c3d479', + name: 'enrich-company', + description: 'Enrich a company record with external data', + timeoutSeconds: 10, + handler, + isTool: true, + toolInputSchema: { + type: 'object', + properties: { + companyName: { + type: 'string', + description: 'The name of the company to enrich', + }, + domain: { + type: 'string', + description: 'The company website domain (optional)', + }, + }, + required: ['companyName'], + }, +}); +``` + +Puncte cheie: + +* **`isTool`** (`boolean`, implicit: `false`): Când este setat la `true`, funcția este înregistrată ca instrument și devine disponibilă pentru agenții AI și automatizările de fluxuri de lucru. +* **`toolInputSchema`** (`object`, opțional): Un obiect JSON Schema care descrie parametrii pe care îi acceptă funcția dvs. Agenții AI folosesc această schemă pentru a înțelege ce intrări așteaptă instrumentul și pentru a valida apelurile. Dacă este omisă, schema are implicit valoarea `{ type: 'object', properties: {} }` (fără parametri). +* Funcțiile cu `isTool: false` (sau nedefinit) **nu** sunt expuse ca instrumente. Pot totuși fi executate direct sau apelate de alte funcții, dar nu vor apărea în descoperirea instrumentelor. +* **Denumierea instrumentelor**: Când este expusă ca instrument, denumirea funcției este normalizată automat la `logic_function_` (convertită la litere mici, iar caracterele non-alfanumerice sunt înlocuite cu caractere de subliniere). De exemplu, `enrich-company` devine `logic_function_enrich_company`. +* Puteți combina `isTool` cu declanșatoare — o funcție poate fi atât un instrument (apelabilă de agenții AI), cât și declanșată de evenimente (cron, evenimente de bază de date, rute) în același timp. + + +**Scrieți o `description` bună.** Agenții AI se bazează pe câmpul `description` al funcției pentru a decide când să folosească instrumentul. Fiți specifici cu privire la ceea ce face instrumentul și când ar trebui apelat. + + +### Componente Front + +Componentele Front vă permit să construiți componente React personalizate care sunt randate în interfața Twenty. Utilizați `defineFrontComponent()` pentru a defini componente cu validare încorporată: + +```typescript +// src/front-components/my-widget.tsx +import { defineFrontComponent } from 'twenty-sdk'; + +const MyWidget = () => { + return ( +
+

My Custom Widget

+

This is a custom front component for Twenty.

+
+ ); +}; + +export default defineFrontComponent({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'my-widget', + description: 'A custom widget component', + component: MyWidget, +}); +``` + +Puncte cheie: + +* Componentele Front sunt componente React care sunt randate în contexte izolate în cadrul Twenty. +* Câmpul `component` face referire la componenta React. +* Componentele sunt construite și sincronizate automat în timpul `yarn twenty app:dev`. + +Puteți crea componente Front noi în două moduri: + +* **Generat**: Rulați `yarn twenty entity:add` și alegeți opțiunea de a adăuga o componentă frontend nouă. +* **Manual**: Creați un fișier nou `.tsx` și folosiți `defineFrontComponent()`, urmând același model. + +### Abilități + +Abilitățile definesc instrucțiuni și capabilități reutilizabile pe care agenții AI le pot folosi în spațiul dvs. de lucru. Folosiți `defineSkill()` pentru a defini abilități cu validare încorporată: + +```typescript +// src/skills/example-skill.ts +import { defineSkill } from 'twenty-sdk'; + +export default defineSkill({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'sales-outreach', + label: 'Sales Outreach', + description: 'Guides the AI agent through a structured sales outreach process', + icon: 'IconBrain', + content: `You are a sales outreach assistant. When reaching out to a prospect: +1. Research the company and recent news +2. Identify the prospect's role and likely pain points +3. Draft a personalized message referencing specific details +4. Keep the tone professional but conversational`, +}); +``` + +Puncte cheie: + +* `name` este un șir identificator unic pentru abilitate (se recomandă kebab-case). +* `label` este numele lizibil afișat în interfața cu utilizatorul (UI). +* `content` conține instrucțiunile abilității — acesta este textul pe care agentul AI îl folosește. +* `icon` (opțional) setează pictograma afișată în UI. +* `description` (opțional) oferă context suplimentar despre scopul abilității. + +Puteți crea abilități noi în două moduri: + +* **Generat**: Rulați `yarn twenty entity:add` și alegeți opțiunea de a adăuga o abilitate nouă. +* **Manual**: Creați un fișier nou și folosiți `defineSkill()`, urmând același model. + +### Clienți tipizați generați + +Doi clienți tipizați sunt generați automat de `yarn twenty app:dev` și stocați în `node_modules/twenty-sdk/generated`, pe baza schemei spațiului tău de lucru: + +* **`CoreApiClient`** — interoghează endpointul `/graphql` pentru datele spațiului de lucru +* **`MetadataApiClient`** — interoghează endpointul `/metadata` pentru configurarea spațiului de lucru și încărcarea fișierelor + +```typescript +import { CoreApiClient, MetadataApiClient } from 'twenty-sdk/generated'; + +const client = new CoreApiClient(); +const { me } = await client.query({ me: { id: true, displayName: true } }); + +const metadataClient = new MetadataApiClient(); +const { currentWorkspace } = await metadataClient.query({ currentWorkspace: { id: true } }); +``` + +Ambii clienți sunt regenerați automat de `yarn twenty app:dev` ori de câte ori obiectele sau câmpurile tale se schimbă. + +#### Acreditări la runtime în funcțiile de logică + +Când funcția rulează pe Twenty, platforma injectează acreditări ca variabile de mediu înainte de execuția codului: + +* `TWENTY_API_URL`: URL-ul de bază al API-ului Twenty către care țintește aplicația. +* `TWENTY_API_KEY`: Cheie cu durată scurtă, limitată la rolul implicit de funcție al aplicației. + +Notițe: + +* Nu trebuie să transmiteți URL-ul sau cheia API către clientul generat. Acesta citește `TWENTY_API_URL` și `TWENTY_API_KEY` din process.env la runtime. +* Permisiunile cheii API sunt determinate de rolul referențiat în `application-config.ts` prin `defaultRoleUniversalIdentifier`. Acesta este rolul implicit folosit de funcțiile de logică ale aplicației. +* Aplicațiile pot defini roluri pentru a urma principiul celui mai mic privilegiu. Acordați doar permisiunile de care au nevoie funcțiile, apoi setați `defaultRoleUniversalIdentifier` la identificatorul universal al acelui rol. + +#### Încărcarea fișierelor + +Clientul `MetadataApiClient` generat include o metodă `uploadFile` pentru atașarea fișierelor la câmpuri de tip fișier ale obiectelor din spațiul tău de lucru. Deoarece clienții GraphQL standard nu acceptă în mod nativ încărcarea fișierelor multipart, clientul oferă această metodă dedicată care implementează, sub capotă, [specificația cererilor GraphQL multipart](https://github.com/jaydenseric/graphql-multipart-request-spec). + +```typescript +import { MetadataApiClient } from 'twenty-sdk/generated'; +import * as fs from 'fs'; + +const metadataClient = new MetadataApiClient(); + +const fileBuffer = fs.readFileSync('./invoice.pdf'); + +const uploadedFile = await metadataClient.uploadFile( + fileBuffer, // file contents as a Buffer + 'invoice.pdf', // filename + 'application/pdf', // MIME type (defaults to 'application/octet-stream') + '58a0a314-d7ea-4865-9850-7fb84e72f30b', // field universal identifier +); + +console.log(uploadedFile); +// { id: '...', path: '...', size: 12345, createdAt: '...', url: 'https://...' } +``` + +Semnătura metodei: + +```typescript +uploadFile( + fileBuffer: Buffer, + filename: string, + contentType: string, + fieldMetadataUniversalIdentifier: string, +): Promise<{ id: string; path: string; size: number; createdAt: string; url: string }> +``` + +| Parametru | Tip | Descriere | +| ---------------------------------- | -------- | ------------------------------------------------------------------------------------------- | +| `fileBuffer` | `Buffer` | Conținutul brut al fișierului | +| `filename` | `string` | Numele fișierului (folosit pentru stocare și afișare) | +| `contentType` | `string` | Tipul MIME al fișierului (are valoarea implicită `application/octet-stream` dacă este omis) | +| `fieldMetadataUniversalIdentifier` | `string` | `universalIdentifier` al câmpului de tip fișier de pe obiectul tău | + +Puncte cheie: + +* Metoda `uploadFile` este disponibilă pe `MetadataApiClient` deoarece mutația de încărcare este rezolvată de endpointul `/metadata`. +* Folosește `universalIdentifier` al câmpului (nu ID-ul specific spațiului de lucru), astfel încât codul tău de încărcare funcționează în orice spațiu de lucru în care aplicația ta este instalată — în concordanță cu modul în care aplicațiile fac referire la câmpuri în rest. +* `url` returnat este un URL semnat pe care îl poți folosi pentru a accesa fișierul încărcat. + +### Exemplu Hello World + +Explorați un exemplu minim, cap la cap, care demonstrează obiecte, funcții de logică, componente Front și declanșatoare multiple [aici](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/hello-world). diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/getting-started.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/getting-started.mdx new file mode 100644 index 0000000000..c0670a40ea --- /dev/null +++ b/packages/twenty-docs/l/ro/developers/extend/apps/getting-started.mdx @@ -0,0 +1,233 @@ +--- +title: Începeți +description: Creați prima dvs. aplicație Twenty în câteva minute. +--- + + +Aplicațiile sunt în prezent în testare alfa. Caracteristica funcționează, dar este încă în dezvoltare. + + +Aplicațiile vă permit să extindeți Twenty cu obiecte personalizate, câmpuri, funcții logice, abilități IA și componente UI — toate gestionate ca cod. + +**Ce puteți face astăzi:** + +* Definiți obiecte și câmpuri personalizate sub formă de cod (model de date gestionat) +* Construiți funcții logice cu declanșatoare personalizate (rute HTTP, cron, evenimente ale bazei de date) +* Definiți abilități pentru agenți de IA +* Construiți componente front-end care se afișează în interfața Twenty +* Implementați aceeași aplicație în mai multe spații de lucru + +## Cerințe + +* Node.js 24+ și Yarn 4 +* Un spațiu de lucru Twenty și o cheie API (creați una la https://app.twenty.com/settings/api-webhooks) + +## Începeți + +Creați o aplicație nouă folosind generatorul oficial, apoi autentificați-vă și începeți să dezvoltați: + +```bash filename="Terminal" +# Scaffold a new app (includes all examples by default) +npx create-twenty-app@latest my-twenty-app +cd my-twenty-app + +# Start dev mode: automatically syncs local changes to your workspace +yarn twenty app:dev +``` + +Generatorul de schelet acceptă două moduri pentru a controla ce fișiere de exemplu sunt incluse: + +```bash filename="Terminal" +# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item, skill) +npx create-twenty-app@latest my-app + +# Minimal: only core files (application-config.ts and default-role.ts) +npx create-twenty-app@latest my-app --minimal +``` + +De aici puteți: + +```bash filename="Terminal" +# Add a new entity to your application (guided) +yarn twenty entity:add + +# Watch your application's function logs +yarn twenty function:logs + +# Execute a function by name +yarn twenty function:execute -n my-function -p '{"name": "test"}' + +# Execute the pre-install function +yarn twenty function:execute --preInstall + +# Execute the post-install function +yarn twenty function:execute --postInstall + +# Uninstall the application from the current workspace +yarn twenty app:uninstall + +# Display commands' help +yarn twenty help +``` + +Consultați și: paginile de referință CLI pentru [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) și [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk). + +## Structura proiectului (generată) + +Când rulați `npx create-twenty-app@latest my-twenty-app`, generatorul: + +* Copiază o aplicație de bază minimală în `my-twenty-app/` +* Adaugă o dependență locală `twenty-sdk` și configurația Yarn 4 +* Creează fișiere de configurare și scripturi conectate la CLI-ul `twenty` +* Generează fișierele de bază (configurația aplicației, rolul implicit al funcțiilor, funcțiile de pre-instalare și post-instalare) plus fișiere de exemplu în funcție de modul de generare a scheletului. + +O aplicație proaspăt generată cu modul implicit `--exhaustive` arată astfel: + +```text filename="my-twenty-app/" +my-twenty-app/ + package.json + yarn.lock + .gitignore + .nvmrc + .yarnrc.yml + .yarn/ + install-state.gz + .oxlintrc.json + tsconfig.json + README.md + public/ # Public assets folder (images, fonts, etc.) + src/ + ├── application-config.ts # Required - main application configuration + ├── roles/ + │ └── default-role.ts # Default role for logic functions + ├── objects/ + │ └── example-object.ts # Example custom object definition + ├── fields/ + │ └── example-field.ts # Example standalone field definition + ├── logic-functions/ + │ ├── hello-world.ts # Example logic function + │ ├── pre-install.ts # Pre-install logic function + │ └── post-install.ts # Post-install logic function + ├── front-components/ + │ └── hello-world.tsx # Example front component + ├── views/ + │ └── example-view.ts # Example saved view definition + ├── navigation-menu-items/ + │ └── example-navigation-menu-item.ts # Example sidebar navigation link + └── skills/ + └── example-skill.ts # Example AI agent skill definition +``` + +Cu `--minimal`, sunt create doar fișierele de bază (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` și `logic-functions/post-install.ts`). + +Pe scurt: + +* **package.json**: Declară numele aplicației, versiunea, motoarele (Node 24+, Yarn 4) și adaugă `twenty-sdk` plus un script `twenty` care deleagă către CLI-ul local `twenty`. Rulați `yarn twenty help` pentru a lista toate comenzile disponibile. +* **.gitignore**: Ignoră artefacte comune precum `node_modules`, `.yarn`, `generated/` (client tipizat), `dist/`, `build/`, foldere de coverage, fișiere jurnal și fișiere `.env*`. +* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Blochează și configurează lanțul de instrumente Yarn 4 folosit de proiect. +* **.nvmrc**: Fixează versiunea Node.js așteptată de proiect. +* **.oxlintrc.json** și **tsconfig.json**: Oferă linting și configurație TypeScript pentru fișierele TypeScript ale aplicației. +* **README.md**: Un README scurt în rădăcina aplicației, cu instrucțiuni de bază. +* **public/**: Un folder pentru stocarea resurselor publice (imagini, fonturi, fișiere statice) care vor fi servite împreună cu aplicația dvs. Fișierele plasate aici sunt încărcate în timpul sincronizării și sunt accesibile la rulare. +* **src/**: Locul principal unde vă definiți aplicația sub formă de cod + +### Detectarea entităților + +SDK-ul detectează entitățile analizând fișierele TypeScript pentru apeluri **`export default define({...})`**. Fiecare tip de entitate are o funcție ajutătoare corespunzătoare, exportată din `twenty-sdk`: + +| Funcție ajutătoare | Tipul entității | +| -------------------------------- | -------------------------------------------------------------- | +| `defineObject` | Definiții de obiecte personalizate | +| `defineLogicFunction` | Definiții de funcții de logică | +| `definePreInstallLogicFunction` | Funcție logică de pre-instalare (rulează înainte de instalare) | +| `definePostInstallLogicFunction` | Funcție logică post-instalare (rulează după instalare) | +| `defineFrontComponent` | Definiții ale componentelor de interfață | +| `defineRole` | Definiții de rol | +| `defineField` | Extensii de câmp pentru obiectele existente | +| `defineView` | Definiții pentru vizualizări salvate | +| `defineNavigationMenuItem` | Definiții pentru elemente de meniu de navigare | +| `defineSkill` | Definiții ale abilităților agentului IA | + + +**Denumirea fișierelor este flexibilă.** Detectarea entităților se bazează pe AST — SDK-ul scanează fișierele sursă pentru tiparul `export default define({...})`. Puteți organiza fișierele și folderele cum doriți. Gruparea după tipul de entitate (de exemplu, `logic-functions/`, `roles/`) este doar o convenție pentru organizarea codului, nu o cerință. + + +Exemplu de entitate detectată: + +```typescript +// This file can be named anything and placed anywhere in src/ +import { defineObject, FieldType } from 'twenty-sdk'; + +export default defineObject({ + universalIdentifier: '...', + nameSingular: 'postCard', + // ... rest of config +}); +``` + +Comenzile ulterioare vor adăuga mai multe fișiere și foldere: + +* `yarn twenty app:dev` va genera automat doi clienți API tipizați în `node_modules/twenty-sdk/generated`: `CoreApiClient` (pentru datele spațiului de lucru prin `/graphql`) și `MetadataApiClient` (pentru configurarea spațiului de lucru și încărcarea fișierelor prin `/metadata`). +* `yarn twenty entity:add` va adăuga fișiere de definire a entităților în `src/` pentru obiectele, funcțiile, componentele front-end, rolurile, abilitățile și altele. + +## Autentificare + +Prima dată când rulați `yarn twenty auth:login`, vi se vor solicita: + +* URL-ul API (implicit http://localhost:3000 sau profilul spațiului de lucru curent) +* Cheie API + +Acreditările dvs. sunt stocate per utilizator în `~/.twenty/config.json`. Puteți menține mai multe profiluri și comuta între ele. + +### Gestionarea spațiilor de lucru + +```bash filename="Terminal" +# Login interactively (recommended) +yarn twenty auth:login + +# Login to a specific workspace profile +yarn twenty auth:login --workspace my-custom-workspace + +# List all configured workspaces +yarn twenty auth:list + +# Switch the default workspace (interactive) +yarn twenty auth:switch + +# Switch to a specific workspace +yarn twenty auth:switch production + +# Check current authentication status +yarn twenty auth:status +``` + +După ce ați schimbat spațiul de lucru cu `yarn twenty auth:switch`, toate comenzile ulterioare vor folosi implicit acel spațiu de lucru. Îl puteți totuși suprascrie temporar cu `--workspace `. + +## Configurare manuală (fără generator) + +Deși recomandăm utilizarea `create-twenty-app` pentru cea mai bună experiență de început, puteți configura și un proiect manual. Nu instalați CLI-ul global. În schimb, adăugați `twenty-sdk` ca dependență locală și conectați un singur script în package.json-ul dvs.: + +```bash filename="Terminal" +yarn add -D twenty-sdk +``` + +Apoi adăugați un script `twenty`: + +```json filename="package.json" +{ + "scripts": { + "twenty": "twenty" + } +} +``` + +Acum puteți rula toate comenzile prin `yarn twenty `, de ex. `yarn twenty app:dev`, `yarn twenty help`, etc. + +## Depanare + +* Erori de autentificare: rulați `yarn twenty auth:login` și asigurați-vă că cheia API are permisiunile necesare. +* Nu se poate conecta la server: verificați URL-ul API și că serverul Twenty este accesibil. +* Tipuri sau client lipsă/învechite: reporniți `yarn twenty app:dev` — acesta generează automat clientul tipizat. +* Modul dev nu sincronizează: asigurați-vă că `yarn twenty app:dev` rulează și că modificările nu sunt ignorate de mediul dvs. + +Canal de ajutor pe Discord: https://discord.com/channels/1130383047699738754/1130386664812982322 diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/publishing.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/publishing.mdx new file mode 100644 index 0000000000..42624544d4 --- /dev/null +++ b/packages/twenty-docs/l/ro/developers/extend/apps/publishing.mdx @@ -0,0 +1,119 @@ +--- +title: Publicare +description: Distribuie aplicația ta Twenty în marketplace sau implementeaz-o intern. +--- + + +Aplicațiile sunt în prezent în testare alfa. Caracteristica funcționează, dar este încă în dezvoltare. + + +## Prezentare generală + +După ce aplicația ta este [construită și testată local](/l/ro/developers/extend/apps/building), ai două căi pentru distribuire: + +* **Publică pe npm** — listează aplicația ta în marketplace-ul Twenty pentru ca orice spațiu de lucru să o poată descoperi și instala. +* **Trimite un tarball** — implementează aplicația ta pe un server Twenty specific pentru utilizare internă, fără a o face disponibilă public. + +## Publicarea pe npm + +Publicarea pe npm face ca aplicația ta să poată fi descoperită în marketplace-ul Twenty. Orice spațiu de lucru Twenty poate răsfoi, instala și actualiza aplicațiile din marketplace direct din interfață. + +### Cerințe + +* Un cont [npm](https://www.npmjs.com) +* Numele pachetului tău **trebuie** să folosească prefixul `twenty-app-` (de ex., `twenty-app-postcard-sender`) + +### Pași + +1. **Construiește-ți aplicația** — CLI compilează sursele TypeScript și generează manifestul aplicației: + +```bash filename="Terminal" +yarn twenty app:build +``` + +2. **Publică pe npm** — publică pachetul construit în registrul npm: + +```bash filename="Terminal" +npx twenty app:publish +``` + +### Descoperire automată + +Pachetele cu prefixul `twenty-app-` sunt descoperite automat de catalogul marketplace-ului Twenty. După publicare, aplicația ta apare în marketplace în câteva minute — fără înregistrare manuală sau aprobare necesară. + +### Publicare CI + +Proiectul generat include un workflow GitHub Actions care publică la fiecare lansare. Acesta rulează `app:build`, apoi `npm publish --provenance` din rezultatul build-ului: + +```yaml filename=".github/workflows/publish.yml" +name: Publish +on: + release: + types: [published] + +permissions: + contents: read + id-token: write + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "24" + registry-url: https://registry.npmjs.org + - run: yarn install --immutable + - run: npx twenty app:build + - run: npm publish --provenance --access public + working-directory: .twenty/output + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} +``` + +Pentru alte sisteme CI (GitLab CI, CircleCI etc.), se aplică aceleași trei comenzi: `yarn install`, `npx twenty app:build`, apoi `npm publish` din `.twenty/output`. + + +**npm provenance** este opțională, dar recomandată. Publicarea cu `--provenance` adaugă un badge de încredere la listarea ta în npm, permițând utilizatorilor să verifice că pachetul a fost construit dintr-un commit specific într-un pipeline CI public. Vezi [documentația npm provenance](https://docs.npmjs.com/generating-provenance-statements) pentru instrucțiuni de configurare. + + +## Distribuire internă + +Pentru aplicațiile pe care nu le dorești disponibile public — instrumente proprietare, integrări doar pentru enterprise sau build-uri experimentale — poți trimite un tarball direct pe un server Twenty. + +### Trimite un tarball + +Construiește-ți aplicația și implementeaz-o pe un server specific, într-un singur pas: + +```bash filename="Terminal" +npx twenty app:publish --server +``` + +Orice spațiu de lucru de pe acel server poate apoi instala și actualiza aplicația din pagina de setări **Applications**. + +### Gestionarea versiunilor + +Pentru a lansa o actualizare: + +1. Actualizează câmpul `version` din `package.json` +2. Trimite un tarball nou cu `npx twenty app:publish --server ` +3. Spațiile de lucru de pe acel server vor vedea actualizarea disponibilă în setările lor + + +Aplicațiile interne sunt limitate la serverul pe care sunt trimise. Acestea nu vor apărea în marketplace-ul public și nu pot fi instalate de spațiile de lucru de pe alte servere. + + +## Categorii de aplicații + +Twenty organizează aplicațiile în trei categorii, în funcție de modul în care sunt distribuite: + +| Categorie | Cum funcționează | Vizibilă în marketplace? | +| -------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| **Dezvoltare** | Aplicații în modul de dezvoltare local, rulate prin `yarn twenty app:dev`. Folosite pentru construire și testare. | Nu | +| **Publicat** | Aplicații publicate pe npm cu prefixul `twenty-app-`. Listate în marketplace pentru ca orice spațiu de lucru să le poată instala. | Da | +| **Intern** | Aplicații implementate prin tarball pe un server specific. Disponibile doar pentru spațiile de lucru de pe acel server. | Nu | + + +Pornește în modul **Dezvoltare** în timp ce îți construiești aplicația. Când este gata, alege **Publicat** (npm) pentru distribuire largă sau **Intern** (tarball) pentru implementare privată. + diff --git a/packages/twenty-docs/l/ro/developers/extend/extend.mdx b/packages/twenty-docs/l/ro/developers/extend/extend.mdx index dbc74980d9..890667ef0b 100644 --- a/packages/twenty-docs/l/ro/developers/extend/extend.mdx +++ b/packages/twenty-docs/l/ro/developers/extend/extend.mdx @@ -1,7 +1,6 @@ --- title: Extindeți description: Extindeți funcționalitatea Twenty cu API-uri, webhook-uri și aplicații personalizate. -redirect: /developers/introduction --- @@ -16,18 +15,18 @@ Twenty este conceput pentru a fi extensibil. Utilizați API-urile noastre, webho * **API-uri**: Interogați și modificați programatic datele din CRM folosind REST sau GraphQL * **Webhook-uri**: Primiți notificări în timp real când au loc evenimente în Twenty -* **Aplicații**: Creați aplicații personalizate care extind capabilitățile Twenty - În curând! +* **Aplicații**: Creați aplicații personalizate care extind capabilitățile Twenty ## Începeți - + Conectați-vă programatic la Twenty - + Primiți notificări despre evenimente în timp real - - Construiți personalizări sub formă de cod (Alpha) + + Construiți personalizări sub formă de cod diff --git a/packages/twenty-docs/l/ro/developers/extend/webhooks.mdx b/packages/twenty-docs/l/ro/developers/extend/webhooks.mdx new file mode 100644 index 0000000000..4ba1237a21 --- /dev/null +++ b/packages/twenty-docs/l/ro/developers/extend/webhooks.mdx @@ -0,0 +1,116 @@ +--- +title: Webhooks +description: Primiți notificări în timp real atunci când au loc evenimente în CRM-ul dvs. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +Webhook-urile trimit date către sistemele dvs. în timp real atunci când au loc evenimente în Twenty — nu este necesară interogarea periodică. Folosiți-le pentru a menține sistemele externe sincronizate, a declanșa automatizări sau a trimite alerte. + +## Creați un webhook + +1. Mergeți la **Setări → API-uri și Webhooks → Webhooks** +2. Faceți clic pe **+ Creează webhook** +3. Introduceți URL-ul webhook-ului dvs. (trebuie să fie accesibil public) +4. Faceți clic pe **Salvează** + +Webhook-ul se activează imediat și începe să trimită notificări. + + + +### Gestionați webhook-urile + +**Editează**: Faceți clic pe webhook → Actualizați URL-ul → **Salvează** + +**Șterge**: Faceți clic pe webhook → **Șterge** → Confirmă + +## Evenimente + +Twenty trimite webhook-uri pentru aceste tipuri de evenimente: + +| Eveniment | Exemplu | +| ---------------------------- | ---------------------------------------------------------- | +| **Înregistrare creată** | `person.created`, `company.created`, `note.created` | +| **Înregistrare actualizată** | `person.updated`, `company.updated`, `opportunity.updated` | +| **Înregistrare ștearsă** | `person.deleted`, `company.deleted` | + +Toate tipurile de evenimente sunt trimise către URL-ul webhook-ului dvs. Filtrarea evenimentelor poate fi adăugată în versiunile viitoare. + +## Formatul payload-ului + +Fiecare webhook trimite un HTTP POST cu un corp JSON: + +```json +{ + "event": "person.created", + "data": { + "id": "abc12345", + "firstName": "Alice", + "lastName": "Doe", + "email": "alice@example.com", + "createdAt": "2025-02-10T15:30:45Z", + "createdBy": "user_123" + }, + "timestamp": "2025-02-10T15:30:50Z" +} +``` + +| Câmp | Descriere | +| ----------- | ------------------------------------------------------------- | +| `event` | Ce s-a întâmplat (de ex., `person.created`) | +| `data` | Înregistrarea completă care a fost creată/actualizată/ștearsă | +| `timestamp` | Când a avut loc evenimentul (UTC) | + + +Răspundeți cu un **status HTTP 2xx** (200-299) pentru a confirma primirea. Răspunsurile non-2xx sunt înregistrate ca eșecuri de livrare. + + +## Validarea Webhook-ului + +Twenty semnează fiecare cerere webhook din motive de securitate. Validați semnăturile pentru a vă asigura că cererile sunt autentice. + +### Anteturi + +| Antet | Descriere | +| ---------------------------- | -------------------------- | +| `X-Twenty-Webhook-Signature` | Semnătură HMAC SHA256 | +| `X-Twenty-Webhook-Timestamp` | Marcaj temporal al cererii | + +### Pași de validare + +1. Obțineți marcajul temporal din `X-Twenty-Webhook-Timestamp` +2. Creați șirul: `{timestamp}:{JSON payload}` +3. Calculați HMAC SHA256 folosind secretul webhook-ului dvs. +4. Comparați cu `X-Twenty-Webhook-Signature` + +### Exemplu (Node.js) + +```javascript +const crypto = require("crypto"); + +const timestamp = req.headers["x-twenty-webhook-timestamp"]; +const payload = JSON.stringify(req.body); +const secret = "your-webhook-secret"; + +const stringToSign = `${timestamp}:${payload}`; +const expectedSignature = crypto + .createHmac("sha256", secret) + .update(stringToSign) + .digest("hex"); + +const receivedSignature = req.headers["x-twenty-webhook-signature"]; +const isValid = crypto.timingSafeEqual( + Buffer.from(expectedSignature, "hex"), + Buffer.from(receivedSignature, "hex") +); +``` + +## Webhook-uri vs Fluxuri de lucru + +| Metodă | Direcție | Caz de utilizare | +| ------------------------------------------ | -------- | -------------------------------------------------------------------------------- | +| **Webhook-uri** | OUT | Notificați automat sistemele externe despre orice modificare a unei înregistrări | +| **Flux de lucru + Cerere HTTP** | OUT | Trimiteți date în exterior cu logică personalizată (filtre, transformări) | +| **Declanșator webhook în fluxul de lucru** | IN | Primiți date în Twenty din sisteme externe | + +Pentru a primi date externe, consultați [Configurați un declanșator Webhook](/l/ro/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger). diff --git a/packages/twenty-docs/l/ro/developers/introduction.mdx b/packages/twenty-docs/l/ro/developers/introduction.mdx index 26b6fc2c9b..da91ecdbc3 100644 --- a/packages/twenty-docs/l/ro/developers/introduction.mdx +++ b/packages/twenty-docs/l/ro/developers/introduction.mdx @@ -5,28 +5,18 @@ description: Bun venit la Documentația Twenty pentru dezvoltatori, resursa dvs. import { CardTitle } from "/snippets/card-title.mdx" - - - API - Interogați și modificați datele CRM cu REST sau GraphQL. + + + Extindeți + Creați integrări cu API-uri, webhook-uri și aplicații personalizate. - - Webhooks - Primiți notificări în timp real când se produc evenimente. - - - - Apps - Creați aplicații personalizate care extind capacitățile Twenty. - - - + Autogăzduire Implementați și gestionați Twenty pe propria infrastructură. - + Contribuiți Alăturați-vă comunității noastre cu sursă deschisă și contribuiți la Twenty. diff --git a/packages/twenty-docs/l/ro/user-guide/data-migration/how-tos/export-your-data.mdx b/packages/twenty-docs/l/ro/user-guide/data-migration/how-tos/export-your-data.mdx index 554fb9cc3b..2e0a95fa37 100644 --- a/packages/twenty-docs/l/ro/user-guide/data-migration/how-tos/export-your-data.mdx +++ b/packages/twenty-docs/l/ro/user-guide/data-migration/how-tos/export-your-data.mdx @@ -24,7 +24,7 @@ Exportați datele spațiului de lucru în CSV pentru copii de siguranță, rapor * Sunt exportate doar **coloanele vizibile** * Sunt exportate doar **înregistrările filtrate** (pe baza vizualizării curente) -Pentru exporturi mai mari (20.000+ înregistrări), utilizați filtre pentru a exporta în loturi sau folosiți [API](/l/ro/developers/api). +Pentru exporturi mai mari (20.000+ înregistrări), utilizați filtre pentru a exporta în loturi sau folosiți [API](/l/ro/developers/extend/api). ### Permisiuni @@ -148,7 +148,7 @@ API-ul nu are limită de înregistrări: 2. Utilizați API-ul GraphQL pentru a interoga înregistrări 3. Procesați rezultatele în aplicația dvs. -Consultați: [Documentație API](/l/ro/developers/api) +Consultați: [Documentație API](/l/ro/developers/extend/api) ## Sfaturi și bune practici @@ -206,4 +206,4 @@ Fișierele exportate pot conține date sensibile: * [Cum să actualizați înregistrările existente](/l/ro/user-guide/data-migration/how-tos/update-existing-records-via-import) — editați și reimportați exportul * [Cum să importați date prin API](/l/ro/user-guide/data-migration/how-tos/import-data-via-api) — pentru seturi de date mari -* [Documentație API](/l/ro/developers/api) — creați fluxuri de lucru de export personalizate +* [Documentație API](/l/ro/developers/extend/api) — creați fluxuri de lucru de export personalizate diff --git a/packages/twenty-docs/l/ro/user-guide/data-migration/how-tos/import-data-via-api.mdx b/packages/twenty-docs/l/ro/user-guide/data-migration/how-tos/import-data-via-api.mdx index 9b1bcf8581..b2e569e835 100644 --- a/packages/twenty-docs/l/ro/user-guide/data-migration/how-tos/import-data-via-api.mdx +++ b/packages/twenty-docs/l/ro/user-guide/data-migration/how-tos/import-data-via-api.mdx @@ -57,10 +57,10 @@ Oricine are cheia dvs. API poate accesa și modifica datele din spațiul dvs. de Twenty acceptă două tipuri de API: -| API | Cel mai potrivit pentru | Documentație | -| ----------- | --------------------------------------------------------------------- | -------------------------------------------------------- | -| **GraphQL** | Interogări flexibile, preluarea datelor asociate, operațiuni complexe | [Documentație API](/l/ro/developers/api) | -| **REST** | Operațiuni CRUD simple, tipare REST familiare | [Documentație API](/l/ro/developers/api) | +| API | Cel mai potrivit pentru | Documentație | +| ----------- | --------------------------------------------------------------------- | ------------------------------------------ | +| **GraphQL** | Interogări flexibile, preluarea datelor asociate, operațiuni complexe | [Documentație API](/l/ro/developers/extend/api) | +| **REST** | Operațiuni CRUD simple, tipare REST familiare | [Documentație API](/l/ro/developers/extend/api) | Ambele API-uri acceptă: @@ -173,4 +173,4 @@ Contactați-ne la [contact@twenty.com](mailto:contact@twenty.com) sau explorați Pentru detalii complete de implementare, exemple de cod și referință de schemă: -* [Documentație API](/l/ro/developers/api) +* [Documentație API](/l/ro/developers/extend/api) diff --git a/packages/twenty-docs/l/ro/user-guide/getting-started/capabilities/what-is-twenty.mdx b/packages/twenty-docs/l/ro/user-guide/getting-started/capabilities/what-is-twenty.mdx index 7ea47b6e8a..fdd664027c 100644 --- a/packages/twenty-docs/l/ro/user-guide/getting-started/capabilities/what-is-twenty.mdx +++ b/packages/twenty-docs/l/ro/user-guide/getting-started/capabilities/what-is-twenty.mdx @@ -35,7 +35,7 @@ Open-source este fundamentul abordării noastre, asigurându-ne că Twenty evolu * **Tablouri de bord:** Urmăriți performanța cu rapoarte și vizualizări personalizate. [Vizualizați tablourile de bord](/l/ro/user-guide/dashboards/overview). * **Permisiuni și acces:** Controlați cine poate vizualiza, edita și gestiona datele dvs. cu permisiuni bazate pe roluri. [Configurați accesul](/l/ro/user-guide/permissions-access/overview). * **Note și sarcini:** Creați note și sarcini legate de înregistrările dvs. pentru o colaborare mai bună. -* **API și Webhooks:** Conectați-vă la alte aplicații și creați integrări personalizate. [Începeți integrarea](/l/ro/developers/api). +* **API și Webhooks:** Conectați-vă la alte aplicații și creați integrări personalizate. [Începeți integrarea](/l/ro/developers/extend/api). ## Alătură-te acum diff --git a/packages/twenty-docs/l/ro/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx b/packages/twenty-docs/l/ro/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx index c408ebaa44..511a30a868 100644 --- a/packages/twenty-docs/l/ro/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx +++ b/packages/twenty-docs/l/ro/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx @@ -95,7 +95,7 @@ Creați câmpurile destinație în **Settings → Data Model → Opportunities** * Dimensiunea Companiei: `{{searchRecords[0].employees}}` -**Limitare Tasks and Notes**: Relațiile pentru Tasks și Notes sunt codificate ca many-to-many și nu sunt încă disponibile în declanșatoare sau acțiuni de flux de lucru. Pentru a accesa aceste relații, utilizați [API-ul](/l/ro/developers/api) în schimb. +**Limitare Tasks and Notes**: Relațiile pentru Tasks și Notes sunt codificate ca many-to-many și nu sunt încă disponibile în declanșatoare sau acțiuni de flux de lucru. Pentru a accesa aceste relații, utilizați [API-ul](/l/ro/developers/extend/api) în schimb. ## Sincronizare bidirecțională diff --git a/packages/twenty-docs/l/ru/developers/extend/api.mdx b/packages/twenty-docs/l/ru/developers/extend/api.mdx new file mode 100644 index 0000000000..6364fe68ac --- /dev/null +++ b/packages/twenty-docs/l/ru/developers/extend/api.mdx @@ -0,0 +1,147 @@ +--- +title: API +description: Запрашивайте и изменяйте данные CRM программно с помощью REST или GraphQL. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +Twenty разработан для удобства разработчиков и предлагает мощные API, которые адаптируются к вашей пользовательской модели данных. Мы предоставляем четыре различных типа API, чтобы удовлетворить различные интеграционные потребности. + +## Подход, ориентированный на разработчиков + +Twenty генерирует API специально для вашей модели данных: + +* **Длинные ID не требуются**: используйте названия объектов и полей прямо в конечных точках. +* **Стандартные и пользовательские объекты обрабатываются одинаково**: ваши пользовательские объекты получают такой же доступ к API, как и встроенные. +* **Выделенные конечные точки**: каждый объект и поле получают свою собственную конечную точку API. +* **Пользовательская документация**: генерируется специально для модели данных вашего рабочего пространства. + + +Персонализированная документация по вашему API доступна в разделе **Настройки → API и вебхуки** после создания ключа API. Поскольку Twenty генерирует API, соответствующие вашей пользовательской модели данных, документация уникальна для вашего рабочего пространства. + + +## Два типа API + +### Основной API + +Доступен на `/rest/` или `/graphql/` + +Работайте с реальными **записями** (данными): + +* Создавайте, читайте, обновляйте и удаляйте People, Companies, Opportunities и т. д. +* Запрашивайте и фильтруйте данные +* Управление отношениями записей. + +### API метаданных + +Доступен на `/rest/metadata/` или `/metadata/` + +Управляйте своим **рабочим пространством и моделью данных**: + +* Создание, изменение или удаление объектов и полей. +* Настройка параметров рабочего пространства. +* Определяйте связи между объектами + +## REST против GraphQL + +И Core, и Metadata API доступны в форматах REST и GraphQL: + +| Формат | Доступные операции | +| ----------- | ------------------------------------------------------------------------ | +| **REST** | CRUD, пакетные операции, upsert-операции | +| **GraphQL** | То же самое + **пакетные upsert-операции**, запросы связей за один вызов | + +Выбирайте по своим потребностям — оба формата обращаются к одним и тем же данным. + +## Конечные точки API + +| Среда | Базовый URL | +| --------------------------- | ------------------------- | +| **Облако** | `https://api.twenty.com/` | +| **Самостоятельный хостинг** | `https://{your-domain}/` | + +## Аутентификация + +Каждый запрос к API требует ключ API в заголовке: + +``` +Authorization: Bearer YOUR_API_KEY +``` + +### Создать ключ API + +1. Перейдите в **Настройки → API и вебхуки** +2. Нажмите **+ Создать ключ** +3. Настройки: + * **Имя**: описательное название для ключа + * **Дата истечения**: когда истекает срок действия ключа +4. Нажмите **Сохранить** +5. **Скопируйте сразу** — ключ показывается только один раз + + + + +Ваш ключ API предоставляет доступ к конфиденциальным данным. Не делитесь им с ненадежными сервисами. Если он скомпрометирован, немедленно отключите его и создайте новый. + + +### Назначить роль ключу API + +Для повышения безопасности назначьте конкретную роль, чтобы ограничить доступ: + +1. Перейдите в **Настройки → Роли** +2. Нажмите на роль, которую хотите назначить +3. Откройте вкладку **Назначение** +4. В разделе **Ключи API** нажмите **+ Назначить ключу API** +5. Выберите ключ API + +Ключ унаследует разрешения этой роли. См. [Разрешения](/l/ru/user-guide/permissions-access/capabilities/permissions) для подробностей. + +### Управление API-ключами + +**Сгенерировать заново**: Настройки → API и вебхуки → Нажмите на ключ → **Сгенерировать заново** + +**Удалить**: Настройки → API и вебхуки → Нажмите ключ → **Удалить** + +## Песочница API + +Тестируйте свои API прямо в браузере с нашей встроенной песочницей — доступной как для **REST**, так и для **GraphQL**. + +### Доступ к песочнице + +1. Перейдите в **Настройки → API и вебхуки** +2. Создайте ключ API (обязательно) +3. Нажмите на **REST API** или **GraphQL API**, чтобы открыть песочницу + +### Что вы получаете + +* **Интерактивная документация**: генерируется для вашей конкретной модели данных +* **Тестирование в реальном времени**: выполняйте реальные вызовы API к вашему рабочему пространству +* **Обозреватель схемы**: просматривайте доступные объекты, поля и связи +* **Конструктор запросов**: создавайте запросы с автодополнением + +Песочница отражает ваши пользовательские объекты и поля, поэтому документация всегда точна для вашего рабочего пространства. + +## Пакетные операции + +И REST, и GraphQL поддерживают пакетные операции: + +* **Размер пакета**: до 60 записей на запрос. +* **Операции**: создание, обновление, удаление нескольких записей + +**Функции только для GraphQL:** + +* **Пакетный upsert**: создание или обновление за один вызов +* Используйте имена объектов во множественном числе (например, `CreateCompanies` вместо `CreateCompany`) + +## Лимиты скорости + +Запросы к API ограничиваются для обеспечения стабильности платформы: + +| Лимит | Значение | +| ----------------- | ------------------------- | +| **Запросы** | 100 запросов в минуту | +| **Размер пакета** | 60 записей за один запрос | + + +Используйте пакетные операции, чтобы максимизировать пропускную способность — обрабатывайте до 60 записей за один запрос API вместо выполнения отдельных запросов. + diff --git a/packages/twenty-docs/l/ru/developers/extend/apps/building.mdx b/packages/twenty-docs/l/ru/developers/extend/apps/building.mdx new file mode 100644 index 0000000000..c6dd6aa8aa --- /dev/null +++ b/packages/twenty-docs/l/ru/developers/extend/apps/building.mdx @@ -0,0 +1,689 @@ +--- +title: Создание приложений +description: Определяйте объекты, функции логики, компоненты фронтенда и многое другое с помощью Twenty SDK. +--- + + +Приложения сейчас проходят альфа-тестирование. Функциональность работает, но продолжает развиваться. + + +## Используйте ресурсы SDK (типы и конфигурация) + +Пакет twenty-sdk предоставляет типизированные строительные блоки и вспомогательные функции, которые вы используете внутри своего приложения. Ниже — ключевые части, с которыми вы будете работать чаще всего. + +### Вспомогательные функции + +SDK предоставляет вспомогательные функции для определения сущностей вашего приложения. Как описано в [Обнаружение сущностей](/l/ru/developers/extend/apps/getting-started#entity-detection), вы должны использовать `export default define({...})`, чтобы ваши сущности были обнаружены: + +| Функция | Назначение | +| -------------------------------- | ------------------------------------------------------------------------ | +| `defineApplication` | Настройка метаданных приложения (обязательно, по одному на приложение) | +| `defineObject` | Определяет пользовательские объекты с полями | +| `defineLogicFunction` | Определение логических функций с обработчиками | +| `definePreInstallLogicFunction` | Определяет предустановочную логическую функцию (по одной на приложение) | +| `definePostInstallLogicFunction` | Определяет послеустановочную логическую функцию (по одной на приложение) | +| `defineFrontComponent` | Определение фронт-компонентов для настраиваемого интерфейса | +| `defineRole` | Настраивает права роли и доступ к объектам | +| `defineField` | Расширение существующих объектов дополнительными полями | +| `defineView` | Определяйте сохранённые представления для объектов | +| `defineNavigationMenuItem` | Определяйте ссылки боковой панели навигации | +| `defineSkill` | Определение навыков агента ИИ | + +Эти функции проверяют вашу конфигурацию на этапе сборки и обеспечивают автодополнение в IDE и безопасность типов. + +### Определение объектов + +Пользовательские объекты описывают как схему, так и поведение записей в вашем рабочем пространстве. Используйте `defineObject()` для определения объектов со встроенной валидацией: + +```typescript +// src/app/postCard.object.ts +import { defineObject, FieldType } from 'twenty-sdk'; + +enum PostCardStatus { + DRAFT = 'DRAFT', + SENT = 'SENT', + DELIVERED = 'DELIVERED', + RETURNED = 'RETURNED', +} + +export default defineObject({ + universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05', + nameSingular: 'postCard', + namePlural: 'postCards', + labelSingular: 'Post Card', + labelPlural: 'Post Cards', + description: 'A post card object', + icon: 'IconMail', + fields: [ + { + universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b', + name: 'content', + type: FieldType.TEXT, + label: 'Content', + description: "Postcard's content", + icon: 'IconAbc', + }, + { + universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac', + name: 'recipientName', + type: FieldType.FULL_NAME, + label: 'Recipient name', + icon: 'IconUser', + }, + { + universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266', + name: 'recipientAddress', + type: FieldType.ADDRESS, + label: 'Recipient address', + icon: 'IconHome', + }, + { + universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e', + name: 'status', + type: FieldType.SELECT, + label: 'Status', + icon: 'IconSend', + defaultValue: `'${PostCardStatus.DRAFT}'`, + options: [ + { value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' }, + { value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' }, + { value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' }, + { value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' }, + ], + }, + { + universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433', + name: 'deliveredAt', + type: FieldType.DATE_TIME, + label: 'Delivered at', + icon: 'IconCheck', + isNullable: true, + defaultValue: null, + }, + ], +}); +``` + +Основные моменты: + +* Используйте `defineObject()` для встроенной валидации и лучшей поддержки в IDE. +* `universalIdentifier` должен быть уникальным и стабильным между развёртываниями. +* Каждому полю требуются `name`, `type`, `label` и собственный стабильный `universalIdentifier`. +* Массив `fields` необязателен — вы можете определять объекты без пользовательских полей. +* Вы можете сгенерировать новые объекты с помощью `yarn twenty entity:add`, который проведёт вас через настройку имени, полей и связей. + + +**Базовые поля создаются автоматически.** Когда вы определяете пользовательский объект, Twenty автоматически добавляет стандартные поля, +такие как `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` и `deletedAt`. +Вам не нужно определять их в массиве `fields` — добавляйте только свои пользовательские поля. +Вы можете переопределить поля по умолчанию, определив поле с тем же именем в массиве `fields`, +но это не рекомендуется. + + +### Конфигурация приложения (application-config.ts) + +У каждого приложения есть единственный файл `application-config.ts`, который описывает: + +* **Что это за приложение**: идентификаторы, отображаемое имя и описание. +* **Как запускаются его функции**: какую роль они используют для прав доступа. +* **(Необязательно) переменные**: пары ключ-значение, предоставляемые вашим функциям как переменные окружения. +* **(Необязательно) предустановочная функция**: логическая функция, которая запускается до установки приложения. +* **(Необязательно) послеустановочная функция**: функция логики, которая запускается после установки приложения. + +Используйте `defineApplication()` для определения конфигурации вашего приложения: + +```typescript +// src/application-config.ts +import { defineApplication } from 'twenty-sdk'; +import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role'; + +export default defineApplication({ + universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7', + displayName: 'My Twenty App', + description: 'My first Twenty app', + icon: 'IconWorld', + applicationVariables: { + DEFAULT_RECIPIENT_NAME: { + universalIdentifier: '19e94e59-d4fe-4251-8981-b96d0a9f74de', + description: 'Default recipient name for postcards', + value: 'Jane Doe', + isSecret: false, + }, + }, + defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, +}); +``` + +Заметки: + +* `universalIdentifier` — это детерминированные идентификаторы, которыми вы управляете; сгенерируйте их один раз и сохраняйте стабильными между синхронизациями. +* `applicationVariables` становятся переменными окружения для ваших функций (например, `DEFAULT_RECIPIENT_NAME` доступна как `process.env.DEFAULT_RECIPIENT_NAME`). +* `defaultRoleUniversalIdentifier` должен соответствовать файлу роли (см. ниже). +* Предустановочные и послеустановочные функции автоматически обнаруживаются во время сборки манифеста. См. [Предустановочные функции](#pre-install-functions) и [Послеустановочные функции](#post-install-functions). + +#### Роли и разрешения + +Приложения могут определять роли, инкапсулирующие права на объекты и действия в вашем рабочем пространстве. Поле `defaultRoleUniversalIdentifier` в `application-config.ts` обозначает роль по умолчанию, используемую логическими функциями вашего приложения. + +* Ключ API во время выполнения, подставляемый как `TWENTY_API_KEY`, получается из этой роли функции по умолчанию. +* Типизированный клиент будет ограничен правами, предоставленными этой ролью. +* Следуйте принципу наименьших привилегий: создайте отдельную роль только с теми правами, которые нужны вашим функциям, и укажите её универсальный идентификатор. + +##### Роль функции по умолчанию (*.role.ts) + +Когда вы генерируете новое приложение, CLI также создаёт файл роли по умолчанию. Используйте `defineRole()` для определения ролей со встроенной валидацией: + +```typescript +// src/roles/default-role.ts +import { defineRole, PermissionFlag } from 'twenty-sdk'; + +export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = + 'b648f87b-1d26-4961-b974-0908fd991061'; + +export default defineRole({ + universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, + label: 'Default function role', + description: 'Default role for function Twenty client', + canReadAllObjectRecords: false, + canUpdateAllObjectRecords: false, + canSoftDeleteAllObjectRecords: false, + canDestroyAllObjectRecords: false, + canUpdateAllSettings: false, + canBeAssignedToAgents: false, + canBeAssignedToUsers: false, + canBeAssignedToApiKeys: false, + objectPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + canReadObjectRecords: true, + canUpdateObjectRecords: true, + canSoftDeleteObjectRecords: false, + canDestroyObjectRecords: false, + }, + ], + fieldPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + fieldUniversalIdentifier: 'b2c37dc0-8ae7-470e-96cd-1476b47dfaff', + canReadFieldValue: false, + canUpdateFieldValue: false, + }, + ], + permissionFlags: [PermissionFlag.APPLICATIONS], +}); +``` + +Значение `universalIdentifier` этой роли затем указывается в `application-config.ts` как `defaultRoleUniversalIdentifier`. Иными словами: + +* **\*.role.ts** определяет, что может делать роль функции по умолчанию. +* **application-config.ts** указывает на эту роль, чтобы ваши функции наследовали её права. + +Заметки: + +* Начните со сгенерированной роли, затем постепенно ограничивайте её, следуя принципу наименьших привилегий. +* Замените `objectPermissions` и `fieldPermissions` на объекты/поля, которые нужны вашим функциям. +* `permissionFlags` управляют доступом к возможностям на уровне платформы. Держите их минимальными; добавляйте только то, что нужно. +* См. рабочий пример в приложении Hello World: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). + +### Конфигурация логической функции и точка входа + +Каждый файл функции использует `defineLogicFunction()` для экспорта конфигурации с обработчиком и необязательными триггерами. + +```typescript +// src/app/createPostCard.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk'; +import { CoreApiClient, type Person } from 'twenty-sdk/generated'; + +const handler = async (params: RoutePayload) => { + const client = new CoreApiClient(); + const name = 'name' in params.queryStringParameters + ? params.queryStringParameters.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world' + : 'Hello world'; + + const result = await client.mutation({ + createPostCard: { + __args: { data: { name } }, + id: true, + name: true, + }, + }); + return result; +}; + +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'create-new-post-card', + timeoutSeconds: 2, + handler, + triggers: [ + // Public HTTP route trigger '/s/post-card/create' + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/post-card/create', + httpMethod: 'GET', + isAuthRequired: false, + }, + // Cron trigger (CRON pattern) + // { + // universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2', + // type: 'cron', + // pattern: '0 0 1 1 *', + // }, + // Database event trigger + // { + // universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156', + // type: 'databaseEvent', + // eventName: 'person.updated', + // updatedFields: ['name'], + // }, + ], +}); +``` + +Распространённые типы триггеров: + +* **route**: Публикует вашу функцию по HTTP-пути и методу **под конечной точкой `/s/`**: + +> например, `path: '/post-card/create',` -> вызов по адресу `/s/post-card/create` + +* **cron**: Запускает вашу функцию по расписанию с использованием выражения CRON. +* **databaseEvent**: Запускается при событиях жизненного цикла объектов рабочего пространства. Когда операция события — `updated`, можно указать конкретные поля для отслеживания в массиве `updatedFields`. Если оставить не заданным или пустым, любое обновление будет вызывать функцию. + +> например, `person.updated` + +Заметки: + +* Массив `triggers` необязателен. Функции без триггеров можно использовать как вспомогательные, вызываемые другими функциями. +* Вы можете сочетать несколько типов триггеров в одной функции. + +### Предустановочные функции + +Предустановочная функция — это логическая функция, которая автоматически выполняется до установки вашего приложения в рабочем пространстве. Это полезно для задач валидации, проверки предварительных условий или подготовки состояния рабочего пространства перед основной установкой. + +Когда вы создаёте каркас нового приложения с помощью `create-twenty-app`, для вас генерируется предустановочная функция по пути `src/logic-functions/pre-install.ts`: + +```typescript +// src/logic-functions/pre-install.ts +import { definePreInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Pre install logic function executed successfully!', payload.previousVersion); +}; + +export default definePreInstallLogicFunction({ + universalIdentifier: '', + name: 'pre-install', + description: 'Runs before installation to prepare the application.', + timeoutSeconds: 300, + handler, +}); +``` + +Вы также можете вручную выполнить предустановочную функцию в любое время с помощью CLI: + +```bash filename="Terminal" +yarn twenty function:execute --preInstall +``` + +Основные моменты: + +* Предустановочные функции используют `definePreInstallLogicFunction()` — специализированный вариант, который опускает настройки триггеров (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`). +* Обработчик получает `InstallLogicFunctionPayload` с `{ previousVersion: string }` — версией приложения, которая была установлена ранее (или пустой строкой для новых установок). +* Для каждого приложения допускается только одна предустановочная функция. Сборка манифеста завершится ошибкой, если будет обнаружено более одной такой функции. +* Параметр `universalIdentifier` функции автоматически устанавливается как `preInstallLogicFunctionUniversalIdentifier` в манифесте приложения во время сборки — вам не нужно ссылаться на него в `defineApplication()`. +* Тайм-аут по умолчанию установлен на 300 секунд (5 минут), чтобы обеспечить выполнение более длительных задач подготовки. +* Предустановочным функциям не нужны триггеры — платформа вызывает их перед установкой или вручную через `function:execute --preInstall`. + +### Послеустановочные функции + +Послеустановочная функция — это функция логики, которая автоматически выполняется после установки вашего приложения в рабочем пространстве. Это полезно для одноразовых задач настройки, таких как инициализация данных по умолчанию, создание начальных записей или настройка параметров рабочего пространства. + +Когда вы создаёте каркас нового приложения с помощью `create-twenty-app`, для вас генерируется постустановочная функция по пути `src/logic-functions/post-install.ts`: + +```typescript +// src/logic-functions/post-install.ts +import { definePostInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Post install logic function executed successfully!', payload.previousVersion); +}; + +export default definePostInstallLogicFunction({ + universalIdentifier: '', + name: 'post-install', + description: 'Runs after installation to set up the application.', + timeoutSeconds: 300, + handler, +}); +``` + +Вы также можете вручную выполнить постустановочную функцию в любое время с помощью CLI: + +```bash filename="Terminal" +yarn twenty function:execute --postInstall +``` + +Основные моменты: + +* Послеустановочные функции используют `definePostInstallLogicFunction()` — специализированный вариант, который опускает настройки триггеров (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`). +* Обработчик получает `InstallLogicFunctionPayload` с `{ previousVersion: string }` — версией приложения, которая была установлена ранее (или пустой строкой для новых установок). +* Для каждого приложения допускается только одна послеустановочная функция. Сборка манифеста завершится ошибкой, если будет обнаружено более одной такой функции. +* Параметр `universalIdentifier` функции автоматически устанавливается как `postInstallLogicFunctionUniversalIdentifier` в манифесте приложения во время сборки — вам не нужно ссылаться на него в `defineApplication()`. +* Тайм-аут по умолчанию установлен на 300 секунд (5 минут), чтобы позволить выполнять более длительные задачи настройки, такие как инициализация данных. +* Постустановочным функциям не нужны триггеры — платформа вызывает их во время установки или вручную через `function:execute --postInstall`. + +### Полезная нагрузка триггера маршрута + + +**Нарушающее совместимость изменение (v1.16, январь 2026):** Формат полезной нагрузки триггера маршрута изменился. До v1.16 параметры запроса, параметры пути и тело передавались напрямую в качестве полезной нагрузки. Начиная с v1.16 они вложены в структурированный объект `RoutePayload`. + +**До v1.16:** +```typescript +const handler = async (params) => { + const { param1, param2 } = params; // Direct access +}; +``` + +**После v1.16:** +```typescript +const handler = async (event: RoutePayload) => { + const { param1, param2 } = event.body; // Access via .body + const { queryParam } = event.queryStringParameters; + const { id } = event.pathParameters; +}; +``` + +**Чтобы мигрировать существующие функции:** Обновите обработчик, чтобы деструктурировать из `event.body`, `event.queryStringParameters` или `event.pathParameters` вместо прямого доступа к объекту params. + + +Когда триггер маршрута вызывает вашу логическую функцию, она получает объект `RoutePayload`, соответствующий формату AWS HTTP API v2. Импортируйте тип из `twenty-sdk`: + +```typescript +import { defineLogicFunction, type RoutePayload } from 'twenty-sdk'; + +const handler = async (event: RoutePayload) => { + // Access request data + const { headers, queryStringParameters, pathParameters, body } = event; + + // HTTP method and path are available in requestContext + const { method, path } = event.requestContext.http; + + return { message: 'Success' }; +}; +``` + +Тип `RoutePayload` имеет следующую структуру: + +| Свойство | Тип | Описание | +| ---------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------ | +| `headers` | `Record` | HTTP-заголовки (только перечисленные в `forwardedRequestHeaders`) | +| `queryStringParameters` | `Record` | Параметры строки запроса (несколько значений объединяются запятыми) | +| `pathParameters` | `Record` | Параметры пути, извлечённые из шаблона маршрута (например, `/users/:id` → `{ id: '123' }`) | +| `body` | `object \| null` | Разобранное тело запроса (JSON) | +| `isBase64Encoded` | `логический тип` | Является ли тело закодированным в base64 | +| `requestContext.http.method` | `строка` | Метод HTTP (GET, POST, PUT, PATCH, DELETE) | +| `requestContext.http.path` | `строка` | Необработанный путь запроса | + +### Проброс HTTP-заголовков + +По умолчанию HTTP-заголовки из входящих запросов **не** передаются в вашу логическую функцию по соображениям безопасности. Чтобы получить доступ к определённым заголовкам, явно перечислите их в массиве `forwardedRequestHeaders`: + +```typescript +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'webhook-handler', + handler, + triggers: [ + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/webhook', + httpMethod: 'POST', + isAuthRequired: false, + forwardedRequestHeaders: ['x-webhook-signature', 'content-type'], + }, + ], +}); +``` + +В обработчике вы сможете получить доступ к этим заголовкам: + +```typescript +const handler = async (event: RoutePayload) => { + const signature = event.headers['x-webhook-signature']; + const contentType = event.headers['content-type']; + + // Validate webhook signature... + return { received: true }; +}; +``` + + + Имена заголовков приводятся к нижнему регистру. Обращайтесь к ним, используя ключи в нижнем регистре (например, `event.headers['content-type']`). + + +Вы можете создать новые функции двумя способами: + +* **Сгенерировано**: Запустите `yarn twenty entity:add` и выберите опцию добавления новой функции логики. Это создаёт стартовый файл с обработчиком и конфигурацией. +* **Вручную**: Создайте новый файл `*.logic-function.ts` и используйте `defineLogicFunction()`, следуя тому же шаблону. + +### Пометка логической функции как инструмента + +Логические функции можно предоставлять как **инструменты** для ИИ-агентов и рабочих процессов. Когда функция помечена как инструмент, она становится доступной для ИИ Twenty и может быть выбрана в качестве шага в автоматизациях рабочих процессов. + +Чтобы пометить логическую функцию как инструмент, установите `isTool: true` и укажите `toolInputSchema` для описания ожидаемых входных параметров с помощью [схемы JSON](https://json-schema.org/): + +```typescript +// src/logic-functions/enrich-company.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import { CoreApiClient } from 'twenty-sdk/generated'; + +const handler = async (params: { companyName: string; domain?: string }) => { + const client = new CoreApiClient(); + + const result = await client.mutation({ + createTask: { + __args: { + data: { + title: `Enrich data for ${params.companyName}`, + body: `Domain: ${params.domain ?? 'unknown'}`, + }, + }, + id: true, + }, + }); + + return { taskId: result.createTask.id }; +}; + +export default defineLogicFunction({ + universalIdentifier: 'f47ac10b-58cc-4372-a567-0e02b2c3d479', + name: 'enrich-company', + description: 'Enrich a company record with external data', + timeoutSeconds: 10, + handler, + isTool: true, + toolInputSchema: { + type: 'object', + properties: { + companyName: { + type: 'string', + description: 'The name of the company to enrich', + }, + domain: { + type: 'string', + description: 'The company website domain (optional)', + }, + }, + required: ['companyName'], + }, +}); +``` + +Основные моменты: + +* **`isTool`** (`boolean`, по умолчанию: `false`): Если значение равно `true`, функция регистрируется как инструмент и становится доступной агентам ИИ и автоматизациям рабочих процессов. +* **`toolInputSchema`** (`object`, необязательно): Объект JSON Schema, который описывает параметры, которые принимает ваша функция. Агенты ИИ используют эту схему, чтобы понять, какие входные данные ожидает инструмент, и проверять корректность вызовов. Если опущено, по умолчанию используется схема `{ type: 'object', properties: {} }` (без параметров). +* Функции с `isTool: false` (или без указания) **не** выставляются как инструменты. Их по-прежнему можно выполнять напрямую или вызывать из других функций, но они не будут отображаться при обнаружении инструментов. +* **Именование инструмента**: При публикации как инструмента имя функции автоматически нормализуется до `logic_function_` (в нижнем регистре, небуквенно-цифровые символы заменяются на подчёркивания). Например, `enrich-company` становится `logic_function_enrich_company`. +* Вы можете комбинировать `isTool` с триггерами — функция может одновременно быть инструментом (вызываемым агентами ИИ) и запускаться событиями (cron, события базы данных, маршруты). + + +**Напишите хорошее описание в поле `description`.** Агенты ИИ опираются на поле `description` функции, чтобы решить, когда использовать инструмент. Чётко опишите, что делает инструмент и когда его следует вызывать. + + +### Фронт-компоненты + +Фронт-компоненты позволяют создавать пользовательские компоненты React, которые рендерятся внутри интерфейса Twenty. Используйте `defineFrontComponent()` для определения компонентов со встроенной валидацией: + +```typescript +// src/front-components/my-widget.tsx +import { defineFrontComponent } from 'twenty-sdk'; + +const MyWidget = () => { + return ( +
+

My Custom Widget

+

This is a custom front component for Twenty.

+
+ ); +}; + +export default defineFrontComponent({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'my-widget', + description: 'A custom widget component', + component: MyWidget, +}); +``` + +Основные моменты: + +* Фронт-компоненты — это компоненты React, которые рендерятся в изолированных контекстах внутри Twenty. +* Поле `component` ссылается на ваш компонент React. +* Компоненты автоматически собираются и синхронизируются во время `yarn twenty app:dev`. + +Вы можете создать новые фронт-компоненты двумя способами: + +* **Сгенерировано**: Запустите `yarn twenty entity:add` и выберите опцию добавления нового фронтенд-компонента. +* **Вручную**: Создайте новый файл `.tsx` и используйте `defineFrontComponent()`, следуя тому же шаблону. + +### Навыки + +Навыки определяют многократно используемые инструкции и возможности, которые агенты ИИ могут использовать в вашем рабочем пространстве. Используйте `defineSkill()` для определения навыков со встроенной валидацией: + +```typescript +// src/skills/example-skill.ts +import { defineSkill } from 'twenty-sdk'; + +export default defineSkill({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'sales-outreach', + label: 'Sales Outreach', + description: 'Guides the AI agent through a structured sales outreach process', + icon: 'IconBrain', + content: `You are a sales outreach assistant. When reaching out to a prospect: +1. Research the company and recent news +2. Identify the prospect's role and likely pain points +3. Draft a personalized message referencing specific details +4. Keep the tone professional but conversational`, +}); +``` + +Основные моменты: + +* `name` — уникальная строка-идентификатор навыка (рекомендуется kebab-case). +* `label` — читаемое человеком отображаемое имя, показываемое в UI. +* `content` содержит инструкции навыка — это текст, который использует агент ИИ. +* `icon` (необязательно) задаёт значок, отображаемый в UI. +* `description` (необязательно) предоставляет дополнительный контекст о назначении навыка. + +Вы можете создать новые навыки двумя способами: + +* **Сгенерировано**: Запустите `yarn twenty entity:add` и выберите опцию добавления нового навыка. +* **Вручную**: Создайте новый файл и используйте `defineSkill()`, следуя тому же шаблону. + +### Сгенерированные типизированные клиенты + +Два типизированных клиента автоматически генерируются с помощью `yarn twenty app:dev` и сохраняются в `node_modules/twenty-sdk/generated` на основе схемы вашего рабочего пространства: + +* **`CoreApiClient`** — выполняет запросы к конечной точке `/graphql` для получения данных рабочего пространства +* **`MetadataApiClient`** — выполняет запросы к эндпоинту `/metadata` для получения конфигурации рабочего пространства и загрузки файлов. + +```typescript +import { CoreApiClient, MetadataApiClient } from 'twenty-sdk/generated'; + +const client = new CoreApiClient(); +const { me } = await client.query({ me: { id: true, displayName: true } }); + +const metadataClient = new MetadataApiClient(); +const { currentWorkspace } = await metadataClient.query({ currentWorkspace: { id: true } }); +``` + +Оба клиента автоматически перегенерируются с помощью `yarn twenty app:dev` при изменении ваших объектов или полей. + +#### Учётные данные времени выполнения в логических функциях + +Когда ваша функция запускается на Twenty, платформа подставляет учётные данные как переменные окружения перед выполнением вашего кода: + +* `TWENTY_API_URL`: Базовый URL API Twenty, на который нацелено ваше приложение. +* `TWENTY_API_KEY`: Краткоживущий ключ, ограниченный ролью функции по умолчанию вашего приложения. + +Заметки: + +* Вам не нужно передавать URL или ключ API сгенерированному клиенту. Он читает `TWENTY_API_URL` и `TWENTY_API_KEY` из process.env во время выполнения. +* Права ключа API определяются ролью, на которую ссылается ваш `application-config.ts` через `defaultRoleUniversalIdentifier`. Это роль по умолчанию, используемая логическими функциями вашего приложения. +* Приложения могут определять роли, чтобы следовать принципу наименьших привилегий. Предоставляйте только те права, которые нужны вашим функциям, затем укажите в `defaultRoleUniversalIdentifier` универсальный идентификатор этой роли. + +#### Загрузка файлов + +Сгенерированный `MetadataApiClient` включает метод `uploadFile` для прикрепления файлов к полям типа «файл» в объектах вашего рабочего пространства. Поскольку стандартные клиенты GraphQL изначально не поддерживают многочастовую загрузку файлов, клиент предоставляет специальный метод, который под капотом реализует [спецификацию многочастных запросов GraphQL](https://github.com/jaydenseric/graphql-multipart-request-spec). + +```typescript +import { MetadataApiClient } from 'twenty-sdk/generated'; +import * as fs from 'fs'; + +const metadataClient = new MetadataApiClient(); + +const fileBuffer = fs.readFileSync('./invoice.pdf'); + +const uploadedFile = await metadataClient.uploadFile( + fileBuffer, // file contents as a Buffer + 'invoice.pdf', // filename + 'application/pdf', // MIME type (defaults to 'application/octet-stream') + '58a0a314-d7ea-4865-9850-7fb84e72f30b', // field universal identifier +); + +console.log(uploadedFile); +// { id: '...', path: '...', size: 12345, createdAt: '...', url: 'https://...' } +``` + +Сигнатура метода: + +```typescript +uploadFile( + fileBuffer: Buffer, + filename: string, + contentType: string, + fieldMetadataUniversalIdentifier: string, +): Promise<{ id: string; path: string; size: number; createdAt: string; url: string }> +``` + +| Параметр | Тип | Описание | +| ---------------------------------- | -------- | ------------------------------------------------------------------------ | +| `fileBuffer` | `Buffer` | Необработанное содержимое файла | +| `filename` | `строка` | Имя файла (используется для хранения и отображения) | +| `contentType` | `строка` | Тип MIME файла (по умолчанию `application/octet-stream`, если не указан) | +| `fieldMetadataUniversalIdentifier` | `строка` | Значение `universalIdentifier` для поля типа файла в вашем объекте | + +Основные моменты: + +* Метод `uploadFile` доступен в `MetadataApiClient`, потому что мутация загрузки обрабатывается эндпоинтом `/metadata`. +* Он использует `universalIdentifier` поля (а не его идентификатор, специфичный для рабочего пространства), поэтому ваш код загрузки будет работать в любом рабочем пространстве, где установлено ваше приложение — в соответствии с тем, как приложения ссылаются на поля повсюду. +* Возвращаемый `url` — это подписанный URL, который можно использовать для доступа к загруженному файлу. + +### Пример Hello World + +Ознакомьтесь с минимальным сквозным примером, демонстрирующим объекты, логические функции, фронт-компоненты и несколько триггеров, [здесь](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/hello-world). diff --git a/packages/twenty-docs/l/ru/developers/extend/apps/getting-started.mdx b/packages/twenty-docs/l/ru/developers/extend/apps/getting-started.mdx new file mode 100644 index 0000000000..be743bad0e --- /dev/null +++ b/packages/twenty-docs/l/ru/developers/extend/apps/getting-started.mdx @@ -0,0 +1,233 @@ +--- +title: Начало работы +description: Создайте своё первое приложение Twenty за считанные минуты. +--- + + +Приложения сейчас проходят альфа-тестирование. Функциональность работает, но продолжает развиваться. + + +Приложения позволяют расширять Twenty с помощью пользовательских объектов, полей, логических функций, навыков ИИ и UI-компонентов — всё это управляется как код. + +**Что вы можете делать уже сегодня:** + +* Определяйте пользовательские объекты и поля в виде кода (управляемая модель данных) +* Создавайте логические функции с пользовательскими триггерами (HTTP-маршруты, cron, события базы данных) +* Определяйте навыки для ИИ-агентов +* Создавайте фронтенд-компоненты, которые отображаются внутри интерфейса Twenty +* Развёртывайте одно и то же приложение в нескольких рабочих пространствах + +## Требования + +* Node.js 24+ и Yarn 4 +* Рабочее пространство Twenty и ключ API (создайте его на https://app.twenty.com/settings/api-webhooks) + +## Начало работы + +Создайте новое приложение с помощью официального генератора, затем выполните аутентификацию и начните разработку: + +```bash filename="Terminal" +# Scaffold a new app (includes all examples by default) +npx create-twenty-app@latest my-twenty-app +cd my-twenty-app + +# Start dev mode: automatically syncs local changes to your workspace +yarn twenty app:dev +``` + +Генератор каркаса поддерживает два режима для управления тем, какие файлы-примеры включаются: + +```bash filename="Terminal" +# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item, skill) +npx create-twenty-app@latest my-app + +# Minimal: only core files (application-config.ts and default-role.ts) +npx create-twenty-app@latest my-app --minimal +``` + +Отсюда вы можете: + +```bash filename="Terminal" +# Add a new entity to your application (guided) +yarn twenty entity:add + +# Watch your application's function logs +yarn twenty function:logs + +# Execute a function by name +yarn twenty function:execute -n my-function -p '{"name": "test"}' + +# Execute the pre-install function +yarn twenty function:execute --preInstall + +# Execute the post-install function +yarn twenty function:execute --postInstall + +# Uninstall the application from the current workspace +yarn twenty app:uninstall + +# Display commands' help +yarn twenty help +``` + +Смотрите также: страницы справки CLI для [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) и [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk). + +## Структура проекта (сгенерированного) + +Когда вы запускаете `npx create-twenty-app@latest my-twenty-app`, генератор: + +* Копирует минимальное базовое приложение в `my-twenty-app/` +* Добавляет локальную зависимость `twenty-sdk` и конфигурацию Yarn 4 +* Создаёт файлы конфигурации и скрипты, подключённые к CLI `twenty` +* Генерирует основные файлы (конфигурацию приложения, роль функций по умолчанию, предустановочную и послеустановочную функции), а также примерные файлы в зависимости от выбранного режима создания каркаса + +Сгенерированное с помощью каркаса приложение с режимом по умолчанию `--exhaustive` выглядит так: + +```text filename="my-twenty-app/" +my-twenty-app/ + package.json + yarn.lock + .gitignore + .nvmrc + .yarnrc.yml + .yarn/ + install-state.gz + .oxlintrc.json + tsconfig.json + README.md + public/ # Public assets folder (images, fonts, etc.) + src/ + ├── application-config.ts # Required - main application configuration + ├── roles/ + │ └── default-role.ts # Default role for logic functions + ├── objects/ + │ └── example-object.ts # Example custom object definition + ├── fields/ + │ └── example-field.ts # Example standalone field definition + ├── logic-functions/ + │ ├── hello-world.ts # Example logic function + │ ├── pre-install.ts # Pre-install logic function + │ └── post-install.ts # Post-install logic function + ├── front-components/ + │ └── hello-world.tsx # Example front component + ├── views/ + │ └── example-view.ts # Example saved view definition + ├── navigation-menu-items/ + │ └── example-navigation-menu-item.ts # Example sidebar navigation link + └── skills/ + └── example-skill.ts # Example AI agent skill definition +``` + +С `--minimal` создаются только основные файлы (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` и `logic-functions/post-install.ts`). + +В общих чертах: + +* **package.json**: Объявляет имя приложения, версию, движки (Node 24+, Yarn 4) и добавляет `twenty-sdk`, а также скрипт `twenty`, который делегирует выполнение локальному CLI `twenty`. Выполните `yarn twenty help`, чтобы вывести список всех доступных команд. +* **.gitignore**: Игнорирует распространённые артефакты, такие как `node_modules`, `.yarn`, `generated/` (типизированный клиент), `dist/`, `build/`, каталоги coverage, файлы журналов и файлы `.env*`. +* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Фиксируют и настраивают используемый в проекте инструментарий Yarn 4. +* **.nvmrc**: Фиксирует версию Node.js, ожидаемую проектом. +* **.oxlintrc.json** и **tsconfig.json**: Обеспечивают линтинг и конфигурацию TypeScript для исходников вашего приложения на TypeScript. +* **README.md**: Короткий README в корне приложения с базовыми инструкциями. +* **public/**: Папка для хранения общедоступных ресурсов (изображений, шрифтов, статических файлов), которые будут отдаваться вашим приложением. Файлы, размещённые здесь, загружаются во время синхронизации и доступны во время выполнения. +* **src/**: Основное место, где вы определяете приложение как код + +### Обнаружение сущностей + +SDK обнаруживает сущности, разбирая ваши файлы TypeScript в поисках вызовов **`export default define({...})`**. Для каждого типа сущности существует соответствующая вспомогательная функция, экспортируемая из `twenty-sdk`: + +| Вспомогательная функция | Тип сущности | +| -------------------------------- | ------------------------------------------------------------------ | +| `defineObject` | Определения пользовательских объектов | +| `defineLogicFunction` | Определения логических функций | +| `definePreInstallLogicFunction` | Предустановочная логическая функция (запускается до установки) | +| `definePostInstallLogicFunction` | Послеустановочная логическая функция (запускается после установки) | +| `defineFrontComponent` | Определения компонентов фронтенда | +| `defineRole` | Определения ролей | +| `defineField` | Расширения полей для существующих объектов | +| `defineView` | Определения сохранённых представлений | +| `defineNavigationMenuItem` | Определения пунктов меню навигации | +| `defineSkill` | Определения навыков агента ИИ | + + +**Имена файлов заданы гибко.** Обнаружение сущностей основано на AST — SDK сканирует ваши исходные файлы в поисках шаблона `export default define({...})`. Вы можете организовывать файлы и папки как угодно. Группировка по типу сущности (например, `logic-functions/`, `roles/`) — это лишь соглашение для организации кода, а не требование. + + +Пример обнаруженной сущности: + +```typescript +// This file can be named anything and placed anywhere in src/ +import { defineObject, FieldType } from 'twenty-sdk'; + +export default defineObject({ + universalIdentifier: '...', + nameSingular: 'postCard', + // ... rest of config +}); +``` + +Позднее команды добавят больше файлов и папок: + +* `yarn twenty app:dev` автоматически сгенерирует два типизированных клиента API в `node_modules/twenty-sdk/generated`: `CoreApiClient` (для данных рабочего пространства через `/graphql`) и `MetadataApiClient` (для конфигурации рабочего пространства и загрузки файлов через `/metadata`). +* `yarn twenty entity:add` добавит файлы определений сущностей в `src/` для ваших пользовательских объектов, функций, фронтенд-компонентов, ролей, навыков и многого другого. + +## Аутентификация + +При первом запуске `yarn twenty auth:login` вам будет предложено указать: + +* URL API (по умолчанию http://localhost:3000 или текущий профиль рабочего пространства) +* Ключ API + +Ваши учётные данные хранятся для каждого пользователя в `~/.twenty/config.json`. Вы можете хранить несколько профилей и переключаться между ними. + +### Управление рабочими пространствами + +```bash filename="Terminal" +# Login interactively (recommended) +yarn twenty auth:login + +# Login to a specific workspace profile +yarn twenty auth:login --workspace my-custom-workspace + +# List all configured workspaces +yarn twenty auth:list + +# Switch the default workspace (interactive) +yarn twenty auth:switch + +# Switch to a specific workspace +yarn twenty auth:switch production + +# Check current authentication status +yarn twenty auth:status +``` + +После переключения рабочего пространства с помощью `yarn twenty auth:switch` все последующие команды по умолчанию будут использовать это рабочее пространство. Вы по-прежнему можете временно переопределить это с помощью `--workspace `. + +## Ручная настройка (без генератора) + +Хотя мы рекомендуем использовать `create-twenty-app` для наилучшего старта, вы также можете настроить проект вручную. Не устанавливайте CLI глобально. Вместо этого добавьте `twenty-sdk` как локальную зависимость и настройте один скрипт в вашем package.json: + +```bash filename="Terminal" +yarn add -D twenty-sdk +``` + +Затем добавьте скрипт `twenty`: + +```json filename="package.json" +{ + "scripts": { + "twenty": "twenty" + } +} +``` + +Теперь вы можете запускать все команды через `yarn twenty `, например, `yarn twenty app:dev`, `yarn twenty help` и т. д. + +## Устранение неполадок + +* Ошибки аутентификации: выполните `yarn twenty auth:login` и убедитесь, что у вашего ключа API есть необходимые права. +* Не удаётся подключиться к серверу: проверьте URL API и доступность сервера Twenty. +* Типы или клиент отсутствуют/устарели: перезапустите `yarn twenty app:dev` — он автоматически генерирует типизированный клиент. +* Режим разработки не синхронизируется: убедитесь, что запущен `yarn twenty app:dev`, и что ваша среда не игнорирует изменения. + +Канал помощи в Discord: https://discord.com/channels/1130383047699738754/1130386664812982322 diff --git a/packages/twenty-docs/l/ru/developers/extend/apps/publishing.mdx b/packages/twenty-docs/l/ru/developers/extend/apps/publishing.mdx new file mode 100644 index 0000000000..47b0cfcac7 --- /dev/null +++ b/packages/twenty-docs/l/ru/developers/extend/apps/publishing.mdx @@ -0,0 +1,119 @@ +--- +title: Публикация +description: Распространяйте своё приложение Twenty в маркетплейсе или разверните его для внутреннего использования. +--- + + +Приложения сейчас проходят альфа-тестирование. Функциональность работает, но продолжает развиваться. + + +## Обзор + +После того как ваше приложение [собрано и протестировано локально](/l/ru/developers/extend/apps/building), у вас есть два пути для его распространения: + +* **Опубликовать в npm** — разместите ваше приложение в маркетплейсе Twenty, чтобы любое рабочее пространство могло его найти и установить. +* **Отправить tarball** — разверните приложение на конкретном сервере Twenty для внутреннего использования, не делая его общедоступным. + +## Публикация в npm + +Публикация в npm делает ваше приложение видимым в маркетплейсе Twenty. Любое рабочее пространство Twenty может просматривать, устанавливать и обновлять приложения из маркетплейса непосредственно из интерфейса. + +### Требования + +* Учётная запись [npm](https://www.npmjs.com) +* Название вашего пакета **должно** использовать префикс `twenty-app-` (например, `twenty-app-postcard-sender`) + +### Шаги + +1. **Соберите приложение** — CLI компилирует исходные файлы TypeScript и генерирует манифест приложения: + +```bash filename="Terminal" +yarn twenty app:build +``` + +2. **Опубликуйте в npm** — отправьте собранный пакет в реестр npm: + +```bash filename="Terminal" +npx twenty app:publish +``` + +### Автоматическое обнаружение + +Пакеты с префиксом `twenty-app-` автоматически обнаруживаются каталогом маркетплейса Twenty. После публикации ваше приложение появится в маркетплейсе в течение нескольких минут — ручная регистрация или одобрение не требуются. + +### Публикация через CI + +Сгенерированный шаблоном проект включает workflow GitHub Actions, который выполняет публикацию при каждом релизе. Он запускает `app:build`, затем `npm publish --provenance` из результатов сборки: + +```yaml filename=".github/workflows/publish.yml" +name: Publish +on: + release: + types: [published] + +permissions: + contents: read + id-token: write + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "24" + registry-url: https://registry.npmjs.org + - run: yarn install --immutable + - run: npx twenty app:build + - run: npm publish --provenance --access public + working-directory: .twenty/output + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} +``` + +Для других CI-систем (GitLab CI, CircleCI и др.) применимы те же три команды: `yarn install`, `npx twenty app:build`, затем `npm publish` из `.twenty/output`. + + +**npm provenance** — опционально, но рекомендуется. Публикация с флагом `--provenance` добавляет к вашему пакету в npm значок доверия, позволяя пользователям проверить, что пакет был собран из конкретного коммита в общедоступном конвейере CI. См. инструкции по настройке в [документации по npm provenance](https://docs.npmjs.com/generating-provenance-statements). + + +## Внутреннее распространение + +Для приложений, которые вы не хотите делать общедоступными — собственные инструменты, интеграции только для предприятия или экспериментальные сборки — вы можете отправить tarball напрямую на сервер Twenty. + +### Отправка tarball + +Соберите приложение и разверните его на конкретном сервере одним шагом: + +```bash filename="Terminal" +npx twenty app:publish --server +``` + +Любое рабочее пространство на этом сервере сможет установить и обновить приложение на странице настроек **Applications**. + +### Управление версиями + +Чтобы выпустить обновление: + +1. Обновите значение поля `version` в файле `package.json` +2. Отправьте новый tarball командой `npx twenty app:publish --server ` +3. Рабочие пространства на этом сервере увидят доступное обновление в своих настройках + + +Внутренние приложения ограничены сервером, на который они отправлены. Они не появятся в публичном маркетплейсе и не могут быть установлены рабочими пространствами на других серверах. + + +## Категории приложений + +Twenty группирует приложения в три категории в зависимости от способа их распространения: + +| Категория | Как это работает | Отображается в маркетплейсе? | +| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | +| **Разработка** | Локальные приложения в режиме разработки, запущенные через `yarn twenty app:dev`. Используются для сборки и тестирования. | Нет | +| **Опубликовано** | Приложения, опубликованные в npm с префиксом `twenty-app-`. Отображаются в маркетплейсе, доступные для установки любому рабочему пространству. | Да | +| **Внутренний** | Приложения, развернутые через tarball на конкретном сервере. Доступны только рабочим пространствам на этом сервере. | Нет | + + +Начните в режиме **Разработка** во время создания приложения. Когда будет готово, выберите **Опубликовано** (npm) для широкого распространения или **Внутренний** (tarball) для приватного развертывания. + diff --git a/packages/twenty-docs/l/ru/developers/extend/capabilities/apps.mdx b/packages/twenty-docs/l/ru/developers/extend/capabilities/apps.mdx index b6f871bf39..c0685379f8 100644 --- a/packages/twenty-docs/l/ru/developers/extend/capabilities/apps.mdx +++ b/packages/twenty-docs/l/ru/developers/extend/capabilities/apps.mdx @@ -321,11 +321,11 @@ export default defineObject({ но это не рекомендуется. -### Defining fields on existing objects +### Определение полей для существующих объектов -Use `defineField()` to add custom fields to existing objects — both standard objects (like `company`, `person`, `opportunity`) and custom objects defined by other apps. Each field lives in its own file and references the target object by its `universalIdentifier`. +Используйте `defineField()` для добавления настраиваемых полей к существующим объектам — как стандартным объектам (например, `company`, `person`, `opportunity`), так и пользовательским объектам, определённым другими приложениями. Каждое поле находится в собственном файле и ссылается на целевой объект по его `universalIdentifier`. -To reference standard objects, import `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` from `twenty-sdk`. This constant provides stable identifiers for all built-in objects and their fields: +Чтобы ссылаться на стандартные объекты, импортируйте `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` из `twenty-sdk`. Эта константа предоставляет стабильные идентификаторы для всех встроенных объектов и их полей: ```typescript // src/fields/apollo-total-funding.field.ts @@ -349,22 +349,22 @@ export default defineField({ Основные моменты: -* `objectUniversalIdentifier` tells Twenty which object to attach the field to. Use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS..universalIdentifier` for standard objects. -* Each field requires its own stable `universalIdentifier`, a `name`, `type`, `label`, and the target `objectUniversalIdentifier`. -* You can scaffold new fields using `yarn twenty entity:add` and choosing the field option. -* `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` is also exported as `STANDARD_OBJECT` for convenience — both refer to the same constant. +* `objectUniversalIdentifier` сообщает Twenty, к какому объекту прикрепить поле. Используйте `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS..universalIdentifier` для стандартных объектов. +* Каждому полю требуется собственный стабильный `universalIdentifier`, а также `name`, `type`, `label` и целевой `objectUniversalIdentifier`. +* Вы можете сгенерировать новые поля с помощью `yarn twenty entity:add`, выбрав опцию поля. +* Для удобства `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` также экспортируется как `STANDARD_OBJECT` — обе ссылки указывают на одну и ту же константу. -Available standard objects include: `attachment`, `blocklist`, `calendarChannel`, `calendarEvent`, `calendarEventParticipant`, `company`, `connectedAccount`, `dashboard`, `favorite`, `favoriteFolder`, `message`, `messageChannel`, `messageParticipant`, `messageThread`, `note`, `noteTarget`, `opportunity`, `person`, `task`, `taskTarget`, `timelineActivity`, `workflow`, `workflowAutomatedTrigger`, `workflowRun`, `workflowVersion`, and `workspaceMember`. +Доступные стандартные объекты включают: `attachment`, `blocklist`, `calendarChannel`, `calendarEvent`, `calendarEventParticipant`, `company`, `connectedAccount`, `dashboard`, `favorite`, `favoriteFolder`, `message`, `messageChannel`, `messageParticipant`, `messageThread`, `note`, `noteTarget`, `opportunity`, `person`, `task`, `taskTarget`, `timelineActivity`, `workflow`, `workflowAutomatedTrigger`, `workflowRun`, `workflowVersion` и `workspaceMember`. -Each standard object also exposes its field identifiers. For example, to reference a specific field on a standard object in role permissions: +Каждый стандартный объект также предоставляет идентификаторы своих полей. Например, чтобы сослаться на конкретное поле стандартного объекта в разрешениях роли: ```typescript STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.fields.name.universalIdentifier ``` -#### Relation fields on existing objects +#### Поля связей в существующих объектах -You can also define relation fields that link existing objects to your custom objects: +Вы также можете определить поля связей, которые связывают существующие объекты с вашими пользовательскими объектами: ```typescript // src/fields/people-on-call-recording.field.ts diff --git a/packages/twenty-docs/l/ru/developers/extend/extend.mdx b/packages/twenty-docs/l/ru/developers/extend/extend.mdx index a4888036dc..30d868d723 100644 --- a/packages/twenty-docs/l/ru/developers/extend/extend.mdx +++ b/packages/twenty-docs/l/ru/developers/extend/extend.mdx @@ -1,7 +1,6 @@ --- title: Расширяйте description: Расширяйте возможности Twenty с помощью API, вебхуков и пользовательских приложений. -redirect: /developers/introduction --- @@ -16,18 +15,18 @@ Twenty разработан с учетом расширяемости. Испо * **APIs**: Запрашивайте и изменяйте данные CRM программно с помощью REST или GraphQL * **Вебхуки**: Получайте уведомления в реальном времени при возникновении событий в Twenty -* **Приложения**: Создавайте пользовательские приложения, которые расширяют возможности Twenty - Скоро! +* **Приложения**: Создавайте пользовательские приложения, которые расширяют возможности Twenty ## Начало работы - + Подключайтесь к Twenty программно - + Получайте уведомления о событиях в реальном времени - - Создавайте настройки как код (Alpha) + + Создавайте настройки как код diff --git a/packages/twenty-docs/l/ru/developers/extend/webhooks.mdx b/packages/twenty-docs/l/ru/developers/extend/webhooks.mdx new file mode 100644 index 0000000000..5312a3c9e4 --- /dev/null +++ b/packages/twenty-docs/l/ru/developers/extend/webhooks.mdx @@ -0,0 +1,116 @@ +--- +title: Вебхуки +description: Получайте уведомления в реальном времени, когда в вашей CRM происходят события. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +Вебхуки отправляют данные в ваши системы в реальном времени при возникновении событий в Twenty — опрос не требуется. Используйте их, чтобы поддерживать синхронизацию с внешними системами, запускать автоматизации или отправлять оповещения. + +## Создать вебхук + +1. Перейдите в **Настройки → API и Вебхуки → Вебхуки** +2. Нажмите **+ Создать вебхук** +3. Введите URL вашего вебхука (должен быть общедоступным) +4. Нажмите **Сохранить** + +Вебхук активируется сразу и начинает отправлять уведомления. + + + +### Управление вебхуками + +**Изменить**: Нажмите на вебхук → Обновите URL → **Сохранить** + +**Удалить**: Нажмите на вебхук → **Удалить** → Подтвердить + +## События + +Twenty отправляет вебхуки для следующих типов событий: + +| Событие | Пример | +| -------------------- | ---------------------------------------------------------- | +| **Запись создана** | `person.created`, `company.created`, `note.created` | +| **Запись обновлена** | `person.updated`, `company.updated`, `opportunity.updated` | +| **Запись удалена** | `person.deleted`, `company.deleted` | + +Все типы событий отправляются на URL вашего вебхука. Фильтрация событий может быть добавлена в будущих версиях. + +## Формат полезной нагрузки + +Каждый вебхук отправляет HTTP POST с телом JSON: + +```json +{ + "event": "person.created", + "data": { + "id": "abc12345", + "firstName": "Alice", + "lastName": "Doe", + "email": "alice@example.com", + "createdAt": "2025-02-10T15:30:45Z", + "createdBy": "user_123" + }, + "timestamp": "2025-02-10T15:30:50Z" +} +``` + +| Поле | Описание | +| ----------- | ----------------------------------------------------- | +| `event` | Что произошло (например, `person.created`) | +| `data` | Полная запись, которая была создана/обновлена/удалена | +| `timestamp` | Когда произошло событие (UTC) | + + +Ответьте со **статусом HTTP 2xx** (200-299), чтобы подтвердить получение. Ответы вне диапазона 2xx фиксируются как ошибки доставки. + + +## Валидация вебхуков + +Twenty подписывает каждый запрос вебхука для обеспечения безопасности. Проверяйте подписи, чтобы убедиться в подлинности запросов. + +### Заголовки + +| Заголовок | Описание | +| ---------------------------- | --------------------- | +| `X-Twenty-Webhook-Signature` | Подпись HMAC SHA256 | +| `X-Twenty-Webhook-Timestamp` | Метка времени запроса | + +### Шаги проверки + +1. Получите метку времени из `X-Twenty-Webhook-Timestamp` +2. Создайте строку: `{timestamp}:{JSON payload}` +3. Вычислите HMAC SHA256, используя секрет вашего вебхука +4. Сравните с `X-Twenty-Webhook-Signature` + +### Пример (Node.js) + +```javascript +const crypto = require("crypto"); + +const timestamp = req.headers["x-twenty-webhook-timestamp"]; +const payload = JSON.stringify(req.body); +const secret = "your-webhook-secret"; + +const stringToSign = `${timestamp}:${payload}`; +const expectedSignature = crypto + .createHmac("sha256", secret) + .update(stringToSign) + .digest("hex"); + +const receivedSignature = req.headers["x-twenty-webhook-signature"]; +const isValid = crypto.timingSafeEqual( + Buffer.from(expectedSignature, "hex"), + Buffer.from(receivedSignature, "hex") +); +``` + +## Вебхуки vs рабочие процессы + +| Метод | Направление | Сценарий использования | +| -------------------------------------- | ----------- | -------------------------------------------------------------------------- | +| **Вебхуки** | OUT | Автоматически уведомлять внешние системы о любом изменении записи | +| **Рабочий процесс + HTTP-запрос** | OUT | Отправлять данные наружу с настраиваемой логикой (фильтры, преобразования) | +| **Триггер вебхука в рабочем процессе** | IN | Получать данные в Twenty из внешних систем | + +Для получения внешних данных см. [Настройка триггера вебхука](/l/ru/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger). diff --git a/packages/twenty-docs/l/ru/developers/introduction.mdx b/packages/twenty-docs/l/ru/developers/introduction.mdx index 647e25a399..95ef917862 100644 --- a/packages/twenty-docs/l/ru/developers/introduction.mdx +++ b/packages/twenty-docs/l/ru/developers/introduction.mdx @@ -5,28 +5,18 @@ description: Добро пожаловать в документацию для import { CardTitle } from "/snippets/card-title.mdx" - - - API - Запрашивайте и изменяйте данные CRM с помощью REST или GraphQL. + + + Расширяйте + Создавайте интеграции с API, вебхуками и пользовательскими приложениями. - - Webhooks - Получайте уведомления в реальном времени при возникновении событий. - - - - Apps - Создавайте пользовательские приложения, расширяющие возможности Twenty. - - - + Развертывайте у себя Развертывайте и управляйте Twenty в собственной инфраструктуре. - + Вносите вклад Присоединяйтесь к нашему сообществу с открытым исходным кодом и вносите вклад в Twenty. diff --git a/packages/twenty-docs/l/ru/user-guide/data-migration/how-tos/export-your-data.mdx b/packages/twenty-docs/l/ru/user-guide/data-migration/how-tos/export-your-data.mdx index f19e722ba0..f961e04c9c 100644 --- a/packages/twenty-docs/l/ru/user-guide/data-migration/how-tos/export-your-data.mdx +++ b/packages/twenty-docs/l/ru/user-guide/data-migration/how-tos/export-your-data.mdx @@ -24,7 +24,7 @@ import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; * Экспортируются только **видимые столбцы** * Экспортируются только **отфильтрованные записи** (на основе вашего текущего представления) -Для больших экспортов (20 000+ записей) используйте фильтры для экспорта партиями или используйте [API](/l/ru/developers/api). +Для больших объемов экспорта (20 000+ записей) используйте фильтры для пакетного экспорта или [API](/l/ru/developers/extend/api). ### Разрешения @@ -148,7 +148,7 @@ import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; 2. Используйте GraphQL API для выборки записей 3. Обрабатывайте результаты в вашем приложении -См.: [Документация по API](/l/ru/developers/api) +См.: [Документация по API](/l/ru/developers/extend/api) ## Советы и лучшие практики @@ -206,4 +206,4 @@ import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; * [Как обновить существующие записи](/l/ru/user-guide/data-migration/how-tos/update-existing-records-via-import) — отредактируйте и импортируйте ваш экспорт повторно * [Как импортировать данные через API](/l/ru/user-guide/data-migration/how-tos/import-data-via-api) — для больших наборов данных -* [Документация по API](/l/ru/developers/api) — создавайте собственные рабочие процессы экспорта +* [Документация по API](/l/ru/developers/extend/api) — создавайте собственные рабочие процессы экспорта diff --git a/packages/twenty-docs/l/ru/user-guide/data-migration/how-tos/import-data-via-api.mdx b/packages/twenty-docs/l/ru/user-guide/data-migration/how-tos/import-data-via-api.mdx index 6fd0435732..3b123441f9 100644 --- a/packages/twenty-docs/l/ru/user-guide/data-migration/how-tos/import-data-via-api.mdx +++ b/packages/twenty-docs/l/ru/user-guide/data-migration/how-tos/import-data-via-api.mdx @@ -57,10 +57,10 @@ Twenty применяет лимиты скорости для обеспече Twenty поддерживает два типа API: -| API | Лучше всего подходит для | Документация | -| ----------- | ------------------------------------------------------------ | ----------------------------------------------------------- | -| **GraphQL** | Гибкие запросы, получение связанных данных, сложные операции | [Документация по API](/l/ru/developers/api) | -| **REST** | Простые операции CRUD, привычные шаблоны REST | [Документация по API](/l/ru/developers/api) | +| API | Лучше всего подходит для | Документация | +| ----------- | ------------------------------------------------------------ | --------------------------------------------- | +| **GraphQL** | Гибкие запросы, получение связанных данных, сложные операции | [Документация по API](/l/ru/developers/extend/api) | +| **REST** | Простые операции CRUD, привычные шаблоны REST | [Документация по API](/l/ru/developers/extend/api) | Оба API поддерживают: @@ -173,4 +173,4 @@ GraphQL API поддерживает **пакетный upsert** — обнов Полная информация о реализации, примеры кода и справочник по схеме: -* [Документация по API](/l/ru/developers/api) +* [Документация по API](/l/ru/developers/extend/api) diff --git a/packages/twenty-docs/l/ru/user-guide/getting-started/capabilities/what-is-twenty.mdx b/packages/twenty-docs/l/ru/user-guide/getting-started/capabilities/what-is-twenty.mdx index 12469775ce..6efb5487f3 100644 --- a/packages/twenty-docs/l/ru/user-guide/getting-started/capabilities/what-is-twenty.mdx +++ b/packages/twenty-docs/l/ru/user-guide/getting-started/capabilities/what-is-twenty.mdx @@ -35,7 +35,7 @@ description: Twenty — это CRM с открытым исходным кодо * **Панели управления:** Отслеживайте производительность с помощью индивидуальных отчетов и визуализаций. [Посмотреть панели управления](/l/ru/user-guide/dashboards/overview). * **Права и доступ:** Управляйте тем, кто может просматривать, редактировать и управлять вашими данными, с помощью ролевых прав доступа. [Настроить доступ](/l/ru/user-guide/permissions-access/overview). * **Заметки и задачи:** Создавайте заметки и задачи, связанные с вашими записями, для более эффективной совместной работы. -* **API и Вебхуки:** Подключайтесь к другим приложениям и создавайте индивидуальные интеграции. [Начать интеграцию](/l/ru/developers/api). +* **API и Вебхуки:** Подключайтесь к другим приложениям и создавайте индивидуальные интеграции. [Начать интеграцию](/l/ru/developers/extend/api). ## Присоединяйтесь сейчас diff --git a/packages/twenty-docs/l/ru/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx b/packages/twenty-docs/l/ru/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx index d3af24fc81..ceac0b55f7 100644 --- a/packages/twenty-docs/l/ru/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx +++ b/packages/twenty-docs/l/ru/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx @@ -95,7 +95,7 @@ description: Показывайте данные из связанных зап * Размер компании: `{{searchRecords[0].employees}}` -**Ограничение для задач и заметок**: связи в задачах и заметках жёстко заданы как многие-ко-многим и пока недоступны в триггерах или действиях рабочего процесса. Чтобы получить доступ к этим связям, вместо этого используйте [API](/l/ru/developers/api). +**Ограничение для задач и заметок**: связи в задачах и заметках жёстко заданы как многие-ко-многим и пока недоступны в триггерах или действиях рабочего процесса. Чтобы получить доступ к этим связям, вместо этого используйте [API](/l/ru/developers/extend/api). ## Двунаправленная синхронизация diff --git a/packages/twenty-docs/l/tr/developers/extend/api.mdx b/packages/twenty-docs/l/tr/developers/extend/api.mdx new file mode 100644 index 0000000000..13103464b2 --- /dev/null +++ b/packages/twenty-docs/l/tr/developers/extend/api.mdx @@ -0,0 +1,147 @@ +--- +title: API'ler +description: CRM verilerinizi REST veya GraphQL kullanarak programatik olarak sorgulayın ve değiştirin. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +Twenty, geliştirici dostu olacak şekilde tasarlanmıştır ve özel veri modelinize uyum sağlayan güçlü API'ler sunar. Farklı entegrasyon ihtiyaçlarını karşılamak üzere dört farklı API türü sunuyoruz. + +## Geliştirici Öncelikli Yaklaşım + +Twenty, veri modeliniz için özel olarak API'ler oluşturur: + +* **Uzun kimlik numaralarına gerek yok**: Uç noktalarda nesne ve alan adlarınızı doğrudan kullanın +* **Standart ve özel nesneler eşit şekilde ele alınır**: Özel nesneleriniz yerleşik olanlarla aynı API muamelesini görür. +* **Özel uç noktalar**: Her nesne ve alan kendi API uç noktasına sahiptir +* **Özel dokümantasyon**: Çalışma alanınızın veri modeli için özel olarak üretilmiştir. + + +Bir API anahtarı oluşturduktan sonra kişiselleştirilmiş API dokümantasyonunuz **Ayarlar → API ve Webhook'lar** altında mevcuttur. Twenty, özel veri modelinize uyan API'ler oluşturduğundan, dokümantasyon çalışma alanınıza özeldir. + + +## İki API Türü + +### Temel API + +`/rest/` veya `/graphql/` üzerinden erişilebilir. + +Gerçek **kayıtlarınızla** (verilerin kendisiyle) çalışın: + +* People, Companies, Opportunities vb. oluşturun, okuyun, güncelleyin, silin. +* Verileri sorgulayın ve filtreleyin +* Kayıt ilişkilerini yönetin + +### Meta Veri API + +`/rest/metadata/` veya `/metadata/` üzerinden erişilebilir. + +**Çalışma alanınızı ve veri modelinizi** yönetin: + +* Nesne ve alanlar oluşturun, değiştirin veya silin +* Çalışma alanı ayarlarını yapılandırın +* Nesneler arasındaki ilişkileri tanımlayın + +## REST ve GraphQL + +Hem Temel hem de Meta Veri API'leri, REST ve GraphQL formatlarında mevcuttur: + +| Biçim | Kullanılabilir İşlemler | +| ----------- | -------------------------------------------------------------------------------- | +| **REST** | CRUD, toplu işlemler, ekleme-güncelleme işlemleri | +| **GraphQL** | Aynısı + **toplu ekleme-güncelleme işlemleri**, tek bir çağrıda ilişki sorguları | + +İhtiyaçlarınıza göre seçin — her iki format da aynı verilere erişir. + +## API Uç Noktaları + +| Ortam | Temel URL | +| ---------------------------- | ------------------------- | +| **Bulut** | `https://api.twenty.com/` | +| **Kendi Kendine Barındırma** | `https://{your-domain}/` | + +## Kimlik Doğrulama + +Her API isteği, başlıkta bir API anahtarı gerektirir: + +``` +Authorization: Bearer YOUR_API_KEY +``` + +### Bir API Anahtarı Oluştur + +1. **Ayarlar → API ve Webhook'lar**'a gidin +2. **+ Anahtar oluştur**'a tıklayın +3. Yapılandırın: + * **Ad**: Anahtar için açıklayıcı bir ad + * **Son Kullanma Tarihi**: Anahtarın ne zaman sona ereceği +4. **Kaydet**'e tıklayın +5. **Hemen kopyalayın** — anahtar yalnızca bir kez gösterilir + + + + +API anahtarınız hassas verilere erişim sağlar. Güvenilmeyen hizmetlerle paylaşmayın. Tehlikeye girerse, onu hemen devre dışı bırakın ve yenisini oluşturun. + + +### Bir API Anahtarına Rol Atama + +Daha iyi güvenlik için, erişimi sınırlamak amacıyla belirli bir rol atayın: + +1. **Ayarlar → Roller** bölümüne gidin +2. Atamak istediğiniz role tıklayın +3. **Atama** sekmesini açın +4. **API Anahtarları** altında, **+ API anahtarına ata**'ya tıklayın +5. API anahtarını seçin + +Anahtar, o rolün izinlerini devralacaktır. Ayrıntılar için [İzinler](/l/tr/user-guide/permissions-access/capabilities/permissions) bölümüne bakın. + +### API Anahtarlarını Yönet + +**Yeniden Oluştur**: Ayarlar → API ve Webhook'lar → Anahtara tıklayın → **Yeniden Oluştur** + +**Sil**: Ayarlar → API ve Webhook'lar → Anahtara tıklayın → **Sil** + +## API Oyun Alanı + +Yerleşik oyun alanımız ile API'lerinizi doğrudan tarayıcıda test edin — hem **REST** hem de **GraphQL** için kullanılabilir. + +### Oyun Alanına Erişin + +1. **Ayarlar → API ve Webhook'lar**'a gidin +2. Bir API anahtarı oluşturun (gerekli) +3. Oyun alanını açmak için **REST API** veya **GraphQL API**'ye tıklayın + +### Elde Edecekleriniz + +* **Etkileşimli dokümantasyon**: Belirli veri modeliniz için oluşturulur +* **Canlı test**: Çalışma alanınıza karşı gerçek API çağrılarını gerçekleştirin +* **Şema gezgini**: Kullanılabilir nesnelere, alanlara ve ilişkilere göz atın +* **İstek oluşturucu**: Otomatik tamamlama ile sorgular oluşturun + +Oyun alanı, özel nesnelerinizi ve alanlarınızı yansıtır, bu nedenle dokümantasyon çalışma alanınız için her zaman doğrudur. + +## Toplu İşlemler + +Hem REST hem de GraphQL, toplu işlemleri destekler: + +* **Toplu boyut**: İstek başına 60 kayıt kadar +* **İşlemler**: Birden çok kaydı oluşturma, güncelleme, silme + +**Yalnızca GraphQL Özellikleri:** + +* **Toplu Ekleme-Güncelleme**: Tek bir çağrıda oluşturun veya güncelleyin +* Çoğul nesne adlarını kullanın (ör. `CreateCompany` yerine `CreateCompanies`) + +## Hız Sınırları + +Platform kararlılığını sağlamak için API istekleri kısıtlanır: + +| Sınır | Değer | +| ---------------- | --------------------- | +| **İstekler** | Dakikada 100 çağrı | +| **Toplu boyutu** | Çağrı başına 60 kayıt | + + +Verimi en üst düzeye çıkarmak için toplu işlemleri kullanın — tekil istekler yapmak yerine tek bir API çağrısında 60 kayda kadar işleyin. + diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/building.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/building.mdx new file mode 100644 index 0000000000..bdc8277fe4 --- /dev/null +++ b/packages/twenty-docs/l/tr/developers/extend/apps/building.mdx @@ -0,0 +1,689 @@ +--- +title: Uygulama Geliştirme +description: Nesneleri, mantık fonksiyonlarını, ön uç bileşenlerini ve daha fazlasını Twenty SDK ile tanımlayın. +--- + + +Uygulamalar şu anda alfa testinde. Özellik işlevsel ancak hâlâ gelişmekte. + + +## SDK kaynaklarını kullanın (türler ve yapılandırma) + +twenty-sdk, uygulamanız içinde kullandığınız türlendirilmiş yapı taşları ve yardımcı fonksiyonlar sağlar. Aşağıda en sık dokunacağınız başlıca parçalar yer alıyor. + +### Yardımcı fonksiyonlar + +SDK, uygulama varlıklarınızı tanımlamak için yardımcı fonksiyonlar sağlar. [Varlık algılama](/l/tr/developers/extend/apps/getting-started#entity-detection) bölümünde açıklandığı gibi, varlıklarınızın algılanması için `export default define({...})` kullanmalısınız: + +| Fonksiyon | Amaç | +| -------------------------------- | ------------------------------------------------------------------------- | +| `defineApplication` | Uygulama meta verilerini yapılandırın (zorunlu, uygulama başına bir adet) | +| `defineObject` | Alanlara sahip özel nesneler tanımlayın | +| `defineLogicFunction` | İşleyicilerle mantık fonksiyonları tanımlayın | +| `definePreInstallLogicFunction` | Bir kurulum öncesi mantık işlevi tanımlayın (uygulama başına bir adet) | +| `definePostInstallLogicFunction` | Bir kurulum sonrası mantık işlevi tanımlayın (uygulama başına bir adet) | +| `defineFrontComponent` | Özel kullanıcı arayüzü için ön uç bileşenlerini tanımlayın | +| `defineRole` | Rol izinlerini ve nesne erişimini yapılandırın | +| `defineField` | Mevcut nesneleri ek alanlarla genişletin | +| `defineView` | Nesneler için kaydedilmiş görünümler tanımlayın | +| `defineNavigationMenuItem` | Kenar çubuğu gezinme bağlantılarını tanımlayın | +| `defineSkill` | Yapay zekâ ajanı yeteneklerini tanımlayın | + +Bu fonksiyonlar, derleme zamanında yapılandırmanızı doğrular ve IDE otomatik tamamlama ile tür güvenliği sağlar. + +### Nesnelerin tanımlanması + +Özel nesneler, çalışma alanınızdaki kayıtlar için hem şemayı hem de davranışı tanımlar. Yerleşik doğrulamayla nesneler tanımlamak için `defineObject()` kullanın: + +```typescript +// src/app/postCard.object.ts +import { defineObject, FieldType } from 'twenty-sdk'; + +enum PostCardStatus { + DRAFT = 'DRAFT', + SENT = 'SENT', + DELIVERED = 'DELIVERED', + RETURNED = 'RETURNED', +} + +export default defineObject({ + universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05', + nameSingular: 'postCard', + namePlural: 'postCards', + labelSingular: 'Post Card', + labelPlural: 'Post Cards', + description: 'A post card object', + icon: 'IconMail', + fields: [ + { + universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b', + name: 'content', + type: FieldType.TEXT, + label: 'Content', + description: "Postcard's content", + icon: 'IconAbc', + }, + { + universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac', + name: 'recipientName', + type: FieldType.FULL_NAME, + label: 'Recipient name', + icon: 'IconUser', + }, + { + universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266', + name: 'recipientAddress', + type: FieldType.ADDRESS, + label: 'Recipient address', + icon: 'IconHome', + }, + { + universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e', + name: 'status', + type: FieldType.SELECT, + label: 'Status', + icon: 'IconSend', + defaultValue: `'${PostCardStatus.DRAFT}'`, + options: [ + { value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' }, + { value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' }, + { value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' }, + { value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' }, + ], + }, + { + universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433', + name: 'deliveredAt', + type: FieldType.DATE_TIME, + label: 'Delivered at', + icon: 'IconCheck', + isNullable: true, + defaultValue: null, + }, + ], +}); +``` + +Önemli noktalar: + +* Yerleşik doğrulama ve daha iyi IDE desteği için `defineObject()` kullanın. +* `universalIdentifier` dağıtımlar arasında benzersiz ve kararlı olmalıdır. +* Her alan bir `name`, `type`, `label` ve kendi kararlı `universalIdentifier` değerini gerektirir. +* `fields` dizisi isteğe bağlıdır — özel alanlar olmadan da nesneler tanımlayabilirsiniz. +* `yarn twenty entity:add` kullanarak, adlandırma, alanlar ve ilişkiler konusunda sizi yönlendirerek yeni nesneler oluşturabilirsiniz. + + +**Temel alanlar otomatik olarak oluşturulur.** Özel bir nesne tanımladığınızda Twenty, standart alanları otomatik olarak ekler +örneğin `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` ve `deletedAt`. +Bunları `fields` dizinizde tanımlamanız gerekmez — yalnızca özel alanlarınızı ekleyin. +`fields` dizinizde aynı ada sahip bir alan tanımlayarak varsayılan alanları geçersiz kılabilirsiniz, +ancak bu önerilmez. + + +### Uygulama yapılandırması (application-config.ts) + +Her uygulamanın aşağıdakileri açıklayan tek bir `application-config.ts` dosyası vardır: + +* **Uygulamanın kim olduğu**: tanımlayıcılar, görünen ad ve açıklama. +* **Fonksiyonlarının nasıl çalıştığı**: izinler için hangi rolü kullandıkları. +* **(İsteğe bağlı) değişkenler**: fonksiyonlarınıza ortam değişkenleri olarak sunulan anahtar–değer çiftleri. +* **(İsteğe bağlı) kurulum öncesi işlev**: uygulama yüklenmeden önce çalışan bir mantık işlevi. +* **(İsteğe bağlı) kurulum sonrası işlev**: uygulama yüklendikten sonra çalışan bir mantık işlevi. + +Uygulama yapılandırmanızı tanımlamak için `defineApplication()` kullanın: + +```typescript +// src/application-config.ts +import { defineApplication } from 'twenty-sdk'; +import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role'; + +export default defineApplication({ + universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7', + displayName: 'My Twenty App', + description: 'My first Twenty app', + icon: 'IconWorld', + applicationVariables: { + DEFAULT_RECIPIENT_NAME: { + universalIdentifier: '19e94e59-d4fe-4251-8981-b96d0a9f74de', + description: 'Default recipient name for postcards', + value: 'Jane Doe', + isSecret: false, + }, + }, + defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, +}); +``` + +Notlar: + +* `universalIdentifier` alanları size ait belirleyici kimliklerdir; bunları bir kez oluşturun ve eşitlemeler boyunca kararlı tutun. +* `applicationVariables`, fonksiyonlarınız için ortam değişkenlerine dönüşür (örneğin, `DEFAULT_RECIPIENT_NAME` değeri `process.env.DEFAULT_RECIPIENT_NAME` olarak kullanılabilir). +* `defaultRoleUniversalIdentifier`, rol dosyasıyla eşleşmelidir (aşağıya bakın). +* Kurulum öncesi ve kurulum sonrası işlevler, manifest oluşturma sırasında otomatik olarak algılanır. Bkz. [Kurulum öncesi işlevler](#pre-install-functions) ve [Kurulum sonrası işlevler](#post-install-functions). + +#### Roller ve izinler + +Uygulamalar, çalışma alanınızdaki nesneler ve eylemler üzerindeki izinleri kapsülleyen roller tanımlayabilir. `application-config.ts` içindeki `defaultRoleUniversalIdentifier` alanı, uygulamanızın mantık fonksiyonlarının kullandığı varsayılan rolü belirtir. + +* `TWENTY_API_KEY` olarak enjekte edilen çalışma zamanı API anahtarı bu varsayılan fonksiyon rolünden türetilir. +* Türlendirilmiş istemci, o role tanınan izinlerle sınırlandırılır. +* En az ayrıcalık ilkesini izleyin: Yalnızca fonksiyonlarınızın ihtiyaç duyduğu izinlere sahip özel bir rol oluşturun ve ardından evrensel tanımlayıcısına referans verin. + +##### Varsayılan fonksiyon rolü (*.role.ts) + +Yeni bir uygulama oluşturduğunuzda CLI ayrıca varsayılan bir rol dosyası da oluşturur. Yerleşik doğrulamayla roller tanımlamak için `defineRole()` kullanın: + +```typescript +// src/roles/default-role.ts +import { defineRole, PermissionFlag } from 'twenty-sdk'; + +export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = + 'b648f87b-1d26-4961-b974-0908fd991061'; + +export default defineRole({ + universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, + label: 'Default function role', + description: 'Default role for function Twenty client', + canReadAllObjectRecords: false, + canUpdateAllObjectRecords: false, + canSoftDeleteAllObjectRecords: false, + canDestroyAllObjectRecords: false, + canUpdateAllSettings: false, + canBeAssignedToAgents: false, + canBeAssignedToUsers: false, + canBeAssignedToApiKeys: false, + objectPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + canReadObjectRecords: true, + canUpdateObjectRecords: true, + canSoftDeleteObjectRecords: false, + canDestroyObjectRecords: false, + }, + ], + fieldPermissions: [ + { + objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050', + fieldUniversalIdentifier: 'b2c37dc0-8ae7-470e-96cd-1476b47dfaff', + canReadFieldValue: false, + canUpdateFieldValue: false, + }, + ], + permissionFlags: [PermissionFlag.APPLICATIONS], +}); +``` + +Bu rolün `universalIdentifier` değeri daha sonra `application-config.ts` içinde `defaultRoleUniversalIdentifier` olarak referans verilir. Başka bir deyişle: + +* **\*.role.ts**, varsayılan fonksiyon rolünün neler yapabileceğini tanımlar. +* **application-config.ts**, fonksiyonlarınızın izinlerini devralması için bu role işaret eder. + +Notlar: + +* Oluşturulan rol ile başlayın ve en az ayrıcalık ilkesini izleyerek aşamalı olarak kısıtlayın. +* `objectPermissions` ve `fieldPermissions` değerlerini, fonksiyonlarınızın ihtiyaç duyduğu nesneler/alanlarla değiştirin. +* `permissionFlags`, platform düzeyindeki yeteneklere erişimi kontrol eder. Minimumda tutun; yalnızca ihtiyacınız olanları ekleyin. +* Çalışan bir örneği Hello World uygulamasında görün: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). + +### Mantık fonksiyon yapılandırması ve giriş noktası + +Her fonksiyon dosyası, bir işleyici ve isteğe bağlı tetikleyiciler içeren bir yapılandırmayı dışa aktarmak için `defineLogicFunction()` kullanır. + +```typescript +// src/app/createPostCard.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk'; +import { CoreApiClient, type Person } from 'twenty-sdk/generated'; + +const handler = async (params: RoutePayload) => { + const client = new CoreApiClient(); + const name = 'name' in params.queryStringParameters + ? params.queryStringParameters.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world' + : 'Hello world'; + + const result = await client.mutation({ + createPostCard: { + __args: { data: { name } }, + id: true, + name: true, + }, + }); + return result; +}; + +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'create-new-post-card', + timeoutSeconds: 2, + handler, + triggers: [ + // Public HTTP route trigger '/s/post-card/create' + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/post-card/create', + httpMethod: 'GET', + isAuthRequired: false, + }, + // Cron trigger (CRON pattern) + // { + // universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2', + // type: 'cron', + // pattern: '0 0 1 1 *', + // }, + // Database event trigger + // { + // universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156', + // type: 'databaseEvent', + // eventName: 'person.updated', + // updatedFields: ['name'], + // }, + ], +}); +``` + +Yaygın tetikleyici türleri: + +* **route**: Fonksiyonunuzu bir HTTP yolu ve yöntemiyle **`/s/` uç noktası altında** sunar: + +> örn. `path: '/post-card/create',` -> `/s/post-card/create` üzerinden çağırın + +* **cron**: Bir CRON ifadesi kullanarak fonksiyonunuzu bir zamanlamayla çalıştırır. +* **databaseEvent**: Çalışma alanı nesnesi yaşam döngüsü olaylarında çalışır. Olay işlemi `updated` olduğunda, dinlenecek belirli alanlar `updatedFields` dizisinde belirtilebilir. Tanımsız veya boş bırakılırsa, herhangi bir güncelleme fonksiyonu tetikler. + +> örn. `person.updated` + +Notlar: + +* `triggers` dizisi isteğe bağlıdır. Tetikleyicisi olmayan fonksiyonlar, diğer fonksiyonlar tarafından çağrılan yardımcı fonksiyonlar olarak kullanılabilir. +* Tek bir fonksiyonda birden çok tetikleyici türünü birleştirebilirsiniz. + +### Kurulum öncesi işlevler + +Kurulum öncesi işlev, uygulamanız bir çalışma alanına yüklenmeden önce otomatik olarak çalışan bir mantık işlevidir. Bu, doğrulama görevleri, önkoşul kontrolleri veya ana kurulum başlamadan önce çalışma alanı durumunun hazırlanması için yararlıdır. + +`create-twenty-app` ile yeni bir uygulama iskeleti oluşturduğunuzda, `src/logic-functions/pre-install.ts` konumunda sizin için bir kurulum öncesi işlev oluşturulur: + +```typescript +// src/logic-functions/pre-install.ts +import { definePreInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Pre install logic function executed successfully!', payload.previousVersion); +}; + +export default definePreInstallLogicFunction({ + universalIdentifier: '', + name: 'pre-install', + description: 'Runs before installation to prepare the application.', + timeoutSeconds: 300, + handler, +}); +``` + +Ayrıca kurulum öncesi işlevi istediğiniz zaman CLI kullanarak manuel olarak çalıştırabilirsiniz: + +```bash filename="Terminal" +yarn twenty function:execute --preInstall +``` + +Önemli noktalar: + +* Kurulum öncesi işlevler `definePreInstallLogicFunction()` kullanır — tetikleyici ayarlarını atlayan (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`) özel bir varyanttır. +* İşleyici, `{ previousVersion: string }` içeren bir `InstallLogicFunctionPayload` alır — daha önce yüklü olan uygulamanın sürümü (veya yeni kurulumlar için boş bir dize). +* Uygulama başına yalnızca bir kurulum öncesi işlevine izin verilir. Birden fazla tespit edilirse manifest oluşturma hataya düşer. +* İşlevin `universalIdentifier` değeri, oluşturma sırasında uygulama manifestinde otomatik olarak `preInstallLogicFunctionUniversalIdentifier` olarak ayarlanır — `defineApplication()` içinde buna atıfta bulunmanıza gerek yoktur. +* Varsayılan zaman aşımı, daha uzun hazırlık görevlerine izin vermek için 300 saniye (5 dakika) olarak ayarlanmıştır. +* Kurulum öncesi işlevlerin tetikleyicilere ihtiyacı yoktur — kurulumdan önce platform tarafından veya `function:execute --preInstall` aracılığıyla manuel olarak çağrılırlar. + +### Kurulum sonrası işlevler + +Kurulum sonrası işlev, uygulamanız bir çalışma alanına yüklendikten sonra otomatik olarak çalışan bir mantık işlevidir. Bu, varsayılan verileri tohumlama, ilk kayıtları oluşturma veya çalışma alanı ayarlarını yapılandırma gibi tek seferlik kurulum görevleri için yararlıdır. + +`create-twenty-app` ile yeni bir uygulama iskeleti oluşturduğunuzda, `src/logic-functions/post-install.ts` konumunda sizin için bir kurulum sonrası işlevi oluşturulur: + +```typescript +// src/logic-functions/post-install.ts +import { definePostInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk'; + +const handler = async (payload: InstallLogicFunctionPayload): Promise => { + console.log('Post install logic function executed successfully!', payload.previousVersion); +}; + +export default definePostInstallLogicFunction({ + universalIdentifier: '', + name: 'post-install', + description: 'Runs after installation to set up the application.', + timeoutSeconds: 300, + handler, +}); +``` + +Ayrıca kurulum sonrası işlevi istediğiniz zaman CLI kullanarak manuel olarak çalıştırabilirsiniz: + +```bash filename="Terminal" +yarn twenty function:execute --postInstall +``` + +Önemli noktalar: + +* Kurulum sonrası işlevler `definePostInstallLogicFunction()` kullanır — tetikleyici ayarlarını atlayan (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`) özel bir varyanttır. +* İşleyici, `{ previousVersion: string }` içeren bir `InstallLogicFunctionPayload` alır — daha önce yüklü olan uygulamanın sürümü (veya yeni kurulumlar için boş bir dize). +* Uygulama başına yalnızca bir kurulum sonrası işlevine izin verilir. Birden fazla tespit edilirse manifest oluşturma hataya düşer. +* İşlevin `universalIdentifier` değeri, oluşturma sırasında uygulama manifestinde otomatik olarak `postInstallLogicFunctionUniversalIdentifier` olarak ayarlanır — `defineApplication()` içinde buna atıfta bulunmanıza gerek yoktur. +* Varsayılan zaman aşımı, veri tohumlama gibi daha uzun kurulum görevlerine izin vermek için 300 saniye (5 dakika) olarak ayarlanmıştır. +* Kurulum sonrası işlevlerin tetikleyicilere ihtiyacı yoktur — kurulum sırasında platform tarafından veya `function:execute --postInstall` aracılığıyla manuel olarak çağrılırlar. + +### Rota tetikleyicisi yükü + + +**Kırıcı değişiklik (v1.16, Ocak 2026):** Rota tetikleyicisi yük formatı değişti. v1.16'dan önce, sorgu parametreleri, yol parametreleri ve gövde doğrudan payload olarak gönderiliyordu. v1.16 itibarıyla, yapılandırılmış bir `RoutePayload` nesnesinin içine yerleştiriliyorlar. + +**v1.16'dan önce:** +```typescript +const handler = async (params) => { + const { param1, param2 } = params; // Direct access +}; +``` + +**v1.16'dan sonra:** +```typescript +const handler = async (event: RoutePayload) => { + const { param1, param2 } = event.body; // Access via .body + const { queryParam } = event.queryStringParameters; + const { id } = event.pathParameters; +}; +``` + +**Mevcut fonksiyonları taşımak için:** İşleyicinizi, parametreler nesnesinden doğrudan ayırmak yerine `event.body`, `event.queryStringParameters` veya `event.pathParameters` üzerinden ayrıştıracak şekilde güncelleyin. + + +Bir rota tetikleyicisi mantık fonksiyonunuzu çağırdığında, AWS HTTP API v2 formatını izleyen bir `RoutePayload` nesnesi alır. Türü `twenty-sdk` içinden içe aktarın: + +```typescript +import { defineLogicFunction, type RoutePayload } from 'twenty-sdk'; + +const handler = async (event: RoutePayload) => { + // Access request data + const { headers, queryStringParameters, pathParameters, body } = event; + + // HTTP method and path are available in requestContext + const { method, path } = event.requestContext.http; + + return { message: 'Success' }; +}; +``` + +`RoutePayload` türünün yapısı şu şekildedir: + +| Özellik | Tür | Açıklama | +| ---------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------- | +| `headers` | `Record` | HTTP başlıkları (`forwardedRequestHeaders` içinde listelenenlerle sınırlı) | +| `queryStringParameters` | `Record` | Sorgu dizesi parametreleri (birden çok değer virgülle birleştirilir) | +| `pathParameters` | `Record` | Rota deseninden çıkarılan yol parametreleri (örn., `/users/:id` → `{ id: '123' }`) | +| `body` | `object \| null` | Ayrıştırılmış istek gövdesi (JSON) | +| `isBase64Encoded` | `boolean` | Gövdenin base64 ile kodlanıp kodlanmadığı | +| `requestContext.http.method` | `string` | HTTP yöntemi (GET, POST, PUT, PATCH, DELETE) | +| `requestContext.http.path` | `string` | Ham istek yolu | + +### HTTP başlıklarını iletme + +Varsayılan olarak, güvenlik nedenleriyle gelen isteklerden HTTP başlıkları mantık fonksiyonunuza **aktarılmaz**. Belirli başlıklara erişmek için bunları açıkça `forwardedRequestHeaders` dizisinde listeleyin: + +```typescript +export default defineLogicFunction({ + universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf', + name: 'webhook-handler', + handler, + triggers: [ + { + universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6', + type: 'route', + path: '/webhook', + httpMethod: 'POST', + isAuthRequired: false, + forwardedRequestHeaders: ['x-webhook-signature', 'content-type'], + }, + ], +}); +``` + +Daha sonra işleyicinizde bu başlıklara erişebilirsiniz: + +```typescript +const handler = async (event: RoutePayload) => { + const signature = event.headers['x-webhook-signature']; + const contentType = event.headers['content-type']; + + // Validate webhook signature... + return { received: true }; +}; +``` + + + Başlık adları küçük harfe normalize edilir. Onlara küçük harfli anahtarlarla erişin (örneğin, `event.headers['content-type']`). + + +Yeni fonksiyonları iki şekilde oluşturabilirsiniz: + +* **Şablondan**: `yarn twenty entity:add` çalıştırın ve yeni bir mantık fonksiyonu ekleme seçeneğini seçin. Bu, bir işleyici ve yapılandırma içeren bir başlangıç dosyası oluşturur. +* **Manuel**: Yeni bir `*.logic-function.ts` dosyası oluşturun ve aynı deseni izleyerek `defineLogicFunction()` kullanın. + +### Bir mantık işlevini araç olarak işaretleme + +Mantık işlevleri, yapay zeka ajanları ve iş akışları için **araçlar** olarak sunulabilir. Bir işlev bir araç olarak işaretlendiğinde, Twenty'nin yapay zeka özellikleri tarafından keşfedilebilir hâle gelir ve iş akışı otomasyonlarında bir adım olarak seçilebilir. + +Bir mantık işlevini bir araç olarak işaretlemek için `isTool: true` olarak ayarlayın ve beklenen giriş parametrelerini açıklayan bir `toolInputSchema`yı [JSON Şeması](https://json-schema.org/) kullanarak sağlayın: + +```typescript +// src/logic-functions/enrich-company.logic-function.ts +import { defineLogicFunction } from 'twenty-sdk'; +import { CoreApiClient } from 'twenty-sdk/generated'; + +const handler = async (params: { companyName: string; domain?: string }) => { + const client = new CoreApiClient(); + + const result = await client.mutation({ + createTask: { + __args: { + data: { + title: `Enrich data for ${params.companyName}`, + body: `Domain: ${params.domain ?? 'unknown'}`, + }, + }, + id: true, + }, + }); + + return { taskId: result.createTask.id }; +}; + +export default defineLogicFunction({ + universalIdentifier: 'f47ac10b-58cc-4372-a567-0e02b2c3d479', + name: 'enrich-company', + description: 'Enrich a company record with external data', + timeoutSeconds: 10, + handler, + isTool: true, + toolInputSchema: { + type: 'object', + properties: { + companyName: { + type: 'string', + description: 'The name of the company to enrich', + }, + domain: { + type: 'string', + description: 'The company website domain (optional)', + }, + }, + required: ['companyName'], + }, +}); +``` + +Önemli noktalar: + +* **`isTool`** (`boolean`, varsayılan: `false`): `true` olarak ayarlandığında, işlev bir araç olarak kaydedilir ve AI ajanları ile iş akışı otomasyonları tarafından kullanılabilir hale gelir. +* **`toolInputSchema`** (`object`, isteğe bağlı): İşlevinizin kabul ettiği parametreleri tanımlayan bir JSON Schema nesnesi. AI ajanları, aracın hangi girdileri beklediğini anlamak ve çağrıları doğrulamak için bu şemayı kullanır. Atlanırsa, şema varsayılan olarak `{ type: 'object', properties: {} }` olur (parametre yok). +* `isTool: false` (veya ayarlanmamış) olan işlevler araç olarak **sunulmaz**. Yine de doğrudan yürütülebilir veya diğer işlevler tarafından çağrılabilirler, ancak araç keşfinde görünmezler. +* **Araç adlandırma**: Bir araç olarak sunulduğunda, işlev adı otomatik olarak `logic_function_` biçimine dönüştürülür (küçük harfe çevrilir, alfasayısal olmayan karakterler alt çizgi ile değiştirilir). Örneğin, `enrich-company` `logic_function_enrich_company` haline gelir. +* `isTool` özelliğini tetikleyicilerle birleştirebilirsiniz — bir işlev aynı anda hem bir araç (AI ajanları tarafından çağrılabilir) olabilir hem de olaylar tarafından tetiklenebilir (cron, veritabanı olayları, routes). + + +**İyi bir `description` yazın.** AI ajanları, aracı ne zaman kullanacaklarına karar vermek için işlevin `description` alanına güvenir. Aracın ne yaptığını ve ne zaman çağrılması gerektiğini açıkça belirtin. + + +### Ön uç bileşenleri + +Ön uç bileşenleri, Twenty'nin kullanıcı arayüzünde görüntülenen özel React bileşenleri oluşturmanıza olanak tanır. Yerleşik doğrulamayla bileşenleri tanımlamak için `defineFrontComponent()` kullanın: + +```typescript +// src/front-components/my-widget.tsx +import { defineFrontComponent } from 'twenty-sdk'; + +const MyWidget = () => { + return ( +
+

My Custom Widget

+

This is a custom front component for Twenty.

+
+ ); +}; + +export default defineFrontComponent({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'my-widget', + description: 'A custom widget component', + component: MyWidget, +}); +``` + +Önemli noktalar: + +* Ön uç bileşenleri, Twenty içinde yalıtılmış bağlamlarda görüntülenen React bileşenleridir. +* `component` alanı, React bileşeninize referans verir. +* Bileşenler, `yarn twenty app:dev` sırasında otomatik olarak oluşturulur ve senkronize edilir. + +Yeni ön uç bileşenlerini iki şekilde oluşturabilirsiniz: + +* **Şablondan**: `yarn twenty entity:add` çalıştırın ve yeni bir ön uç bileşeni ekleme seçeneğini seçin. +* **Manuel**: Aynı deseni izleyerek yeni bir `.tsx` dosyası oluşturun ve `defineFrontComponent()` kullanın. + +### Beceriler + +Yetenekler, yapay zekâ ajanlarının çalışma alanınızda kullanabileceği yeniden kullanılabilir yönergeleri ve kabiliyetleri tanımlar. Yerleşik doğrulamayla yetenekleri tanımlamak için `defineSkill()` kullanın: + +```typescript +// src/skills/example-skill.ts +import { defineSkill } from 'twenty-sdk'; + +export default defineSkill({ + universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', + name: 'sales-outreach', + label: 'Sales Outreach', + description: 'Guides the AI agent through a structured sales outreach process', + icon: 'IconBrain', + content: `You are a sales outreach assistant. When reaching out to a prospect: +1. Research the company and recent news +2. Identify the prospect's role and likely pain points +3. Draft a personalized message referencing specific details +4. Keep the tone professional but conversational`, +}); +``` + +Önemli noktalar: + +* `name`, yetenek için benzersiz bir tanımlayıcı dizedir (kebab-case önerilir). +* `label`, UI'de gösterilen, insan tarafından okunabilir addır. +* `content`, yetenek yönergelerini içerir — bu, yapay zekâ ajanının kullandığı metindir. +* `icon` (isteğe bağlı), UI'de gösterilen simgeyi ayarlar. +* `description` (isteğe bağlı), yeteneğin amacı hakkında ek bağlam sağlar. + +Yeni yetenekleri iki şekilde oluşturabilirsiniz: + +* **Şablondan**: `yarn twenty entity:add` komutunu çalıştırın ve yeni bir yetenek ekleme seçeneğini seçin. +* **Manuel**: Yeni bir dosya oluşturun ve aynı deseni izleyerek `defineSkill()` kullanın. + +### Oluşturulan tiplendirilmiş istemciler + +Çalışma alanı şemanıza göre `yarn twenty app:dev` tarafından iki tiplendirilmiş istemci otomatik olarak oluşturulur ve `node_modules/twenty-sdk/generated` içine kaydedilir: + +* **`CoreApiClient`** — çalışma alanı verileri için `/graphql` uç noktasını sorgular +* **`MetadataApiClient`** — çalışma alanı yapılandırması ve dosya yüklemeleri için `/metadata` uç noktasını sorgular. + +```typescript +import { CoreApiClient, MetadataApiClient } from 'twenty-sdk/generated'; + +const client = new CoreApiClient(); +const { me } = await client.query({ me: { id: true, displayName: true } }); + +const metadataClient = new MetadataApiClient(); +const { currentWorkspace } = await metadataClient.query({ currentWorkspace: { id: true } }); +``` + +Her iki istemci de, nesneleriniz veya alanlarınız değiştiğinde, `yarn twenty app:dev` tarafından otomatik olarak yeniden oluşturulur. + +#### Mantık fonksiyonlarında çalışma zamanı kimlik bilgileri + +Fonksiyonunuz Twenty üzerinde çalıştığında, platform kodunuz yürütülmeden önce kimlik bilgilerini ortam değişkenleri olarak enjekte eder: + +* `TWENTY_API_URL`: Uygulamanızın hedeflediği Twenty API'nin temel URL’si. +* `TWENTY_API_KEY`: Uygulamanızın varsayılan fonksiyon rolü kapsamına sahip kısa ömürlü anahtar. + +Notlar: + +* Oluşturulan istemciye URL veya API anahtarı geçirmeniz gerekmez. Çalışma zamanında `TWENTY_API_URL` ve `TWENTY_API_KEY` değerlerini process.env üzerinden okur. +* API anahtarının izinleri, `application-config.ts` içinde `defaultRoleUniversalIdentifier` aracılığıyla referans verilen role göre belirlenir. Bu, uygulamanızın mantık fonksiyonları tarafından kullanılan varsayılan roldür. +* Uygulamalar, en az ayrıcalık ilkesini izlemek için roller tanımlayabilir. Yalnızca fonksiyonlarınızın ihtiyaç duyduğu izinleri verin ve ardından `defaultRoleUniversalIdentifier` değerini o rolün evrensel tanımlayıcısına yönlendirin. + +#### Dosya yükleme + +Oluşturulan `MetadataApiClient`, çalışma alanı nesnelerinizdeki dosya türündeki alanlara dosya eklemek için bir `uploadFile` yöntemi içerir. Standart GraphQL istemcileri çok parçalı dosya yüklemelerini yerel olarak desteklemediğinden, istemci arka planda [GraphQL çok parçalı istek belirtimi](https://github.com/jaydenseric/graphql-multipart-request-spec) uygulayan bu özel yöntemi sağlar. + +```typescript +import { MetadataApiClient } from 'twenty-sdk/generated'; +import * as fs from 'fs'; + +const metadataClient = new MetadataApiClient(); + +const fileBuffer = fs.readFileSync('./invoice.pdf'); + +const uploadedFile = await metadataClient.uploadFile( + fileBuffer, // file contents as a Buffer + 'invoice.pdf', // filename + 'application/pdf', // MIME type (defaults to 'application/octet-stream') + '58a0a314-d7ea-4865-9850-7fb84e72f30b', // field universal identifier +); + +console.log(uploadedFile); +// { id: '...', path: '...', size: 12345, createdAt: '...', url: 'https://...' } +``` + +Yöntem imzası: + +```typescript +uploadFile( + fileBuffer: Buffer, + filename: string, + contentType: string, + fieldMetadataUniversalIdentifier: string, +): Promise<{ id: string; path: string; size: number; createdAt: string; url: string }> +``` + +| Parametre | Tür | Açıklama | +| ---------------------------------- | -------- | ------------------------------------------------------------------------------------------ | +| `fileBuffer` | `Buffer` | Dosyanın ham içeriği | +| `filename` | `string` | Dosyanın adı (depolama ve görüntüleme için kullanılır) | +| `contentType` | `string` | Dosyanın MIME türü (belirtilmezse varsayılan olarak `application/octet-stream` kullanılır) | +| `fieldMetadataUniversalIdentifier` | `string` | Nesnenizdeki dosya türü alanının `universalIdentifier` değeri | + +Önemli noktalar: + +* `uploadFile` yöntemi, yükleme mutasyonu `/metadata` uç noktası tarafından çözümlendiği için `MetadataApiClient` üzerinde mevcuttur. +* Alan için `universalIdentifier` kullanılır (çalışma alanına özgü kimliği değil), böylece yükleme kodunuz uygulamanızın yüklü olduğu herhangi bir çalışma alanında çalışır — uygulamaların başka her yerde alanlara nasıl atıfta bulunduğuyla tutarlıdır. +* Döndürülen `url`, yüklenen dosyaya erişmek için kullanabileceğiniz imzalı bir URL'dir. + +### Hello World örneği + +Nesneleri, mantık fonksiyonlarını, ön uç bileşenlerini ve birden çok tetikleyiciyi gösteren minimal, uçtan uca bir örneği [buradan](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/hello-world) inceleyin. diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/getting-started.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/getting-started.mdx new file mode 100644 index 0000000000..f1af3ed302 --- /dev/null +++ b/packages/twenty-docs/l/tr/developers/extend/apps/getting-started.mdx @@ -0,0 +1,233 @@ +--- +title: Başlarken +description: İlk Twenty uygulamanızı dakikalar içinde oluşturun. +--- + + +Uygulamalar şu anda alfa testinde. Özellik işlevsel ancak hâlâ gelişmekte. + + +Uygulamalar, Twenty'yi özel nesneler, alanlar, mantık işlevleri, Yapay Zeka yetenekleri ve UI bileşenleriyle genişletmenizi sağlar — tümü kod olarak yönetilir. + +**Bugün Yapabilecekleriniz:** + +* Özel nesneleri ve alanları kod olarak tanımlayın (yönetilen veri modeli) +* Özel tetikleyicilerle mantık işlevleri oluşturun (HTTP routes, cron, database events) +* Yapay zekâ ajanları için becerileri tanımlayın +* Twenty'nin UI'si içinde görüntülenen ön bileşenler oluşturun +* Aynı uygulamayı birden çok çalışma alanına dağıtın + +## Ön Gereksinimler + +* Node.js 24+ ve Yarn 4 +* Bir Twenty çalışma alanı ve bir API anahtarı (https://app.twenty.com/settings/api-webhooks adresinde oluşturun) + +## Başlarken + +Resmi iskelet oluşturucu aracını kullanarak yeni bir uygulama oluşturun, ardından kimlik doğrulaması yapıp geliştirmeye başlayın: + +```bash filename="Terminal" +# Scaffold a new app (includes all examples by default) +npx create-twenty-app@latest my-twenty-app +cd my-twenty-app + +# Start dev mode: automatically syncs local changes to your workspace +yarn twenty app:dev +``` + +İskelet oluşturucu, hangi örnek dosyaların dahil edileceğini kontrol etmek için iki modu destekler: + +```bash filename="Terminal" +# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item, skill) +npx create-twenty-app@latest my-app + +# Minimal: only core files (application-config.ts and default-role.ts) +npx create-twenty-app@latest my-app --minimal +``` + +Buradan şunları yapabilirsiniz: + +```bash filename="Terminal" +# Add a new entity to your application (guided) +yarn twenty entity:add + +# Watch your application's function logs +yarn twenty function:logs + +# Execute a function by name +yarn twenty function:execute -n my-function -p '{"name": "test"}' + +# Execute the pre-install function +yarn twenty function:execute --preInstall + +# Execute the post-install function +yarn twenty function:execute --postInstall + +# Uninstall the application from the current workspace +yarn twenty app:uninstall + +# Display commands' help +yarn twenty help +``` + +Ayrıca bkz.: [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) ve [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk) için CLI başvuru sayfaları. + +## Proje yapısı (şablondan oluşturulmuş) + +`npx create-twenty-app@latest my-twenty-app` komutunu çalıştırdığınızda iskelet oluşturucu şunları yapar: + +* Minimal bir temel uygulamayı `my-twenty-app/` içine kopyalar +* Yerel bir `twenty-sdk` bağımlılığı ve Yarn 4 yapılandırması ekler +* `twenty` CLI ile bağlantılı yapılandırma dosyaları ve betikler oluşturur +* İskelet oluşturma moduna bağlı olarak çekirdek dosyaları (uygulama yapılandırması, varsayılan işlev rolü, kurulum öncesi ve kurulum sonrası işlevler) ile örnek dosyaları üretir + +Varsayılan `--exhaustive` moduyla yeni oluşturulmuş bir uygulama şu şekilde görünür: + +```text filename="my-twenty-app/" +my-twenty-app/ + package.json + yarn.lock + .gitignore + .nvmrc + .yarnrc.yml + .yarn/ + install-state.gz + .oxlintrc.json + tsconfig.json + README.md + public/ # Public assets folder (images, fonts, etc.) + src/ + ├── application-config.ts # Required - main application configuration + ├── roles/ + │ └── default-role.ts # Default role for logic functions + ├── objects/ + │ └── example-object.ts # Example custom object definition + ├── fields/ + │ └── example-field.ts # Example standalone field definition + ├── logic-functions/ + │ ├── hello-world.ts # Example logic function + │ ├── pre-install.ts # Pre-install logic function + │ └── post-install.ts # Post-install logic function + ├── front-components/ + │ └── hello-world.tsx # Example front component + ├── views/ + │ └── example-view.ts # Example saved view definition + ├── navigation-menu-items/ + │ └── example-navigation-menu-item.ts # Example sidebar navigation link + └── skills/ + └── example-skill.ts # Example AI agent skill definition +``` + +`--minimal` ile yalnızca çekirdek dosyalar oluşturulur (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` ve `logic-functions/post-install.ts`). + +Genel hatlarıyla: + +* **package.json**: Uygulama adını, sürümünü, motorları (Node 24+, Yarn 4) bildirir ve `twenty-sdk` ile yerel `twenty` CLI'sine yetki devreden bir `twenty` betiği ekler. Tüm mevcut komutları listelemek için `yarn twenty help` komutunu çalıştırın. +* **.gitignore**: `node_modules`, `.yarn`, `generated/` (türlendirilmiş istemci), `dist/`, `build/`, kapsam klasörleri, günlük dosyaları ve `.env*` dosyaları gibi yaygın artifaktları yok sayar. +* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Proje tarafından kullanılan Yarn 4 araç zincirini kilitler ve yapılandırır. +* **.nvmrc**: Projenin beklediği Node.js sürümünü sabitler. +* **.oxlintrc.json** ve **tsconfig.json**: Uygulamanızın TypeScript kaynakları için linting ve TypeScript yapılandırması sağlar. +* **README.md**: Uygulama kökünde temel talimatların yer aldığı kısa bir README. +* **public/**: Uygulamanızla birlikte sunulacak genel varlıkları (görseller, yazı tipleri, statik dosyalar) depolamak için bir klasör. Buraya yerleştirilen dosyalar senkronizasyon sırasında yüklenir ve çalışma zamanında erişilebilir olur. +* **src/**: Uygulamanızı kod olarak tanımladığınız ana yer + +### Varlık algılama + +SDK, TypeScript dosyalarınızı **`export default define({...})`** çağrılarını arayarak ayrıştırıp varlıkları algılar. Her varlık türünün, `twenty-sdk` tarafından dışa aktarılan karşılık gelen bir yardımcı fonksiyonu vardır: + +| Yardımcı fonksiyon | Varlık türü | +| -------------------------------- | -------------------------------------------------------- | +| `defineObject` | Özel nesne tanımları | +| `defineLogicFunction` | Mantık işlevi tanımları | +| `definePreInstallLogicFunction` | Kurulum öncesi mantık işlevi (kurulumdan önce çalışır) | +| `definePostInstallLogicFunction` | Kurulum sonrası mantık işlevi (kurulumdan sonra çalışır) | +| `defineFrontComponent` | Ön bileşen tanımları | +| `defineRole` | Rol tanımları | +| `defineField` | Mevcut nesneler için alan genişletmeleri | +| `defineView` | Kaydedilmiş görünüm tanımları | +| `defineNavigationMenuItem` | Gezinme menüsü öğesi tanımları | +| `defineSkill` | Yapay zekâ ajanı yetenek tanımları | + + +**Dosya adlandırma esnektir.** Varlık algılama AST tabanlıdır — SDK, kaynak dosyalarınızı `export default define({...})` desenini bulmak için tarar. Dosyalarınızı ve klasörlerinizi dilediğiniz gibi düzenleyebilirsiniz. Varlık türüne göre gruplama (örn. `logic-functions/`, `roles/`) bir gereklilik değil, yalnızca kod organizasyonu için bir gelenektir. + + +Algılanan bir varlığa örnek: + +```typescript +// This file can be named anything and placed anywhere in src/ +import { defineObject, FieldType } from 'twenty-sdk'; + +export default defineObject({ + universalIdentifier: '...', + nameSingular: 'postCard', + // ... rest of config +}); +``` + +İlerideki komutlar daha fazla dosya ve klasör ekleyecektir: + +* `yarn twenty app:dev`, `node_modules/twenty-sdk/generated` içinde iki tiplendirilmiş API istemcisini otomatik olarak oluşturur: `CoreApiClient` (`/graphql` üzerinden çalışma alanı verileri için) ve `MetadataApiClient` (çalışma alanı yapılandırması ve `/metadata` üzerinden dosya yüklemeleri için). +* `yarn twenty entity:add`, özel nesneleriniz, fonksiyonlarınız, ön bileşenleriniz, rolleriniz, yetenekleriniz ve daha fazlası için `src/` altında varlık tanım dosyaları ekler. + +## Kimlik Doğrulama + +`yarn twenty auth:login` komutunu ilk kez çalıştırdığınızda, sizden şunlar istenir: + +* API URL’si (varsayılan: http://localhost:3000 veya mevcut çalışma alanı profiliniz) +* API anahtarı + +Kimlik bilgileriniz kullanıcı başına `~/.twenty/config.json` içinde saklanır. Birden fazla profili yönetebilir ve aralarında geçiş yapabilirsiniz. + +### Çalışma alanlarını yönetme + +```bash filename="Terminal" +# Login interactively (recommended) +yarn twenty auth:login + +# Login to a specific workspace profile +yarn twenty auth:login --workspace my-custom-workspace + +# List all configured workspaces +yarn twenty auth:list + +# Switch the default workspace (interactive) +yarn twenty auth:switch + +# Switch to a specific workspace +yarn twenty auth:switch production + +# Check current authentication status +yarn twenty auth:status +``` + +`yarn twenty auth:switch` ile çalışma alanlarını değiştirdikten sonra, sonraki tüm komutlar varsayılan olarak o çalışma alanını kullanacaktır. Yine de bunu geçici olarak `--workspace ` ile geçersiz kılabilirsiniz. + +## Manuel kurulum (iskelet oluşturucu olmadan) + +En iyi başlangıç deneyimi için `create-twenty-app` kullanmanızı önersek de, bir projeyi manuel olarak da kurabilirsiniz. CLI'yi global olarak kurmayın. Bunun yerine `twenty-sdk`'yi yerel bir bağımlılık olarak ekleyin ve package.json içinde tek bir betik tanımlayın: + +```bash filename="Terminal" +yarn add -D twenty-sdk +``` + +Ardından bir `twenty` betiği ekleyin: + +```json filename="package.json" +{ + "scripts": { + "twenty": "twenty" + } +} +``` + +Artık tüm komutları `yarn twenty ` üzerinden çalıştırabilirsiniz; örn. `yarn twenty app:dev`, `yarn twenty help` vb. + +## Sorun Giderme + +* Kimlik doğrulama hataları: `yarn twenty auth:login` çalıştırın ve API anahtarınızın gerekli izinlere sahip olduğundan emin olun. +* Sunucuya bağlanılamıyor: API URL’sini ve Twenty sunucusunun erişilebilir olduğunu doğrulayın. +* Türler veya istemci eksik/eski: `yarn twenty app:dev` komutunu yeniden çalıştırın — tiplendirilmiş istemciyi otomatik olarak oluşturur. +* Geliştirme modu eşitlenmiyor: `yarn twenty app:dev`'in çalıştığından ve değişikliklerin ortamınız tarafından yok sayılmadığından emin olun. + +Discord Yardım Kanalı: https://discord.com/channels/1130383047699738754/1130386664812982322 diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/publishing.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/publishing.mdx new file mode 100644 index 0000000000..6962471fa6 --- /dev/null +++ b/packages/twenty-docs/l/tr/developers/extend/apps/publishing.mdx @@ -0,0 +1,119 @@ +--- +title: Yayımlama +description: Twenty uygulamanızı pazaryerine sunun ya da dahili olarak dağıtın. +--- + + +Uygulamalar şu anda alfa testinde. Özellik işlevsel ancak hâlâ gelişmekte. + + +## Genel Bakış + +Uygulamanız [yerelde derlenip test edildikten sonra](/l/tr/developers/extend/apps/building), dağıtım için iki yolunuz vardır: + +* **npm’ye yayımlama** — uygulamanızı Twenty pazaryerinde listeleyin; böylece herhangi bir çalışma alanı keşfedip yükleyebilir. +* **Bir tarball gönderin** — uygulamanızı herkese açık yapmadan, dahili kullanım için belirli bir Twenty sunucusuna dağıtın. + +## npm’ye yayımlama + +npm’ye yayımlamak, uygulamanızın Twenty pazaryerinde keşfedilebilir olmasını sağlar. Herhangi bir Twenty çalışma alanı, pazaryeri uygulamalarına doğrudan arayüzden göz atabilir, yükleyebilir ve güncelleyebilir. + +### Gereksinimler + +* Bir [npm](https://www.npmjs.com) hesabı +* Paket adınız **mutlaka** `twenty-app-` önekini kullanmalıdır (ör. `twenty-app-postcard-sender`) + +### Adımlar + +1. **Uygulamanızı derleyin** — CLI, TypeScript kaynaklarınızı derler ve uygulama manifestini oluşturur: + +```bash filename="Terminal" +yarn twenty app:build +``` + +2. **npm’ye yayımlayın** — derlenmiş paketi npm registry’ye gönderin: + +```bash filename="Terminal" +npx twenty app:publish +``` + +### Otomatik keşif + +`twenty-app-` önekine sahip paketler, Twenty pazaryeri kataloğu tarafından otomatik olarak keşfedilir. Yayımlandıktan sonra, uygulamanız birkaç dakika içinde pazaryerinde görünür — manuel kayıt veya onay gerekmez. + +### CI üzerinden yayımlama + +İskelet proje, her sürümde yayımlama yapan bir GitHub Actions iş akışını içerir. Önce `app:build` çalıştırır, ardından derleme çıktısından `npm publish --provenance` çalıştırır: + +```yaml filename=".github/workflows/publish.yml" +name: Publish +on: + release: + types: [published] + +permissions: + contents: read + id-token: write + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "24" + registry-url: https://registry.npmjs.org + - run: yarn install --immutable + - run: npx twenty app:build + - run: npm publish --provenance --access public + working-directory: .twenty/output + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} +``` + +Diğer CI sistemleri (GitLab CI, CircleCI, vb.) için de aynı üç komut geçerlidir: `yarn install`, `npx twenty app:build` ve ardından `.twenty/output` dizininden `npm publish`. + + +**npm provenance** isteğe bağlıdır ancak önerilir. `--provenance` ile yayımlamak, npm listenize bir güven rozeti ekler ve kullanıcıların paketin herkese açık bir CI ardışık düzenindeki belirli bir commit’ten oluşturulduğunu doğrulamasını sağlar. Kurulum talimatları için [npm provenance belgelerine](https://docs.npmjs.com/generating-provenance-statements) bakın. + + +## Dahili dağıtım + +Genel kullanıma açık olmasını istemediğiniz uygulamalar — sahipli araçlar, yalnızca kurumsal entegrasyonlar veya deneysel yapılar — için bir tarball’ı doğrudan bir Twenty sunucusuna gönderebilirsiniz. + +### Bir tarball gönderin + +Uygulamanızı derleyin ve tek adımda belirli bir sunucuya dağıtın: + +```bash filename="Terminal" +npx twenty app:publish --server +``` + +Daha sonra, bu sunucudaki herhangi bir çalışma alanı uygulamayı **Applications** ayarları sayfasından yükleyip güncelleyebilir. + +### Sürüm yönetimi + +Bir güncelleme yayımlamak için: + +1. `package.json` içindeki `version` alanını artırın +2. `npx twenty app:publish --server ` ile yeni bir tarball gönderin +3. O sunucudaki çalışma alanları, ayarlarında kullanılabilir güncellemeyi görecektir. + + +Dahili uygulamalar, gönderildikleri sunucu ile sınırlıdır. Genel pazaryerinde görünmezler ve diğer sunuculardaki çalışma alanları tarafından yüklenemezler. + + +## Uygulama kategorileri + +Twenty, uygulamaları nasıl dağıtıldıklarına göre üç kategoriye ayırır: + +| Kategori | Nasıl Çalışır | Pazaryerinde görünür mü? | +| --------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| **Geliştirme** | `yarn twenty app:dev` ile çalışan yerel geliştirme modu uygulamaları. Derleme ve test için kullanılır. | Hayır | +| **Yayımlanmış** | `twenty-app-` önekiyle npm’ye yayımlanan uygulamalar. Herhangi bir çalışma alanının yükleyebilmesi için pazaryerinde listelenir. | Evet | +| **Dahili** | Bir tarball aracılığıyla belirli bir sunucuya dağıtılan uygulamalar. Yalnızca o sunucudaki çalışma alanlarının kullanımına açıktır. | Hayır | + + +Uygulamanızı geliştirirken **Geliştirme** modunda başlayın. Hazır olduğunda, geniş dağıtım için **Yayımlanmış** (npm) ya da özel dağıtım için **Dahili** (tarball) seçeneğini tercih edin. + diff --git a/packages/twenty-docs/l/tr/developers/extend/capabilities/apps.mdx b/packages/twenty-docs/l/tr/developers/extend/capabilities/apps.mdx index 140a6e14bc..096d5d075e 100644 --- a/packages/twenty-docs/l/tr/developers/extend/capabilities/apps.mdx +++ b/packages/twenty-docs/l/tr/developers/extend/capabilities/apps.mdx @@ -321,11 +321,11 @@ Bunları `fields` dizinizde tanımlamanız gerekmez — yalnızca özel alanlar ancak bu önerilmez. -### Defining fields on existing objects +### Mevcut nesneler üzerinde alanları tanımlama -Use `defineField()` to add custom fields to existing objects — both standard objects (like `company`, `person`, `opportunity`) and custom objects defined by other apps. Each field lives in its own file and references the target object by its `universalIdentifier`. +Mevcut nesnelere özel alanlar eklemek için `defineField()` kullanın — hem standart nesnelere (ör. `company`, `person`, `opportunity`) hem de diğer uygulamalar tarafından tanımlanan özel nesnelere. Her alan kendi dosyasında bulunur ve hedef nesneye `universalIdentifier` ile başvurur. -To reference standard objects, import `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` from `twenty-sdk`. This constant provides stable identifiers for all built-in objects and their fields: +Standart nesnelere başvurmak için `twenty-sdk` içinden `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` öğesini içe aktarın. Bu sabit, tüm yerleşik nesneler ve onların alanları için kararlı tanımlayıcılar sağlar: ```typescript // src/fields/apollo-total-funding.field.ts @@ -349,22 +349,22 @@ export default defineField({ Önemli noktalar: -* `objectUniversalIdentifier` tells Twenty which object to attach the field to. Use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS..universalIdentifier` for standard objects. -* Each field requires its own stable `universalIdentifier`, a `name`, `type`, `label`, and the target `objectUniversalIdentifier`. -* You can scaffold new fields using `yarn twenty entity:add` and choosing the field option. -* `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` is also exported as `STANDARD_OBJECT` for convenience — both refer to the same constant. +* `objectUniversalIdentifier`, alanın hangi nesneye ekleneceğini Twenty'ye bildirir. `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS..universalIdentifier` standart nesneler için kullanın. +* Her alan için kararlı bir `universalIdentifier`, `name`, `type`, `label` ve hedef `objectUniversalIdentifier` gerekir. +* `yarn twenty entity:add` kullanarak yeni alanlar oluşturabilir ve alan seçeneğini seçebilirsiniz. +* `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS`, kolaylık olması için `STANDARD_OBJECT` olarak da dışa aktarılır — her ikisi de aynı sabite atıfta bulunur. -Available standard objects include: `attachment`, `blocklist`, `calendarChannel`, `calendarEvent`, `calendarEventParticipant`, `company`, `connectedAccount`, `dashboard`, `favorite`, `favoriteFolder`, `message`, `messageChannel`, `messageParticipant`, `messageThread`, `note`, `noteTarget`, `opportunity`, `person`, `task`, `taskTarget`, `timelineActivity`, `workflow`, `workflowAutomatedTrigger`, `workflowRun`, `workflowVersion`, and `workspaceMember`. +Kullanılabilir standart nesneler şunları içerir: `attachment`, `blocklist`, `calendarChannel`, `calendarEvent`, `calendarEventParticipant`, `company`, `connectedAccount`, `dashboard`, `favorite`, `favoriteFolder`, `message`, `messageChannel`, `messageParticipant`, `messageThread`, `note`, `noteTarget`, `opportunity`, `person`, `task`, `taskTarget`, `timelineActivity`, `workflow`, `workflowAutomatedTrigger`, `workflowRun`, `workflowVersion` ve `workspaceMember`. -Each standard object also exposes its field identifiers. For example, to reference a specific field on a standard object in role permissions: +Her standart nesne ayrıca alan tanımlayıcılarını da sunar. Örneğin, rol izinlerinde standart bir nesnedeki belirli bir alana başvurmak için: ```typescript STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.fields.name.universalIdentifier ``` -#### Relation fields on existing objects +#### Mevcut nesnelerde ilişki alanları -You can also define relation fields that link existing objects to your custom objects: +Mevcut nesneleri özel nesnelerinize bağlayan ilişki alanlarını da tanımlayabilirsiniz: ```typescript // src/fields/people-on-call-recording.field.ts diff --git a/packages/twenty-docs/l/tr/developers/extend/extend.mdx b/packages/twenty-docs/l/tr/developers/extend/extend.mdx index 65af313b32..83bd85901d 100644 --- a/packages/twenty-docs/l/tr/developers/extend/extend.mdx +++ b/packages/twenty-docs/l/tr/developers/extend/extend.mdx @@ -1,7 +1,6 @@ --- title: Genişlet description: Twenty'nin işlevselliğini API'ler, webhook'lar ve özel uygulamalarla genişletin. -redirect: /developers/introduction --- @@ -16,18 +15,18 @@ Twenty, genişletilebilir olacak şekilde tasarlanmıştır. Mevcut araçların * **API'ler**: CRM verilerinizi REST veya GraphQL kullanarak programatik olarak sorgulayın ve değiştirin * **Webhook'lar**: Twenty'de olaylar gerçekleştiğinde gerçek zamanlı bildirimler alın -* **Uygulamalar**: Twenty'nin yeteneklerini genişleten özel uygulamalar oluşturun - Çok yakında! +* **Uygulamalar**: Twenty'nin yeteneklerini genişleten özel uygulamalar oluşturun ## Başlarken - + Twenty'ye programatik olarak bağlanın - + Olaylardan gerçek zamanlı olarak haberdar olun - - Özelleştirmeleri kod olarak oluşturun (Alfa) + + Özelleştirmeleri kod olarak oluşturun diff --git a/packages/twenty-docs/l/tr/developers/extend/webhooks.mdx b/packages/twenty-docs/l/tr/developers/extend/webhooks.mdx new file mode 100644 index 0000000000..d108c7f0ae --- /dev/null +++ b/packages/twenty-docs/l/tr/developers/extend/webhooks.mdx @@ -0,0 +1,116 @@ +--- +title: Webhook'lar +description: CRM'inizde olaylar gerçekleştiğinde gerçek zamanlı bildirimler alın. +--- + +import { VimeoEmbed } from '/snippets/vimeo-embed.mdx'; + +Webhook'lar, Twenty'de olaylar gerçekleştiğinde verileri sistemlerinize gerçek zamanlı olarak iletir — sürekli sorgulamaya gerek yok. Harici sistemleri senkron tutmak, otomasyonları tetiklemek veya uyarılar göndermek için bunları kullanın. + +## Webhook oluştur + +1. **Ayarlar → API'ler ve Webhook'lar → Webhook'lar**'a gidin +2. **+ Webhook oluştur**'a tıklayın +3. Webhook URL'nizi girin (herkese açık olarak erişilebilir olmalıdır) +4. **Kaydet**'e tıklayın + +Webhook anında etkinleşir ve bildirim göndermeye başlar. + + + +### Webhook'ları Yönet + +**Düzenle**: Webhook'u tıklayın → URL'yi güncelleyin → **Kaydet** + +**Sil**: Webhook'u tıklayın → **Sil** → Onayla + +## Etkinlikler + +Twenty, şu olay türleri için webhook'lar gönderir: + +| Etkinlik | Örnek | +| --------------------- | ---------------------------------------------------------- | +| **Kayıt Oluşturuldu** | `person.created`, `company.created`, `note.created` | +| **Kayıt Güncellendi** | `person.updated`, `company.updated`, `opportunity.updated` | +| **Kayıt Silindi** | `person.deleted`, `company.deleted` | + +Tüm olay türleri webhook URL'nize gönderilir. Olay filtreleme özelliği ilerideki sürümlerde eklenebilir. + +## Yük Biçimi + +Her webhook, JSON gövdeli bir HTTP POST gönderir: + +```json +{ + "event": "person.created", + "data": { + "id": "abc12345", + "firstName": "Alice", + "lastName": "Doe", + "email": "alice@example.com", + "createdAt": "2025-02-10T15:30:45Z", + "createdBy": "user_123" + }, + "timestamp": "2025-02-10T15:30:50Z" +} +``` + +| Alan | Açıklama | +| ----------- | --------------------------------------------- | +| `event` | Ne oldu (ör. `person.created`) | +| `data` | Oluşturulan/güncellenen/silinen kaydın tamamı | +| `timestamp` | Olayın ne zaman gerçekleştiği (UTC) | + + +Alındığını onaylamak için **2xx HTTP durumu** (200-299) ile yanıt verin. 2xx dışı yanıtlar teslimat hataları olarak kaydedilir. + + +## Webhook Doğrulaması + +Twenty, güvenlik için her webhook isteğini imzalar. İsteklerin gerçekliğini sağlamak için imzaları doğrulayın. + +### Üstbilgiler + +| Başlık | Açıklama | +| ---------------------------- | ------------------- | +| `X-Twenty-Webhook-Signature` | HMAC SHA256 imzası | +| `X-Twenty-Webhook-Timestamp` | İstek zaman damgası | + +### Doğrulama Adımları + +1. `X-Twenty-Webhook-Timestamp` değerinden zaman damgasını alın +2. Dizeyi oluşturun: `{timestamp}:{JSON payload}` +3. Webhook gizli anahtarınızı kullanarak HMAC SHA256 hesaplayın +4. `X-Twenty-Webhook-Signature` ile karşılaştırın + +### Örnek (Node.js) + +```javascript +const crypto = require("crypto"); + +const timestamp = req.headers["x-twenty-webhook-timestamp"]; +const payload = JSON.stringify(req.body); +const secret = "your-webhook-secret"; + +const stringToSign = `${timestamp}:${payload}`; +const expectedSignature = crypto + .createHmac("sha256", secret) + .update(stringToSign) + .digest("hex"); + +const receivedSignature = req.headers["x-twenty-webhook-signature"]; +const isValid = crypto.timingSafeEqual( + Buffer.from(expectedSignature, "hex"), + Buffer.from(receivedSignature, "hex") +); +``` + +## Webhook'lar ve İş Akışları + +| Yöntem | Yön | Kullanım Senaryosu | +| ---------------------------------- | --- | --------------------------------------------------------------------------- | +| **Webhook'lar** | OUT | Herhangi bir kayıt değişikliğini harici sistemlere otomatik olarak bildirin | +| **İş Akışı + HTTP İsteği** | OUT | Özel mantıkla (filtreler, dönüşümler) verileri dışarı gönderin | +| **İş Akışı Webhook Tetikleyicisi** | IN | Harici sistemlerden Twenty'ye veri alın | + +Harici verileri almak için bkz. [Bir Webhook Tetikleyicisi Kurun](/l/tr/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger). diff --git a/packages/twenty-docs/l/tr/developers/introduction.mdx b/packages/twenty-docs/l/tr/developers/introduction.mdx index bbc336ce65..943afd7952 100644 --- a/packages/twenty-docs/l/tr/developers/introduction.mdx +++ b/packages/twenty-docs/l/tr/developers/introduction.mdx @@ -5,28 +5,18 @@ description: Twenty Geliştirici Belgeleri'ne hoş geldiniz; Twenty'yi genişlet import { CardTitle } from "/snippets/card-title.mdx" - - - API - REST veya GraphQL ile CRM verilerinizi sorgulayın ve değiştirin. + + + Extend + API'ler, webhook'lar ve özel uygulamalarla entegrasyonlar oluşturun. - - Webhooks - Olaylar gerçekleştiğinde gerçek zamanlı bildirimler alın. - - - - Apps - Twenty'nin yeteneklerini genişleten özel uygulamalar oluşturun. - - - + Self-Host Twenty'yi kendi altyapınızda dağıtın ve yönetin. - + Contribute Açık kaynak topluluğumuza katılın ve Twenty'ye katkıda bulunun. diff --git a/packages/twenty-docs/l/tr/user-guide/data-migration/how-tos/export-your-data.mdx b/packages/twenty-docs/l/tr/user-guide/data-migration/how-tos/export-your-data.mdx index 2c82ffdecc..fdce17db0b 100644 --- a/packages/twenty-docs/l/tr/user-guide/data-migration/how-tos/export-your-data.mdx +++ b/packages/twenty-docs/l/tr/user-guide/data-migration/how-tos/export-your-data.mdx @@ -24,7 +24,7 @@ Yedekleme, raporlama veya geçiş için çalışma alanı verilerinizi CSV'ye d * Yalnızca **görünür sütunlar** dışa aktarılır * Yalnızca **filtrelenmiş kayıtlar** dışa aktarılır (mevcut görünümünüze göre) -Daha büyük dışa aktarmalar için (20.000+ kayıt), toplu halde dışa aktarmak üzere filtreleri kullanın veya [API](/l/tr/developers/api)'yi kullanın. +Daha büyük dışa aktarmalar için (20.000+ kayıt), toplu halde dışa aktarmak üzere filtreleri kullanın veya [API](/l/tr/developers/extend/api)'yi kullanın. ### İzinler @@ -148,7 +148,7 @@ API'nin kayıt sınırı yoktur: 2. Kayıtları sorgulamak için GraphQL API'sini kullanın 3. Sonuçları uygulamanızda işleyin -Bkz: [API Belgeleri](/l/tr/developers/api) +Bkz: [API Belgeleri](/l/tr/developers/extend/api) ## İpuçları ve En İyi Uygulamalar @@ -206,4 +206,4 @@ Dışa aktarılan dosyalar hassas veriler içerebilir: * [Mevcut Kayıtlar Nasıl Güncellenir](/l/tr/user-guide/data-migration/how-tos/update-existing-records-via-import) — dışa aktarmanızı düzenleyin ve yeniden içe aktarın * [API ile Veri Nasıl İçe Aktarılır](/l/tr/user-guide/data-migration/how-tos/import-data-via-api) — büyük veri kümeleri için -* [API Belgeleri](/l/tr/developers/api) — özel dışa aktarma iş akışları oluşturun +* [API Belgeleri](/l/tr/developers/extend/api) — özel dışa aktarma iş akışları oluşturun diff --git a/packages/twenty-docs/l/tr/user-guide/data-migration/how-tos/import-data-via-api.mdx b/packages/twenty-docs/l/tr/user-guide/data-migration/how-tos/import-data-via-api.mdx index b50b14db03..6c76f1ee9b 100644 --- a/packages/twenty-docs/l/tr/user-guide/data-migration/how-tos/import-data-via-api.mdx +++ b/packages/twenty-docs/l/tr/user-guide/data-migration/how-tos/import-data-via-api.mdx @@ -57,10 +57,10 @@ API anahtarınıza sahip olan herkes çalışma alanı verilerinize erişebilir Twenty iki API türünü destekler: -| API | En uygun | Dokümantasyon | -| ----------- | ------------------------------------------------------------ | ----------------------------------------------------- | -| **GraphQL** | Esnek sorgular, ilişkili verileri getirme, karmaşık işlemler | [API Belgeleri](/l/tr/developers/api) | -| **REST** | Basit CRUD işlemleri, alışıldık REST kalıpları | [API Belgeleri](/l/tr/developers/api) | +| API | En uygun | Dokümantasyon | +| ----------- | ------------------------------------------------------------ | --------------------------------------- | +| **GraphQL** | Esnek sorgular, ilişkili verileri getirme, karmaşık işlemler | [API Belgeleri](/l/tr/developers/extend/api) | +| **REST** | Basit CRUD işlemleri, alışıldık REST kalıpları | [API Belgeleri](/l/tr/developers/extend/api) | Her iki API de şunları destekler: @@ -173,4 +173,4 @@ Karmaşık API geçişleri için iş ortaklarımız yardımcı olabilir: Tam uygulama ayrıntıları, kod örnekleri ve şema başvurusu için: -* [API Belgeleri](/l/tr/developers/api) +* [API Belgeleri](/l/tr/developers/extend/api) diff --git a/packages/twenty-docs/l/tr/user-guide/getting-started/capabilities/what-is-twenty.mdx b/packages/twenty-docs/l/tr/user-guide/getting-started/capabilities/what-is-twenty.mdx index cbab83e6ce..ae98273442 100644 --- a/packages/twenty-docs/l/tr/user-guide/getting-started/capabilities/what-is-twenty.mdx +++ b/packages/twenty-docs/l/tr/user-guide/getting-started/capabilities/what-is-twenty.mdx @@ -35,7 +35,7 @@ Açık kaynak, yaklaşımımızın temel taşıdır, Twenty'nin topluluğu ile b * **Panolar:** Özel raporlar ve görselleştirmelerle performansı izleyin. [Panoları görüntüleyin](/l/tr/user-guide/dashboards/overview). * **İzinler ve Erişim:** Rol tabanlı izinlerle verilerinizi kimlerin görüntüleyebileceğini, düzenleyebileceğini ve yönetebileceğini kontrol edin. [Erişimi yapılandırın](/l/tr/user-guide/permissions-access/overview). * **Notlar ve Görevler:** Daha iyi iş birliği için kayıtlarınıza bağlı notlar ve görevler oluşturun. -* **API & Webhooks:** Diğer uygulamalara bağlanın ve özel entegrasyonlar oluşturun. [Start integrating](/l/tr/developers/api). +* **API & Webhooks:** Diğer uygulamalara bağlanın ve özel entegrasyonlar oluşturun. [Entegrasyona başlayın](/l/tr/developers/extend/api). ## Şimdi katılın diff --git a/packages/twenty-docs/l/tr/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx b/packages/twenty-docs/l/tr/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx index 114f8a47e5..db02346b51 100644 --- a/packages/twenty-docs/l/tr/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx +++ b/packages/twenty-docs/l/tr/user-guide/workflows/how-tos/crm-automations/display-related-record-data.mdx @@ -95,7 +95,7 @@ Hedef alanları **Ayarlar → Veri Modeli → Fırsatlar** içinde oluşturun: * Şirket Büyüklüğü: `{{searchRecords[0].employees}}` -**Görevler ve Notlar sınırlaması**: Görevler ve Notlar üzerindeki ilişkiler çoktan çoğa olarak sabit kodlanmıştır ve henüz iş akışı tetikleyicileri veya eylemlerinde mevcut değildir. Bu ilişkilere erişmek için bunun yerine [API](/l/tr/developers/api) kullanın. +**Görevler ve Notlar sınırlaması**: Görevler ve Notlar üzerindeki ilişkiler çoktan çoğa olarak sabit kodlanmıştır ve henüz iş akışı tetikleyicileri veya eylemlerinde mevcut değildir. Bu ilişkilere erişmek için bunun yerine [API](/l/tr/developers/extend/api) kullanın. ## Çift Yönlü Senkronizasyon diff --git a/packages/twenty-docs/l/zh/developers/contribute/capabilities/frontend-development/frontend-commands.mdx b/packages/twenty-docs/l/zh/developers/contribute/capabilities/frontend-development/frontend-commands.mdx index d642d5d880..dd623139d4 100644 --- a/packages/twenty-docs/l/zh/developers/contribute/capabilities/frontend-development/frontend-commands.mdx +++ b/packages/twenty-docs/l/zh/developers/contribute/capabilities/frontend-development/frontend-commands.mdx @@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/zh/developers/contribute/capabilities/front ### 状态管理 -[Jotai](https://jotai.org/) 处理状态管理。 +[Jotai](https://jotai.org/) handles state management. 查看[最佳实践](/l/zh/developers/contribute/capabilities/frontend-development/best-practices-front#state-management)以获取有关状态管理的更多信息。