الانتقال إلى المحتوى الرئيسي
التطبيقات حاليًا في مرحلة الاختبار الألفا. الميزة تعمل لكنها لا تزال قيد التطور.

ما هي التطبيقات؟

تتيح لك التطبيقات إنشاء وإدارة تخصيصات Twenty ككود. بدلًا من تكوين كل شيء عبر واجهة المستخدم، تُعرِّف نموذج بياناتك ووظائف المنطق في الكود — مما يجعل البناء والصيانة والنشر إلى مساحات عمل متعددة أسرع. ما الذي يمكنك فعله اليوم:
  • عرِّف كائنات وحقولًا مخصصة على شكل كود (نموذج بيانات مُدار)
  • أنشئ وظائف منطقية مع مشغلات مخصصة
  • انشر التطبيق نفسه عبر مساحات عمل متعددة

المتطلبات الأساسية

البدء

أنشئ تطبيقًا جديدًا باستخدام المُهيئ الرسمي، ثم قم بالمصادقة وابدأ التطوير:
# Scaffold a new app
npx create-twenty-app@latest my-twenty-app
cd my-twenty-app

# If you don't use yarn@4
corepack enable
yarn install

# Authenticate using your API key (you'll be prompted)
yarn twenty auth:login

# Start dev mode: automatically syncs local changes to your workspace
yarn twenty app:dev
من هنا يمكنك:
# Add a new entity to your application (guided)
yarn twenty entity:add

# Generate a typed Twenty client and workspace entity types
yarn twenty app:generate

# 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"}'

# Uninstall the application from the current workspace
yarn twenty app:uninstall

# Display commands' help
yarn twenty help
راجع أيضًا: صفحات مرجع CLI لـ create-twenty-app وtwenty-sdk CLI.

هيكل المشروع (مُنشأ بالقالب)

عند تشغيل npx create-twenty-app@latest my-twenty-app، يقوم المُهيئ بما يلي:
  • ينسخ تطبيقًا أساسيًا مصغّرًا إلى my-twenty-app/
  • يضيف اعتمادًا محليًا twenty-sdk وتهيئة Yarn 4
  • ينشئ ملفات ضبط ونصوصًا مرتبطة بـ twenty CLI
  • يُولّد ضبطًا افتراضيًا للتطبيق ودورًا افتراضيًا للوظيفة
يبدو التطبيق المُنشأ حديثًا بالقالب كما يلي:
my-twenty-app/
  package.json
  yarn.lock
  .gitignore
  .nvmrc
  .yarnrc.yml
  .yarn/
    install-state.gz
  eslint.config.mjs
  tsconfig.json
  README.md
  public/                           # مجلد الأصول العامة (صور، خطوط، إلخ)
  src/
  ├── application-config.ts           # مطلوب - التكوين الرئيسي للتطبيق
  ├── roles/
  │   └── default-role.ts               # الدور الافتراضي لوظائف المنطق
  ├── logic-functions/
  │   └── hello-world.ts                # مثال لوظيفة منطقية
  └── front-components/
      └── hello-world.tsx               # مثال لمكوّن الواجهة الأمامية
بشكل عام:
  • package.json: Declares the app name, version, engines (Node 24+, Yarn 4), and adds twenty-sdk plus a twenty script that delegates to the local twenty CLI. Run yarn twenty help to list all available commands.
  • .gitignore: يتجاهل العناصر الشائعة مثل node_modules و.yarn وgenerated/ (عميل مضبوط الأنواع) وdist/ وbuild/ ومجلدات التغطية وملفات السجلات وملفات .env*.
  • yarn.lock، .yarnrc.yml، .yarn/: تقوم بقفل وتكوين حزمة أدوات Yarn 4 المستخدمة في المشروع.
  • .nvmrc: يثبّت إصدار Node.js المتوقع للمشروع.
  • eslint.config.mjs وtsconfig.json: يقدّمان إعدادات الفحص والتهيئة لـ TypeScript لمصادر TypeScript في تطبيقك.
  • README.md: ملف README قصير في جذر التطبيق يتضمن تعليمات أساسية.
  • public/: مجلد لتخزين الأصول العامة (صور، خطوط، ملفات ثابتة) التي سيتم تقديمها مع تطبيقك. الملفات الموضوعة هنا تُرفع أثناء المزامنة وتكون متاحة أثناء وقت التشغيل.
  • src/: المكان الرئيسي حيث تعرّف تطبيقك ككود

اكتشاف الكيانات

يكتشف SDK الكيانات عبر تحليل ملفات TypeScript الخاصة بك بحثًا عن استدعاءات export default define<Entity>({...}). يحتوي كل نوع كيان على دالة مساعدة مقابلة يتم تصديرها من twenty-sdk:
دالة مساعدةنوع الكيان
defineObject()تعريفات كائنات مخصصة
defineLogicFunction()تعريفات الوظائف المنطقية
defineFrontComponent()Front component definitions
defineRole()تعريفات الأدوار
defineField()امتدادات الحقول للكائنات الموجودة
تسمية الملفات مرنة. يعتمد اكتشاف الكيانات على بنية الشجرة المجردة (AST) — إذ يقوم SDK بفحص ملفات المصدر لديك بحثًا عن النمط export default define<Entity>({...}). يمكنك تنظيم ملفاتك ومجلداتك كيفما تشاء. التجميع حسب نوع الكيان (مثلًا، logic-functions/ وroles/) هو مجرد عرف لتنظيم الشيفرة، وليس مطلبًا إلزاميًا.
مثال على كيان تم اكتشافه:
// 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:generate will create a generated/ folder (typed Twenty client + workspace types).
  • yarn twenty entity:add will add entity definition files under src/ for your custom objects, functions, front components, or roles.

المصادقة

The first time you run yarn twenty auth:login, you’ll be prompted for:
  • عنوان URL لواجهة برمجة التطبيقات (الافتراضي http://localhost:3000 أو ملف تعريف مساحة العمل الحالية لديك)
  • مفتاح واجهة برمجة التطبيقات
تُخزَّن بيانات اعتمادك لكل مستخدم في ~/.twenty/config.json. You can maintain multiple profiles and switch between them.

Managing workspaces

# 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
Once you’ve switched workspaces with yarn twenty auth:switch, all subsequent commands will use that workspace by default. You can still override it temporarily with --workspace <name>.

استخدم موارد SDK (الأنواع والتكوين)

يوفّر twenty-sdk كتلَ بناءٍ مضبوطة الأنواع ودوال مساعدة تستخدمها داخل تطبيقك. فيما يلي الأجزاء الأساسية التي ستتعامل معها غالبًا.

دوال مساعدة

يوفّر SDK دوالًا مساعدة لتعريف كيانات تطبيقك. كما هو موضح في اكتشاف الكيانات، يجب استخدام export default define<Entity>({...}) كي يتم اكتشاف كياناتك:
دالةالغرض
defineApplication()تهيئة بيانات التعريف للتطبيق (مطلوب، واحد لكل تطبيق)
defineObject()تعريف كائنات مخصصة مع حقول
defineLogicFunction()تعريف وظائف منطقية مع معالجات
defineFrontComponent()عرِّف مكوّنات أمامية لواجهة مستخدم مخصّصة
defineRole()تهيئة صلاحيات الدور والوصول إلى الكائنات
defineField()وسّع الكائنات الموجودة بحقول إضافية
تتحقق هذه الدوال من تكوينك وقت البناء وتوفّر إكمالًا تلقائيًا في بيئة التطوير وأمان الأنواع.

تعريف الكائنات

تصف الكائنات المخصصة كلًا من المخطط والسلوك للسجلات في مساحة عملك. استخدم defineObject() لتعريف كائنات مع تحقق مدمج:
// 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 اختيارية — يمكنك تعريف كائنات بدون حقول مخصصة.
  • You can scaffold new objects using yarn twenty entity:add, which guides you through naming, fields, and relationships.
يتم إنشاء الحقول الأساسية تلقائيًا. عند تعريف كائن مخصص، يضيف Twenty تلقائيًا حقولًا قياسية مثل name وcreatedAt وupdatedAt وcreatedBy وposition وdeletedAt. لا تحتاج إلى تعريف هذه في مصفوفة fields — أضف فقط حقولك المخصصة.

تكوين التطبيق (application-config.ts)

كل تطبيق لديه ملف واحد application-config.ts يصف:
  • هوية التطبيق: المعرفات، اسم العرض، والوصف.
  • كيفية تشغيل وظائفه: الدور الذي تستخدمه للأذونات.
  • متغيرات (اختياري): أزواج مفتاح-قيمة تُعرض لوظائفك كمتغيرات بيئة.
Use defineApplication() to define your application configuration:
// 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 يجب أن يطابق ملف الدور (انظر أدناه).

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

يمكن للتطبيقات تعريف أدوار تُغلّف الصلاحيات على كائنات وإجراءات مساحة العمل لديك. يعين الحقل defaultRoleUniversalIdentifier في application-config.ts الدور الافتراضي الذي تستخدمه وظائف المنطق في تطبيقك.
  • مفتاح واجهة البرمجة في وقت التشغيل المحقون باسم TWENTY_API_KEY مستمد من دور الوظيفة الافتراضي هذا.
  • سيُقيَّد العميل مضبوط الأنواع بالأذونات الممنوحة لذلك الدور.
  • اتبع مبدأ أقل الامتياز: أنشئ دورًا مخصصًا بالأذونات التي تحتاجها وظائفك فقط، ثم أشِر إلى معرّفه الشامل.
الدور الافتراضي للوظيفة (*.role.ts)
عند توليد تطبيق جديد بالقالب، ينشئ CLI أيضًا ملف دور افتراضي. استخدم defineRole() لتعريف أدوار مع تحقق مدمج:
// 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.

تكوين الوظيفة المنطقية ونقطة الدخول

كل ملف وظيفة يستخدم defineLogicFunction() لتصدير تكوين مع معالج ومشغّلات اختيارية.
// src/app/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '~/generated';

const handler = async (params: RoutePayload) => {
  const client = new Twenty(); // generated typed client
  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', -> الاستدعاء على <APP_URL>/s/post-card/create
  • cron: يشغّل وظيفتك على جدول باستخدام تعبير CRON.
  • databaseEvent: يعمل على أحداث دورة حياة كائنات مساحة العمل. عندما تكون عملية الحدث هي updated، يمكن تحديد الحقول المحددة المراد الاستماع إليها في مصفوفة updatedFields. إذا تُركت غير معرّفة أو فارغة، فسيؤدي أي تحديث إلى تشغيل الدالة.
مثال: person.updated
الملاحظات:
  • المصفوفة triggers اختيارية. يمكن استخدام الوظائف بدون مشغلات كوظائف مساعدة تُستدعى بواسطة وظائف أخرى.
  • يمكنك مزج أنواع متعددة من المشغلات في وظيفة واحدة.

حمولة مشغل المسار

تغيير غير متوافق (v1.16، يناير 2026): لقد تغير تنسيق حمولة مشغل المسار. قبل v1.16، كانت معلمات الاستعلام، ومعلمات المسار، وجسم الطلب تُرسل مباشرةً كحمولة. بدءًا من v1.16، أصبحت متداخلة داخل كائن منظَّم RoutePayload.قبل v1.16:
const handler = async (params) => {
  const { param1, param2 } = params; // Direct access
};
بعد v1.16:
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:
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 على البنية التالية:
الخاصيةالنوعالوصف
headersRecord<string, string | undefined>رؤوس HTTP (فقط تلك المدرجة في forwardedRequestHeaders)
queryStringParametersRecord<string, string | undefined>معلمات سلسلة الاستعلام (تُضمّ القيم المتعددة باستخدام فواصل)
pathParametersRecord<string, string | undefined>معلمات المسار المستخرجة من نمط المسار (على سبيل المثال، /users/:id{ id: '123' })
المحتوىobject | nullجسم الطلب المُحلَّل (JSON)
isBase64Encodedقيمة منطقيةما إذا كان جسم الطلب مُرمَّزًا بترميز base64
requestContext.http.methodstringطريقة HTTP (GET, POST, PUT, PATCH, DELETE)
requestContext.http.pathstringالمسار الخام للطلب

تمرير رؤوس HTTP

افتراضيًا، لا تُمرَّر رؤوس HTTP من الطلبات الواردة إلى وظيفتك المنطقية لأسباب أمنية. للوصول إلى رؤوس محددة، قم بإدراجها صراحةً في مصفوفة forwardedRequestHeaders:
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'],
    },
  ],
});
في المعالج الخاص بك، يمكنك حينها الوصول إلى هذه الرؤوس:
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']).
يمكنك إنشاء وظائف جديدة بطريقتين:
  • Scaffolded: Run yarn twenty entity:add and choose the option to add a new logic function. يُولّد هذا ملفًا مبدئيًا مع معالج وتكوين.
  • يدوي: أنشئ ملفًا جديدًا *.logic-function.ts واستخدم defineLogicFunction() مع اتباع النمط نفسه.

المكوّنات الأمامية

تتيح لك المكوّنات الأمامية إنشاء مكوّنات React مخصّصة تُعرَض داخل واجهة مستخدم Twenty. استخدم defineFrontComponent() لتعريف مكوّنات مع تحقّق مدمج:
// src/my-widget.front-component.tsx
import { defineFrontComponent } from 'twenty-sdk';

const MyWidget = () => {
  return (
    <div style={{ padding: '20px', fontFamily: 'sans-serif' }}>
      <h1>My Custom Widget</h1>
      <p>This is a custom front component for Twenty.</p>
    </div>
  );
};

export default defineFrontComponent({
  universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
  name: 'my-widget',
  description: 'A custom widget component',
  component: MyWidget,
});
النقاط الرئيسية:
  • المكوّنات الأمامية هي مكوّنات React تُعرَض ضمن سياقات معزولة داخل Twenty.
  • استخدم لاحقة الملف *.front-component.tsx للاكتشاف التلقائي.
  • يشير الحقل component إلى مكوّن React الخاص بك.
  • Components are built and synced automatically during yarn twenty app:dev.
يمكنك إنشاء مكوّنات أمامية جديدة بطريقتين:
  • Scaffolded: Run yarn twenty entity:add and choose the option to add a new front component.
  • يدوي: أنشئ ملفًا جديدًا *.front-component.tsx واستخدم defineFrontComponent().

عميل مُولَّد مضبوط الأنواع

Run yarn twenty app:generate to create a local typed client in generated/ based on your workspace schema. استخدمه في وظائفك:
import Twenty from '~/generated';

const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
The client is re-generated by yarn twenty app:generate. أعِد التشغيل بعد تغيير كائناتك أو عند الانضمام إلى مساحة عمل جديدة.

بيانات الاعتماد وقت التشغيل في الوظائف المنطقية

عندما تعمل وظيفتك على Twenty، يقوم النظام الأساسي بحقن بيانات الاعتماد كمتغيرات بيئة قبل تنفيذ كودك:
  • TWENTY_API_URL: عنوان URL الأساسي لواجهة Twenty البرمجية التي يستهدفها تطبيقك.
  • TWENTY_API_KEY: مفتاح قصير العمر ذو نطاق يقتصر على الدور الافتراضي لوظيفة تطبيقك.
الملاحظات:
  • لا تحتاج إلى تمرير عنوان URL أو مفتاح واجهة برمجة التطبيقات إلى العميل المُولَّد. يقوم بقراءة TWENTY_API_URL وTWENTY_API_KEY من process.env وقت التشغيل.
  • تُحدَّد أذونات مفتاح واجهة برمجة التطبيقات بواسطة الدور المشار إليه في application-config.ts عبر defaultRoleUniversalIdentifier. هذا هو الدور الافتراضي الذي تستخدمه الوظائف المنطقية في تطبيقك.
  • يمكن للتطبيقات تعريف أدوار لاتباع مبدأ أقل الامتياز. امنح فقط الأذونات التي تحتاجها وظائفك، ثم وجّه defaultRoleUniversalIdentifier إلى المعرّف الشامل لذلك الدور.

مثال Hello World

استكشف مثالًا بسيطًا شاملًا من البداية إلى النهاية يوضح الكائنات والوظائف المنطقية والمكوّنات الأمامية ومشغّلات متعددة هنا:

إعداد يدوي (بدون المهيئ)

بينما نوصي باستخدام create-twenty-app للحصول على أفضل تجربة للبدء، يمكنك أيضًا إعداد مشروع يدويًا. لا تثبّت CLI عالميًا. Instead, add twenty-sdk as a local dependency and wire a single script in your package.json:
yarn add -D twenty-sdk
Then add a twenty script:
{
  "scripts": {
    "twenty": "twenty"
  }
}
Now you can run all commands via yarn twenty <command>, e.g. yarn twenty app:dev, yarn twenty app:generate, yarn twenty help, etc.

استكشاف الأخطاء وإصلاحها

  • Authentication errors: run yarn twenty auth:login and ensure your API key has the required permissions.
  • يتعذّر الاتصال بالخادم: تحقق من عنوان URL لواجهة البرمجة وأن خادم Twenty قابل للوصول.
  • Types or client missing/outdated: run yarn twenty app:generate.
  • Dev mode not syncing: ensure yarn twenty app:dev is running and that changes are not ignored by your environment.
قناة المساعدة على Discord: https://discord.com/channels/1130383047699738754/1130386664812982322