i18n - docs translations (#17499)

Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
This commit is contained in:
github-actions[bot]
2026-01-27 23:33:44 +01:00
committed by GitHub
parent 2ffe2d8aa6
commit 59d123d2b1
13 changed files with 761 additions and 1424 deletions
@@ -50,15 +50,12 @@ yarn app:dev
```bash filename="Terminal"
# Add a new entity to your application (guided)
yarn app:create-entity
yarn entity:add
# Generate a typed Twenty client and workspace entity types
yarn app:generate
# Run a onetime sync (instead of watch mode)
yarn app:sync
# Watch your application's functions logs
# Watch your application's function logs
yarn function:logs
# Execute a function by name
@@ -68,7 +65,7 @@ yarn function:execute -n my-function -p '{"name": "test"}'
yarn app:uninstall
# Display commands' help
yarn app:help
yarn help
```
راجع أيضًا: صفحات مرجع CLI لـ [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) و[twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -97,22 +94,23 @@ my-twenty-app/
tsconfig.json
README.md
src/
app/
application.config.ts # مطلوب - التكوين الرئيسي للتطبيق
default-function.role.ts # الدور الافتراضي للوظائف بدون خادم
// الكيانات الخاصة بك (*.object.ts, *.function.ts, *.role.ts)
utils/ # اختياري - تنفيذات المُعالِجات والأدوات المساعدة
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
hello-world.function.ts # Example serverless function
hello-world.front-component.tsx # Example front component
// your entities (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
```
### الاتفاقية فوق التهيئة
تستخدم التطبيقات نهج **الاتفاقية فوق التهيئة** حيث تُكتشف الكيانات عبر لاحقة اسم الملف. يتيح ذلك تنظيمًا مرنًا داخل مجلد `src/app/`:
| لاحقة الملف | نوع الكيان |
| --------------- | ---------------------- |
| `*.object.ts` | تعريفات كائنات مخصصة |
| `*.function.ts` | تعريفات وظائف بلا خادم |
| `*.role.ts` | تعريفات الأدوار |
| لاحقة الملف | نوع الكيان |
| ----------------------- | --------------------------- |
| `*.object.ts` | تعريفات كائنات مخصصة |
| `*.function.ts` | تعريفات وظائف بلا خادم |
| `*.front-component.tsx` | Front component definitions |
| `*.role.ts` | تعريفات الأدوار |
### طرق تنظيم المجلدات المدعومة
@@ -121,12 +119,14 @@ my-twenty-app/
**تقليدي (حسب النوع):**
```text
src/app/
src/
├── application.config.ts
├── objects/
│ └── postCard.object.ts
├── functions/
│ └── createPostCard.function.ts
├── components/
│ └── card.front-component.tsx
└── roles/
└── admin.role.ts
```
@@ -134,44 +134,45 @@ src/app/
**حسب الميزة:**
```text
src/app/
src/
├── application.config.ts
└── post-card/
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── postCardAdmin.role.ts
```
**مسطح:**
```text
src/app/
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.ts
```
بشكل عام:
* **package.json**: يصرّح باسم التطبيق والإصدار والمحرّكات (Node 24+، Yarn 4)، ويضيف `twenty-sdk` فضلًا عن نصوص مثل `dev` و`sync` و`generate` و`create-entity` و`logs` و`uninstall` و`auth` التي تفوِّض إلى `twenty` CLI المحلي.
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **.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 قصير في جذر التطبيق يتضمن تعليمات أساسية.
* **src/app/**: المكان الرئيسي حيث تعرّف تطبيقك ككود:
* **src/**: The main place where you define your application-as-code:
* `application.config.ts`: التكوين العام لتطبيقك (بيانات وصفية وربط وقت التشغيل). انظر "تكوين التطبيق" أدناه.
* `*.role.ts`: تعريفات الأدوار المستخدمة بواسطة وظائفك بلا خادم. انظر "الدور الافتراضي للوظيفة" أدناه.
* `*.object.ts`: تعريفات كائنات مخصصة.
* `*.function.ts`: تعريفات وظائف بلا خادم.
* **src/utils/**: مجلد اختياري لتنفيذات المعالجات والأدوات المساعدة.
* `*.front-component.tsx`: Front component definitions.
ستضيف الأوامر اللاحقة مزيدًا من الملفات والمجلدات:
* `yarn app:generate` سيُنشئ مجلدًا `generated/` (عميل Twenty مضبوط الأنواع + أنواع مساحة العمل).
* `yarn app:create-entity` سيضيف ملفات تعريف الكيانات تحت `src/app/` لكائناتك المخصصة أو الوظائف أو الأدوار.
l
* `yarn entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
## المصادقة
@@ -302,63 +303,12 @@ export default defineObject({
* `universalIdentifier` يجب أن يكون فريدًا وثابتًا عبر عمليات النشر.
* يتطلب كل حقل `name` و`type` و`label` ومعرّف `universalIdentifier` ثابتًا خاصًا به.
* المصفوفة `fields` اختيارية — يمكنك تعريف كائنات بدون حقول مخصصة.
* يمكنك إنشاء كائنات جديدة باستخدام `yarn app:create-entity`، والذي يرشدك خلال التسمية والحقول والعلاقات.
* You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
<Note>
**يتم إنشاء الحقول الأساسية تلقائيًا.** عند تعريف كائن مخصص، يضيف Twenty تلقائيًا حقولًا قياسية مثل `name` و`createdAt` و`updatedAt` و`createdBy` و`position` و`deletedAt`. لا تحتاج إلى تعريف هذه في مصفوفة `fields` — أضف فقط حقولك المخصصة.
</Note>
<Accordion title="بديل: صياغة قائمة على المزيّنات">
يمكنك أيضًا تعريف كائنات باستخدام مزيّنات TypeScript. يستخدم هذا النهج صياغة معتمدة على الأصناف مع مزيّنات `@Object` و`@Field` و`@Relation`:
```typescript
import {
type AddressField,
Field,
FieldType,
type FullNameField,
Object,
OnDeleteAction,
Relation,
RelationType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
import { type Note } from '../../generated';
@Object({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post card',
labelPlural: 'Post cards',
description: 'A post card object',
icon: 'IconMail',
})
export class PostCard {
@Field({
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
})
content: string;
@Relation({
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
type: RelationType.ONE_TO_MANY,
label: 'Notes',
icon: 'IconComment',
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
onDelete: OnDeleteAction.CASCADE,
})
notes: Note[];
}
```
ملاحظة: يتطلب نهج المزيّنات `experimentalDecorators` في تهيئة TypeScript لديك.
</Accordion>
### تكوين التطبيق (application.config.ts)
كل تطبيق لديه ملف واحد `application.config.ts` يصف:
@@ -469,14 +419,9 @@ export default defineRole({
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '../../generated';
import Twenty, { type Person } from '~/generated';
const handler = async (
params:
| RoutePayload
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
| CronPayload,
) => {
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'
@@ -507,18 +452,18 @@ export default defineFunction({
isAuthRequired: false,
},
// Cron trigger (CRON pattern)
{
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
type: 'cron',
pattern: '0 0 1 1 *',
},
// {
// 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'],
},
// {
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
// type: 'databaseEvent',
// eventName: 'person.updated',
// updatedFields: ['name'],
// },
],
});
```
@@ -633,7 +578,7 @@ const handler = async (event: RoutePayload) => {
يمكنك إنشاء وظائف جديدة بطريقتين:
* **مُنشأ بالقالب**: شغّل `yarn app:create-entity` واختر خيار إضافة وظيفة جديدة. يُولّد هذا ملفًا مبدئيًا مع معالج وتكوين.
* **Scaffolded**: Run `yarn entity:add` and choose the option to add a new function. يُولّد هذا ملفًا مبدئيًا مع معالج وتكوين.
* **يدوي**: أنشئ ملفًا جديدًا `*.function.ts` واستخدم `defineFunction()` مع اتباع النمط نفسه.
### عميل مُولَّد مضبوط الأنواع
@@ -641,13 +586,13 @@ const handler = async (event: RoutePayload) => {
شغّل yarn app:generate لإنشاء عميل محلي مضبوط الأنواع في generated/ استنادًا إلى مخطط مساحة العمل لديك. استخدمه في وظائفك:
```typescript
import Twenty from './generated';
import Twenty from '~/generated';
const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
```
يُعاد توليد العميل بواسطة `yarn app:generate`. أعِد تشغيله بعد تغيير كائناتك وتشغيل `yarn app:sync` أو عند الانضمام إلى مساحة عمل جديدة.
يُعاد توليد العميل بواسطة `yarn app:generate`. Re-run after changing your objects or when onboarding to a new workspace.
#### بيانات الاعتماد في وقت التشغيل في الوظائف بلا خادم
@@ -679,25 +624,29 @@ yarn add -D twenty-sdk
```json filename="package.json"
{
"scripts": {
"auth": "twenty auth login",
"generate": "twenty app generate",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
}
}
```
يمكنك الآن تشغيل الأوامر نفسها عبر Yarn، مثل `yarn app:dev` و`yarn app:sync`، إلخ.
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
## استكشاف الأخطاء وإصلاحها
* أخطاء المصادقة: شغّل `yarn auth:login` وتأكد من أن مفتاح واجهة برمجة التطبيقات لديك يمتلك الأذونات المطلوبة.
* يتعذّر الاتصال بالخادم: تحقق من عنوان URL لواجهة البرمجة وأن خادم Twenty قابل للوصول.
* الأنواع أو العميل مفقود/قديم: شغّل `yarn app:generate` ثم `yarn app:dev`.
* Types or client missing/outdated: run `yarn app:generate`.
* وضع التطوير لا يزامن: تأكد من أن `yarn app:dev` قيد التشغيل وأن التغييرات ليست متجاهلة من بيئتك.
قناة المساعدة على Discord: https://discord.com/channels/1130383047699738754/1130386664812982322
@@ -50,15 +50,12 @@ Odtud můžete:
```bash filename="Terminal"
# Add a new entity to your application (guided)
yarn app:create-entity
yarn entity:add
# Generate a typed Twenty client and workspace entity types
yarn app:generate
# Run a onetime sync (instead of watch mode)
yarn app:sync
# Watch your application's functions logs
# Watch your application's function logs
yarn function:logs
# Execute a function by name
@@ -68,7 +65,7 @@ yarn function:execute -n my-function -p '{"name": "test"}'
yarn app:uninstall
# Display commands' help
yarn app:help
yarn help
```
Viz také: referenční stránky CLI pro [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) a [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -97,22 +94,23 @@ my-twenty-app/
tsconfig.json
README.md
src/
app/
application.config.ts # Povinné - hlavní konfigurace aplikace
default-function.role.ts # Výchozí role pro serverless funkce
// vaše entity (*.object.ts, *.function.ts, *.role.ts)
utils/ # Volitelné - implementace handlerů a nástroje
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
hello-world.function.ts # Example serverless function
hello-world.front-component.tsx # Example front component
// your entities (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
```
### Konvence před konfigurací
Aplikace používají přístup **konvence před konfigurací**, kde jsou entity detekovány podle přípony souboru. To umožňuje flexibilní organizaci ve složce `src/app/`:
| Přípona souboru | Typ entity |
| --------------- | -------------------------- |
| `*.object.ts` | Definice vlastních objektů |
| `*.function.ts` | Definice serverless funkcí |
| `*.role.ts` | Definice rolí |
| Přípona souboru | Typ entity |
| ----------------------- | --------------------------- |
| `*.object.ts` | Definice vlastních objektů |
| `*.function.ts` | Definice serverless funkcí |
| `*.front-component.tsx` | Front component definitions |
| `*.role.ts` | Definice rolí |
### Podporované uspořádání složek
@@ -121,12 +119,14 @@ Entity můžete uspořádat podle některého z těchto vzorů:
**Tradiční (podle typu):**
```text
src/app/
src/
├── application.config.ts
├── objects/
│ └── postCard.object.ts
├── functions/
│ └── createPostCard.function.ts
├── components/
│ └── card.front-component.tsx
└── roles/
└── admin.role.ts
```
@@ -134,44 +134,45 @@ src/app/
**Podle funkcí:**
```text
src/app/
src/
├── application.config.ts
└── post-card/
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── postCardAdmin.role.ts
```
**Plochá:**
```text
src/app/
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.ts
```
V kostce:
* **package.json**: Deklaruje název aplikace, verzi, engines (Node 24+, Yarn 4) a přidává `twenty-sdk` plus skripty jako `dev`, `sync`, `generate`, `create-entity`, `logs`, `uninstall` a `auth`, které delegují na lokální `twenty` CLI.
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **.gitignore**: Ignoruje běžné artefakty jako `node_modules`, `.yarn`, `generated/` (typovaný klient), `dist/`, `build/`, složky s coverage, logy a soubory `.env*`.
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Zamykají a konfigurují nástrojový řetězec Yarn 4 používaný projektem.
* **.nvmrc**: Fixuje verzi Node.js požadovanou projektem.
* **eslint.config.mjs** a **tsconfig.json**: Poskytují lintování a konfiguraci TypeScriptu pro zdrojové soubory vaší aplikace v TypeScriptu.
* **README.md**: Krátké README v kořeni aplikace se základními pokyny.
* **src/app/**: Hlavní místo, kde definujete svou aplikaci jako kód:
* **src/**: The main place where you define your application-as-code:
* `application.config.ts`: Globální konfigurace vaší aplikace (metadata a napojení za běhu). Viz „Konfigurace aplikace“ níže.
* `*.role.ts`: Definice rolí používané vašimi serverless funkcemi. Viz „Výchozí role funkce“ níže.
* `*.object.ts`: Definice vlastních objektů.
* `*.function.ts`: Definice serverless funkcí.
* **src/utils/**: Volitelná složka pro implementace obslužných funkcí a pomocné nástroje.
* `*.front-component.tsx`: Front component definitions.
Pozdější příkazy přidají další soubory a složky:
* `yarn app:generate` vytvoří složku `generated/` (typovaný klient Twenty + typy pracovního prostoru).
* `yarn app:create-entity` přidá soubory s definicemi entit do `src/app/` pro vaše vlastní objekty, funkce nebo role.
l
* `yarn entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
## Ověření
@@ -302,63 +303,12 @@ Hlavní body:
* Hodnota `universalIdentifier` musí být jedinečná a stabilní napříč nasazeními.
* Každé pole vyžaduje `name`, `type`, `label` a svůj vlastní stabilní `universalIdentifier`.
* Pole `fields` je volitelné — objekty můžete definovat i bez vlastních polí.
* Nové objekty můžete vygenerovat pomocí `yarn app:create-entity`, který vás provede pojmenováním, poli a vztahy.
* You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
<Note>
**Základní pole jsou vytvořena automaticky.** Když definujete vlastní objekt, Twenty automaticky přidá standardní pole jako `name`, `createdAt`, `updatedAt`, `createdBy`, `position` a `deletedAt`. Nemusíte je definovat v poli `fields` — přidejte pouze svá vlastní pole.
</Note>
<Accordion title="Alternativa: Syntaxe založená na dekorátorech">
Objekty můžete definovat také pomocí dekorátorů TypeScriptu. Tento přístup používá třídovou syntaxi s dekorátory `@Object`, `@Field` a `@Relation`:
```typescript
import {
type AddressField,
Field,
FieldType,
type FullNameField,
Object,
OnDeleteAction,
Relation,
RelationType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
import { type Note } from '../../generated';
@Object({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post card',
labelPlural: 'Post cards',
description: 'A post card object',
icon: 'IconMail',
})
export class PostCard {
@Field({
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
})
content: string;
@Relation({
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
type: RelationType.ONE_TO_MANY,
label: 'Notes',
icon: 'IconComment',
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
onDelete: OnDeleteAction.CASCADE,
})
notes: Note[];
}
```
Poznámka: Přístup s dekorátory vyžaduje `experimentalDecorators` v konfiguraci TypeScriptu.
</Accordion>
### Konfigurace aplikace (application.config.ts)
Každá aplikace má jeden soubor `application.config.ts`, který popisuje:
@@ -469,14 +419,9 @@ Každý soubor funkce používá `defineFunction()` k exportu konfigurace s obsl
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '../../generated';
import Twenty, { type Person } from '~/generated';
const handler = async (
params:
| RoutePayload
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
| CronPayload,
) => {
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'
@@ -507,18 +452,18 @@ export default defineFunction({
isAuthRequired: false,
},
// Cron trigger (CRON pattern)
{
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
type: 'cron',
pattern: '0 0 1 1 *',
},
// {
// 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'],
},
// {
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
// type: 'databaseEvent',
// eventName: 'person.updated',
// updatedFields: ['name'],
// },
],
});
```
@@ -633,7 +578,7 @@ const handler = async (event: RoutePayload) => {
Nové funkce můžete vytvářet dvěma způsoby:
* **Vygenerované**: Spusťte `yarn app:create-entity` a zvolte možnost přidat novou funkci. Tím se vygeneruje startovací soubor s obslužnou funkcí a konfigurací.
* **Scaffolded**: Run `yarn entity:add` and choose the option to add a new function. Tím se vygeneruje startovací soubor s obslužnou funkcí a konfigurací.
* **Ruční**: Vytvořte nový soubor `*.function.ts` a použijte `defineFunction()` podle stejného vzoru.
### Generovaný typovaný klient
@@ -641,13 +586,13 @@ Nové funkce můžete vytvářet dvěma způsoby:
Spusťte yarn app:generate a vytvořte lokálního typovaného klienta v generated/ na základě schématu vašeho pracovního prostoru. Použijte jej ve svých funkcích:
```typescript
import Twenty from './generated';
import Twenty from '~/generated';
const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
```
Klient je znovu generován příkazem `yarn app:generate`. Spusťte jej znovu po změně objektů a po `yarn app:sync`, případně při připojení k novému pracovnímu prostoru.
Klient je znovu generován příkazem `yarn app:generate`. Re-run after changing your objects or when onboarding to a new workspace.
#### Běhové přihlašovací údaje v serverless funkcích
@@ -679,25 +624,29 @@ Poté přidejte skripty jako tyto:
```json filename="package.json"
{
"scripts": {
"auth": "twenty auth login",
"generate": "twenty app generate",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
}
}
```
Nyní můžete spouštět stejné příkazy přes Yarn, např. `yarn app:dev`, `yarn app:sync` atd.
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
## Řešení potíží
* Chyby ověření: spusťte `yarn auth:login` a ujistěte se, že váš klíč API má požadovaná oprávnění.
* Nelze se připojit k serveru: ověřte URL API a že je server Twenty dosažitelný.
* Typy nebo klient chybí/jsou zastaralé: spusťte `yarn app:generate` a poté `yarn app:dev`.
* Types or client missing/outdated: run `yarn app:generate`.
* Režim vývoje nesynchronizuje: ujistěte se, že běží `yarn app:dev` a že vaše prostředí změny neignoruje.
Kanál podpory na Discordu: https://discord.com/channels/1130383047699738754/1130386664812982322
@@ -50,15 +50,12 @@ Von hier aus können Sie:
```bash filename="Terminal"
# Add a new entity to your application (guided)
yarn app:create-entity
yarn entity:add
# Generate a typed Twenty client and workspace entity types
yarn app:generate
# Run a onetime sync (instead of watch mode)
yarn app:sync
# Watch your application's functions logs
# Watch your application's function logs
yarn function:logs
# Execute a function by name
@@ -68,7 +65,7 @@ yarn function:execute -n my-function -p '{"name": "test"}'
yarn app:uninstall
# Display commands' help
yarn app:help
yarn 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).
@@ -97,22 +94,23 @@ my-twenty-app/
tsconfig.json
README.md
src/
app/
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
// your entities (*.object.ts, *.function.ts, *.role.ts)
utils/ # Optional - handler implementations & utilities
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
hello-world.function.ts # Example serverless function
hello-world.front-component.tsx # Example front component
// your entities (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
```
### Konvention vor Konfiguration
Anwendungen verwenden einen Ansatz **Konvention vor Konfiguration**, bei dem Entitäten anhand ihrer Dateiendung erkannt werden. Dies ermöglicht eine flexible Organisation im Ordner `src/app/`:
| Dateiendung | Entitätstyp |
| --------------- | ------------------------------------- |
| `*.object.ts` | Benutzerdefinierte Objektdefinitionen |
| `*.function.ts` | Definitionen serverloser Funktionen |
| `*.role.ts` | Rollendefinitionen |
| Dateiendung | Entitätstyp |
| ----------------------- | ------------------------------------- |
| `*.object.ts` | Benutzerdefinierte Objektdefinitionen |
| `*.function.ts` | Definitionen serverloser Funktionen |
| `*.front-component.tsx` | Front component definitions |
| `*.role.ts` | Rollendefinitionen |
### Unterstützte Ordnerorganisationen
@@ -121,12 +119,14 @@ Sie können Ihre Entitäten nach einem der folgenden Muster organisieren:
**Traditionell (nach Typ):**
```text
src/app/
src/
├── application.config.ts
├── objects/
│ └── postCard.object.ts
├── functions/
│ └── createPostCard.function.ts
├── components/
│ └── card.front-component.tsx
└── roles/
└── admin.role.ts
```
@@ -134,44 +134,45 @@ src/app/
**Feature-basiert:**
```text
src/app/
src/
├── application.config.ts
└── post-card/
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── postCardAdmin.role.ts
```
**Flach:**
```text
src/app/
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.ts
```
Auf hoher Ebene:
* **package.json**: Deklariert App-Name, Version, Engines (Node 24+, Yarn 4) und fügt `twenty-sdk` sowie Skripte wie `dev`, `sync`, `generate`, `create-entity`, `logs`, `uninstall` und `auth` hinzu, die an die lokale `twenty`-CLI delegieren.
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **.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.
* **eslint.config.mjs** 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.
* **src/app/**: Der Hauptort, an dem Sie Ihre Anwendung als Code definieren:
* **src/**: The main place where you define your application-as-code:
* `application.config.ts`: Globale Konfiguration für Ihre App (Metadaten und Laufzeit-Anbindung). Siehe unten „Anwendungskonfiguration“.
* `*.role.ts`: Rollendefinitionen, die von Ihren serverlosen Funktionen verwendet werden. Siehe unten „Standard-Funktionsrolle“.
* `*.object.ts`: Benutzerdefinierte Objektdefinitionen.
* `*.function.ts`: Definitionen serverloser Funktionen.
* **src/utils/**: Optionaler Ordner für Handler-Implementierungen und Utilities.
* `*.front-component.tsx`: Front component definitions.
Spätere Befehle fügen weitere Dateien und Ordner hinzu:
* `yarn app:generate` erstellt einen `generated/`-Ordner (typisierter Twenty-Client + Workspace-Typen).
* `yarn app:create-entity` fügt unter `src/app/` Entitätsdefinitionsdateien für Ihre benutzerdefinierten Objekte, Funktionen oder Rollen hinzu.
l
* `yarn entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
## Authentifizierung
@@ -302,63 +303,12 @@ Hauptpunkte:
* 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 app:create-entity` neue Objekte erzeugen; der Assistent führt Sie durch Benennung, Felder und Beziehungen.
* You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
<Note>
**Basisfelder werden automatisch erstellt.** Wenn Sie ein benutzerdefiniertes Objekt definieren, fügt Twenty automatisch Standardfelder wie `name`, `createdAt`, `updatedAt`, `createdBy`, `position` und `deletedAt` hinzu. Sie müssen diese nicht in Ihrem `fields`-Array definieren — fügen Sie nur Ihre benutzerdefinierten Felder hinzu.
</Note>
<Accordion title="Alternative: Dekoratorbasierte Syntax">
Sie können Objekte auch mit TypeScript-Dekoratoren definieren. Dieser Ansatz verwendet klassenbasierte Syntax mit den Dekoratoren `@Object`, `@Field` und `@Relation`:
```typescript
import {
type AddressField,
Field,
FieldType,
type FullNameField,
Object,
OnDeleteAction,
Relation,
RelationType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
import { type Note } from '../../generated';
@Object({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post card',
labelPlural: 'Post cards',
description: 'A post card object',
icon: 'IconMail',
})
export class PostCard {
@Field({
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
})
content: string;
@Relation({
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
type: RelationType.ONE_TO_MANY,
label: 'Notes',
icon: 'IconComment',
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
onDelete: OnDeleteAction.CASCADE,
})
notes: Note[];
}
```
Hinweis: Der Dekorator-Ansatz erfordert `experimentalDecorators` in Ihrer TypeScript-Konfiguration.
</Accordion>
### Anwendungskonfiguration (application.config.ts)
Jede App hat eine einzelne Datei `application.config.ts`, die Folgendes beschreibt:
@@ -469,14 +419,9 @@ Jede Funktionsdatei verwendet `defineFunction()`, um eine Konfiguration mit eine
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '../../generated';
import Twenty, { type Person } from '~/generated';
const handler = async (
params:
| RoutePayload
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
| CronPayload,
) => {
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'
@@ -507,18 +452,18 @@ export default defineFunction({
isAuthRequired: false,
},
// Cron trigger (CRON pattern)
{
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
type: 'cron',
pattern: '0 0 1 1 *',
},
// {
// 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'],
},
// {
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
// type: 'databaseEvent',
// eventName: 'person.updated',
// updatedFields: ['name'],
// },
],
});
```
@@ -633,7 +578,7 @@ const handler = async (event: RoutePayload) => {
Sie können neue Funktionen auf zwei Arten erstellen:
* **Generiert**: Führen Sie `yarn app:create-entity` aus und wählen Sie die Option zum Hinzufügen einer neuen Funktion. Dadurch wird eine Starterdatei mit Handler und Konfiguration erzeugt.
* **Scaffolded**: Run `yarn entity:add` and choose the option to add a new function. Dadurch wird eine Starterdatei mit Handler und Konfiguration erzeugt.
* **Manuell**: Erstellen Sie eine neue `*.function.ts`-Datei und verwenden Sie `defineFunction()` nach demselben Muster.
### Generierter typisierter Client
@@ -641,13 +586,13 @@ Sie können neue Funktionen auf zwei Arten erstellen:
Führen Sie yarn app:generate aus, um einen lokalen typisierten Client in generated/ basierend auf Ihrem Workspace-Schema zu erstellen. Verwenden Sie ihn in Ihren Funktionen:
```typescript
import Twenty from './generated';
import Twenty from '~/generated';
const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
```
Der Client wird durch `yarn app:generate` erneut generiert. Führen Sie ihn nach Änderungen an Ihren Objekten und nach `yarn app:sync` bzw. beim Onboarding in einen neuen Workspace erneut aus.
Der Client wird durch `yarn app:generate` erneut generiert. Re-run after changing your objects or when onboarding to a new workspace.
#### Laufzeit-Anmeldedaten in serverlosen Funktionen
@@ -679,25 +624,29 @@ Fügen Sie dann Skripte wie diese hinzu:
```json filename="package.json"
{
"scripts": {
"auth": "twenty auth login",
"generate": "twenty app generate",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
}
}
```
Jetzt können Sie dieselben Befehle über Yarn ausführen, z. B. `yarn app:dev`, `yarn app:sync` usw.
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
## Fehlerbehebung
* Authentifizierungsfehler: Führen Sie `yarn 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: Führen Sie `yarn app:generate` und anschließend `yarn app:dev` aus.
* Types or client missing/outdated: run `yarn app:generate`.
* Dev-Modus synchronisiert nicht: Stellen Sie sicher, dass `yarn app:dev` läuft und dass Änderungen von Ihrer Umgebung nicht ignoriert werden.
Discord-Hilfekanal: https://discord.com/channels/1130383047699738754/1130386664812982322
@@ -49,26 +49,23 @@ yarn app:dev
Desde aquí usted puede:
```bash filename="Terminal"
# Add a new entity to your application (guided)
yarn app:create-entity
# Añade una nueva entidad a tu aplicación (guiado)
yarn entity:add
# Generate a typed Twenty client and workspace entity types
# Genera un cliente tipado de Twenty y tipos de entidad del espacio de trabajo
yarn app:generate
# Run a onetime sync (instead of watch mode)
yarn app:sync
# Watch your application's functions logs
# Supervisa los registros de funciones de tu aplicación
yarn function:logs
# Execute a function by name
yarn function:execute -n my-function -p '{"name": "test"}'
# Ejecuta una función por nombre
yarn function:execute -n my-function -p '{\"name\": \"test\"}'
# Uninstall the application from the current workspace
# Desinstala la aplicación del espacio de trabajo actual
yarn app:uninstall
# Display commands' help
yarn app:help
# Muestra la ayuda de los comandos
yarn help
```
Consulta también: las páginas de referencia de la CLI para [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) y [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -97,22 +94,23 @@ my-twenty-app/
tsconfig.json
README.md
src/
app/
application.config.ts # Obligatorio - configuración principal de la aplicación
default-function.role.ts # Rol predeterminado para las funciones sin servidor
// tus entidades (*.object.ts, *.function.ts, *.role.ts)
utils/ # Opcional - implementaciones de manejadores y utilidades
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
hello-world.function.ts # Example serverless function
hello-world.front-component.tsx # Example front component
// your entities (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
```
### Convención sobre configuración
Las aplicaciones usan un enfoque de **convención sobre configuración** en el que las entidades se detectan por su sufijo de archivo. Esto permite una organización flexible dentro de la carpeta `src/app/`:
| Sufijo de archivo | Tipo de entidad |
| ----------------- | -------------------------------------- |
| `*.object.ts` | Definiciones de objetos personalizados |
| `*.function.ts` | Definiciones de funciones sin servidor |
| `*.role.ts` | Definiciones de roles |
| Sufijo de archivo | Tipo de entidad |
| ----------------------- | --------------------------------------- |
| `*.object.ts` | Definiciones de objetos personalizados |
| `*.function.ts` | Definiciones de funciones sin servidor |
| `*.front-component.tsx` | Definiciones de componentes de interfaz |
| `*.role.ts` | Definiciones de roles |
### Organizaciones de carpetas compatibles
@@ -121,12 +119,14 @@ Puedes organizar tus entidades con cualquiera de estos patrones:
**Tradicional (por tipo):**
```text
src/app/
src/
├── application.config.ts
├── objects/
│ └── postCard.object.ts
├── functions/
│ └── createPostCard.function.ts
├── components/
│ └── card.front-component.tsx
└── roles/
└── admin.role.ts
```
@@ -134,44 +134,45 @@ src/app/
**Basado en funcionalidades:**
```text
src/app/
src/
├── application.config.ts
└── post-card/
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── postCardAdmin.role.ts
```
**Plano:**
```text
src/app/
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.ts
```
A grandes rasgos:
* **package.json**: Declara el nombre de la aplicación, la versión, los entornos (Node 24+, Yarn 4) y agrega `twenty-sdk` además de scripts como `dev`, `sync`, `generate`, `create-entity`, `logs`, `uninstall` y `auth` que delegan en la CLI local `twenty`.
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **.gitignore**: Ignora artefactos comunes como `node_modules`, `.yarn`, `generated/` (cliente tipado), `dist/`, `build/`, carpetas de cobertura, archivos de registro y archivos `.env*`.
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Bloquean y configuran la cadena de herramientas Yarn 4 utilizada por el proyecto.
* **.nvmrc**: Fija la versión de Node.js esperada por el proyecto.
* **eslint.config.mjs** y **tsconfig.json**: Proporcionan linting y configuración de TypeScript para las fuentes de TypeScript de tu aplicación.
* **README.md**: Un README breve en la raíz de la aplicación con instrucciones básicas.
* **src/app/**: El lugar principal donde defines tu aplicación como código:
* **src/**: The main place where you define your application-as-code:
* `application.config.ts`: Configuración global de tu aplicación (metadatos y vinculación en tiempo de ejecución). Consulta "Configuración de la aplicación" más abajo.
* `*.role.ts`: Definiciones de roles usadas por tus funciones sin servidor. Consulta "Rol de función predeterminado" más abajo.
* `*.object.ts`: Definiciones de objetos personalizados.
* `*.function.ts`: Definiciones de funciones sin servidor.
* **src/utils/**: Carpeta opcional para implementaciones de controladores y utilidades.
* `*.front-component.tsx`: Front component definitions.
Comandos posteriores añadirán más archivos y carpetas:
* `yarn app:generate` creará una carpeta `generated/` (cliente tipado de Twenty + tipos del espacio de trabajo).
* `yarn app:create-entity` añadirá archivos de definición de entidades en `src/app/` para tus objetos, funciones o roles personalizados.
l
* `yarn entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
## Autenticación
@@ -302,63 +303,12 @@ Puntos clave:
* El `universalIdentifier` debe ser único y estable entre implementaciones.
* Cada campo requiere `name`, `type`, `label` y su propio `universalIdentifier` estable.
* La matriz `fields` es opcional: puedes definir objetos sin campos personalizados.
* Puedes generar nuevos objetos usando `yarn app:create-entity`, que te guía por el nombrado, los campos y las relaciones.
* You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
<Note>
**Los campos base se crean automáticamente.** Cuando defines un objeto personalizado, Twenty añade automáticamente campos estándar como `name`, `createdAt`, `updatedAt`, `createdBy`, `position` y `deletedAt`. No necesitas definir estos en tu matriz `fields` — solo agrega tus campos personalizados.
</Note>
<Accordion title="Alternativa: sintaxis basada en decoradores">
También puedes definir objetos usando decoradores de TypeScript. Este enfoque usa sintaxis basada en clases con los decoradores `@Object`, `@Field` y `@Relation`:
```typescript
import {
type AddressField,
Field,
FieldType,
type FullNameField,
Object,
OnDeleteAction,
Relation,
RelationType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
import { type Note } from '../../generated';
@Object({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post card',
labelPlural: 'Post cards',
description: 'A post card object',
icon: 'IconMail',
})
export class PostCard {
@Field({
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
})
content: string;
@Relation({
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
type: RelationType.ONE_TO_MANY,
label: 'Notes',
icon: 'IconComment',
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
onDelete: OnDeleteAction.CASCADE,
})
notes: Note[];
}
```
Nota: El enfoque de decoradores requiere `experimentalDecorators` en tu configuración de TypeScript.
</Accordion>
### Configuración de la aplicación (application.config.ts)
Cada aplicación tiene un único archivo `application.config.ts` que describe:
@@ -469,14 +419,9 @@ Cada archivo de función usa `defineFunction()` para exportar una configuración
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '../../generated';
import Twenty, { type Person } from '~/generated';
const handler = async (
params:
| RoutePayload
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
| CronPayload,
) => {
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'
@@ -507,18 +452,18 @@ export default defineFunction({
isAuthRequired: false,
},
// Cron trigger (CRON pattern)
{
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
type: 'cron',
pattern: '0 0 1 1 *',
},
// {
// 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'],
},
// {
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
// type: 'databaseEvent',
// eventName: 'person.updated',
// updatedFields: ['name'],
// },
],
});
```
@@ -633,7 +578,7 @@ const handler = async (event: RoutePayload) => {
Puedes crear funciones nuevas de dos maneras:
* **Generado**: Ejecuta `yarn app:create-entity` y elige la opción para añadir una nueva funcn. Esto genera un archivo inicial con un controlador y configuración.
* **Scaffolded**: Run `yarn entity:add` and choose the option to add a new function. Esto genera un archivo inicial con un controlador y configuración.
* **Manual**: Crea un nuevo archivo `*.function.ts` y usa `defineFunction()`, siguiendo el mismo patrón.
### Cliente tipado generado
@@ -641,13 +586,13 @@ Puedes crear funciones nuevas de dos maneras:
Ejecuta yarn app:generate para crear un cliente tipado local en generated/ basado en el esquema de tu espacio de trabajo. Úsalo en tus funciones:
```typescript
import Twenty from './generated';
import Twenty from '~/generated';
const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
```
El cliente se vuelve a generar con `yarn app:generate`. Vuelve a ejecutarlo después de cambiar tus objetos y de hacer `yarn app:sync`, o al incorporarte a un nuevo espacio de trabajo.
El cliente se vuelve a generar con `yarn app:generate`. Re-run after changing your objects or when onboarding to a new workspace.
#### Credenciales en tiempo de ejecución en funciones sin servidor
@@ -679,25 +624,29 @@ Luego agrega scripts como estos:
```json filename="package.json"
{
"scripts": {
"auth": "twenty auth login",
"generate": "twenty app generate",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
}
}
```
Ahora puedes ejecutar los mismos comandos mediante Yarn, p. ej., `yarn app:dev`, `yarn app:sync`, etc.
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
## Solución de problemas
* Errores de autenticación: ejecuta `yarn auth:login` y asegúrate de que tu clave de API tenga los permisos necesarios.
* No se puede conectar al servidor: verifica la URL de la API y que el servidor de Twenty sea accesible.
* Tipos o cliente faltantes/obsoletos: ejecuta `yarn app:generate` y luego `yarn app:dev`.
* Types or client missing/outdated: run `yarn app:generate`.
* El modo de desarrollo no sincroniza: asegúrate de que `yarn app:dev` esté ejecutándose y de que los cambios no sean ignorados por tu entorno.
Canal de ayuda en Discord: https://discord.com/channels/1130383047699738754/1130386664812982322
@@ -49,26 +49,23 @@ yarn app:dev
À partir d'ici, vous pouvez :
```bash filename="Terminal"
# Add a new entity to your application (guided)
yarn app:create-entity
# Ajouter une nouvelle entité à votre application (assisté)
yarn entity:add
# Generate a typed Twenty client and workspace entity types
# Générer un client Twenty typé et les types d'entité de l'espace de travail
yarn app:generate
# Run a onetime sync (instead of watch mode)
yarn app:sync
# Watch your application's functions logs
# Surveiller les journaux des fonctions de votre application
yarn function:logs
# Execute a function by name
# Exécuter une fonction par nom
yarn function:execute -n my-function -p '{"name": "test"}'
# Uninstall the application from the current workspace
# Désinstaller l'application de l'espace de travail actuel
yarn app:uninstall
# Display commands' help
yarn app:help},{
# Afficher l'aide des commandes
yarn help
```
Voir aussi : les pages de référence CLI pour [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) et [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -97,22 +94,23 @@ my-twenty-app/
tsconfig.json
README.md
src/
app/
application.config.ts # Obligatoire - configuration principale de l'application
default-function.role.ts # Rôle par défaut pour les fonctions serverless
// vos entités (*.object.ts, *.function.ts, *.role.ts)
utils/ # Optionnel - implémentations de gestionnaires et utilitaires
application.config.ts # Obligatoire - configuration principale de l'application
default-function.role.ts # Rôle par défaut pour les fonctions serverless
hello-world.function.ts # Exemple de fonction serverless
hello-world.front-component.tsx # Exemple de composant frontal
// vos entités (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
```
### Convention plutôt que configuration
Les applications adoptent une approche **convention plutôt que configuration** où les entités sont détectées par leur suffixe de fichier. Cela permet une organisation flexible dans le dossier `src/app/` :
| Suffixe de fichier | Type dentité |
| ------------------ | ------------------------------------- |
| `*.object.ts` | Définitions dobjets personnalisés |
| `*.function.ts` | Définitions de fonctions sans serveur |
| `*.role.ts` | Définitions de rôles |
| Suffixe de fichier | Type dentité |
| ----------------------- | ------------------------------------- |
| `*.object.ts` | Définitions dobjets personnalisés |
| `*.function.ts` | Définitions de fonctions sans serveur |
| `*.front-component.tsx` | Définitions des composants frontaux |
| `*.role.ts` | Définitions de rôles |
### Structures de dossiers prises en charge
@@ -121,12 +119,14 @@ Vous pouvez organiser vos entités selon lun des schémas suivants :
**Traditionnelle (par type) :**
```text
src/app/
src/
├── application.config.ts
├── objects/
│ └── postCard.object.ts
├── functions/
│ └── createPostCard.function.ts
├── components/
│ └── card.front-component.tsx
└── roles/
└── admin.role.ts
```
@@ -134,44 +134,45 @@ src/app/
**Par fonctionnalité :**
```text
src/app/
src/
├── application.config.ts
└── post-card/
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── postCardAdmin.role.ts
```
**À plat :**
```text
src/app/
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.ts
```
Dans les grandes lignes :
* **package.json** : Déclare le nom de lapplication, la version, les moteurs (Node 24+, Yarn 4), et ajoute `twenty-sdk` ainsi que des scripts comme `dev`, `sync`, `generate`, `create-entity`, `logs`, `uninstall` et `auth` qui délèguent à la CLI locale `twenty`.
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **.gitignore** : Ignore les artefacts courants tels que `node_modules`, `.yarn`, `generated/` (client typé), `dist/`, `build/`, les dossiers de couverture, les fichiers journaux et les fichiers `.env*`.
* **yarn.lock**, **.yarnrc.yml**, **.yarn/** : Verrouillent et configurent la chaîne doutils Yarn 4 utilisée par le projet.
* **.nvmrc** : Fige la version de Node.js attendue par le projet.
* **eslint.config.mjs** et **tsconfig.json** : Fournissent la configuration de linting et TypeScript pour les sources TypeScript de votre application.
* **README.md** : Un bref README à la racine de lapplication avec des instructions de base.
* **src/app/** : Lendroit principal où vous définissez votre application sous forme de code :
* **src/**: The main place where you define your application-as-code:
* `application.config.ts` : Configuration globale de votre application (métadonnées et liaisons dexécution). Voir « Configuration de lapplication » ci-dessous.
* `*.role.ts` : Définitions de rôles utilisées par vos fonctions sans serveur. Voir « Rôle de fonction par défaut » ci-dessous.
* `*.object.ts` : Définitions dobjets personnalisés.
* `*.function.ts` : Définitions de fonctions sans serveur.
* **src/utils/** : Dossier facultatif pour les implémentations de gestionnaires et utilitaires.
* `*.front-component.tsx`: Front component definitions.
Des commandes ultérieures ajouteront dautres fichiers et dossiers :
* `yarn app:generate` créera un dossier `generated/` (client Twenty typé + types de lespace de travail).
* `yarn app:create-entity` ajoutera des fichiers de définition dentité sous `src/app/` pour vos objets, fonctions ou rôles personnalisés.
l
* `yarn entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
## Authentification
@@ -302,63 +303,12 @@ Points clés :
* Le `universalIdentifier` doit être unique et stable entre les déploiements.
* Chaque champ nécessite un `name`, un `type`, un `label` et son propre `universalIdentifier` stable.
* Le tableau `fields` est facultatif — vous pouvez définir des objets sans champs personnalisés.
* Vous pouvez générer de nouveaux objets avec `yarn app:create-entity`, qui vous guide à travers le nommage, les champs et les relations.
* You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
<Note>
**Les champs de base sont créés automatiquement.** Lorsque vous définissez un objet personnalisé, Twenty ajoute automatiquement des champs standard tels que `name`, `createdAt`, `updatedAt`, `createdBy`, `position` et `deletedAt`. Vous n'avez pas besoin de les définir dans votre tableau `fields` — ajoutez uniquement vos champs personnalisés.
</Note>
<Accordion title="Alternative : syntaxe basée sur des décorateurs">
Vous pouvez également définir des objets à laide de décorateurs TypeScript. Cette approche utilise une syntaxe basée sur les classes avec les décorateurs `@Object`, `@Field` et `@Relation` :
```typescript
import {
type AddressField,
Field,
FieldType,
type FullNameField,
Object,
OnDeleteAction,
Relation,
RelationType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
import { type Note } from '../../generated';
@Object({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post card',
labelPlural: 'Post cards',
description: 'A post card object',
icon: 'IconMail',
})
export class PostCard {
@Field({
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
})
content: string;
@Relation({
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
type: RelationType.ONE_TO_MANY,
label: 'Notes',
icon: 'IconComment',
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
onDelete: OnDeleteAction.CASCADE,
})
notes: Note[];
}
```
Remarque : lapproche avec décorateurs requiert `experimentalDecorators` dans votre configuration TypeScript.
</Accordion>
### Configuration de lapplication (application.config.ts)
Chaque application dispose dun seul fichier `application.config.ts` qui décrit :
@@ -469,14 +419,9 @@ Chaque fichier de fonction utilise `defineFunction()` pour exporter une configur
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '../../generated';
import Twenty, { type Person } from '~/generated';
const handler = async (
params:
| RoutePayload
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
| CronPayload,
) => {
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'
@@ -507,18 +452,18 @@ export default defineFunction({
isAuthRequired: false,
},
// Cron trigger (CRON pattern)
{
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
type: 'cron',
pattern: '0 0 1 1 *',
},
// {
// 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'],
},
// {
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
// type: 'databaseEvent',
// eventName: 'person.updated',
// updatedFields: ['name'],
// },
],
});
```
@@ -633,7 +578,7 @@ const handler = async (event: RoutePayload) => {
Vous pouvez créer de nouvelles fonctions de deux façons :
* **Générée** : Exécutez `yarn app:create-entity` et choisissez loption pour ajouter une nouvelle fonction. Cela génère un fichier de démarrage avec un gestionnaire et une configuration.
* **Scaffolded**: Run `yarn entity:add` and choose the option to add a new function. Cela génère un fichier de démarrage avec un gestionnaire et une configuration.
* **Manuelle** : Créez un nouveau fichier `*.function.ts` et utilisez `defineFunction()`, en suivant le même modèle.
### Client typé généré
@@ -641,13 +586,13 @@ Vous pouvez créer de nouvelles fonctions de deux façons :
Exécutez yarn app:generate pour créer un client typé local dans generated/ basé sur le schéma de votre espace de travail. Utilisez-le dans vos fonctions :
```typescript
import Twenty from './generated';
import Twenty from '~/generated';
const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
```
Le client est régénéré par `yarn app:generate`. Relancez la commande après avoir modifié vos objets et exécuté `yarn app:sync`, ou lors de lintégration à un nouvel espace de travail.
Le client est régénéré par `yarn app:generate`. Re-run after changing your objects or when onboarding to a new workspace.
#### Identifiants dexécution dans les fonctions sans serveur
@@ -679,25 +624,29 @@ Ajoutez ensuite des scripts comme ceux-ci :
```json filename="package.json"
{
"scripts": {
"auth": "twenty auth login",
"generate": "twenty app generate",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
}
}
```
Vous pouvez désormais exécuter les mêmes commandes via Yarn, par exemple `yarn app:dev`, `yarn app:sync`, etc.
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
## Résolution des problèmes
* Erreurs dauthentification : exécutez `yarn auth:login` et assurez-vous que votre clé API dispose des autorisations requises.
* Impossible de se connecter au serveur : vérifiez lURL de lAPI et que le serveur Twenty est accessible.
* Types ou client manquants/obsolètes : exécutez `yarn app:generate` puis `yarn app:dev`.
* Types or client missing/outdated: run `yarn app:generate`.
* Le mode dev ne se synchronise pas : assurez-vous que `yarn app:dev` est en cours dexécution et que les modifications ne sont pas ignorées par votre environnement.
Canal daide Discord : https://discord.com/channels/1130383047699738754/1130386664812982322
@@ -50,25 +50,22 @@ Da qui puoi:
```bash filename="Terminal"
# Add a new entity to your application (guided)
yarn app:create-entity
yarn entity:add
# Generate a typed Twenty client and workspace entity types
yarn app:generate
# Run a onetime sync (instead of watch mode)
yarn app:sync
# Watch your application's functions logs
# Watch your application's function logs
yarn function:logs
# Execute a function by name
yarn function:execute -n my-function -p '{\"name\": \"test\"}'
yarn function:execute -n my-function -p '{"name": "test"}'
# Uninstall the application from the current workspace
yarn app:uninstall
# Display commands' help
yarn app:help
yarn 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).
@@ -97,22 +94,23 @@ my-twenty-app/
tsconfig.json
README.md
src/
app/
application.config.ts # Obbligatorio - configurazione principale dell'applicazione
default-function.role.ts # Ruolo predefinito per le funzioni serverless
// le tue entità (*.object.ts, *.function.ts, *.role.ts)
utils/ # Opzionale - implementazioni degli handler e utility
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
hello-world.function.ts # Example serverless function
hello-world.front-component.tsx # Example front component
// your entities (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
```
### Convenzioni invece della configurazione
Le applicazioni usano un approccio basato sulle **convenzioni invece della configurazione** in cui le entità vengono rilevate in base al suffisso del file. Questo consente un'organizzazione flessibile all'interno della cartella `src/app/`:
| Suffisso del file | Tipo di entità |
| ----------------- | ------------------------------------- |
| `*.object.ts` | Definizioni di oggetti personalizzati |
| `*.function.ts` | Definizioni di funzioni serverless |
| `*.role.ts` | Definizioni di ruoli |
| Suffisso del file | Tipo di entità |
| ----------------------- | ------------------------------------- |
| `*.object.ts` | Definizioni di oggetti personalizzati |
| `*.function.ts` | Definizioni di funzioni serverless |
| `*.front-component.tsx` | Front component definitions |
| `*.role.ts` | Definizioni di ruoli |
### Organizzazioni di cartelle supportate
@@ -121,12 +119,14 @@ Puoi organizzare le tue entità in uno qualsiasi di questi modelli:
**Tradizionale (per tipo):**
```text
src/app/
src/
├── application.config.ts
├── objects/
│ └── postCard.object.ts
├── functions/
│ └── createPostCard.function.ts
├── components/
│ └── card.front-component.tsx
└── roles/
└── admin.role.ts
```
@@ -134,44 +134,45 @@ src/app/
**Per funzionalità:**
```text
src/app/
src/
├── application.config.ts
└── post-card/
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── postCardAdmin.role.ts
```
**Struttura piatta:**
```text
src/app/
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.ts
```
A livello generale:
* **package.json**: Dichiara il nome dell'app, la versione, i motori (Node 24+, Yarn 4) e aggiunge `twenty-sdk`, oltre a script come `dev`, `sync`, `generate`, `create-entity`, `logs`, `uninstall` e `auth` che delegano alla CLI locale `twenty`.
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **.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.
* **eslint.config.mjs** 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.
* **src/app/**: Il luogo principale in cui definisci la tua applicazione come codice:
* **src/**: The main place where you define your application-as-code:
* `application.config.ts`: Configurazione globale della tua app (metadati e collegamenti di runtime). Vedi "Configurazione dell'applicazione" qui sotto.
* `*.role.ts`: Definizioni di ruoli usate dalle tue funzioni serverless. Vedi "Ruolo funzione predefinito" qui sotto.
* `*.object.ts`: Definizioni di oggetti personalizzati.
* `*.function.ts`: Definizioni di funzioni serverless.
* **src/utils/**: Cartella opzionale per le implementazioni degli handler e le utility.
* `*.front-component.tsx`: Front component definitions.
Comandi successivi aggiungeranno altri file e cartelle:
* `yarn app:generate` creerà una cartella `generated/` (client Twenty tipizzato + tipi dello spazio di lavoro).
* `yarn app:create-entity` aggiungerà file di definizione delle entità sotto `src/app/` per i tuoi oggetti, funzioni o ruoli personalizzati.
l
* `yarn entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
## Autenticazione
@@ -302,63 +303,12 @@ Punti chiave:
* 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 app:create-entity`, che ti guida nella denominazione, nei campi e nelle relazioni.
* You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
<Note>
**I campi base vengono creati automaticamente.** Quando definisci un oggetto personalizzato, Twenty aggiunge automaticamente i campi standard come `name`, `createdAt`, `updatedAt`, `createdBy`, `position` e `deletedAt`. Non è necessario definirli nel tuo array `fields` — aggiungi solo i tuoi campi personalizzati.
</Note>
<Accordion title="Alternativa: sintassi basata sui decorator">
Puoi anche definire oggetti utilizzando i decorator di TypeScript. Questo approccio utilizza una sintassi basata sulle classi con i decorator `@Object`, `@Field` e `@Relation`:
```typescript
import {
type AddressField,
Field,
FieldType,
type FullNameField,
Object,
OnDeleteAction,
Relation,
RelationType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
import { type Note } from '../../generated';
@Object({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post card',
labelPlural: 'Post cards',
description: 'A post card object',
icon: 'IconMail',
})
export class PostCard {
@Field({
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
})
content: string;
@Relation({
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
type: RelationType.ONE_TO_MANY,
label: 'Notes',
icon: 'IconComment',
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
onDelete: OnDeleteAction.CASCADE,
})
notes: Note[];
}
```
Nota: L'approccio con i decorator richiede `experimentalDecorators` nella configurazione di TypeScript.
</Accordion>
### Configurazione dell'applicazione (application.config.ts)
Ogni app ha un singolo file `application.config.ts` che descrive:
@@ -469,14 +419,9 @@ Ogni file di funzione usa `defineFunction()` per esportare una configurazione co
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '../../generated';
import Twenty, { type Person } from '~/generated';
const handler = async (
params:
| RoutePayload
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
| CronPayload,
) => {
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'
@@ -507,18 +452,18 @@ export default defineFunction({
isAuthRequired: false,
},
// Cron trigger (CRON pattern)
{
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
type: 'cron',
pattern: '0 0 1 1 *',
},
// {
// 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'],
},
// {
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
// type: 'databaseEvent',
// eventName: 'person.updated',
// updatedFields: ['name'],
// },
],
});
```
@@ -633,7 +578,7 @@ const handler = async (event: RoutePayload) => {
Puoi creare nuove funzioni in due modi:
* **Generata dallo scaffolder**: Esegui `yarn app:create-entity` e scegli l'opzione per aggiungere una nuova funzione. Questo genera un file iniziale con un handler e una configurazione.
* **Scaffolded**: Run `yarn entity:add` and choose the option to add a new function. Questo genera un file iniziale con un handler e una configurazione.
* **Manuale**: Crea un nuovo file `*.function.ts` e usa `defineFunction()`, seguendo lo stesso schema.
### Client tipizzato generato
@@ -641,13 +586,13 @@ Puoi creare nuove funzioni in due modi:
Esegui yarn app:generate per creare un client tipizzato locale in generated/ basato sullo schema del tuo spazio di lavoro. Usalo nelle tue funzioni:
```typescript
import Twenty from './generated';
import Twenty from '~/generated';
const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
```
Il client viene rigenerato da `yarn app:generate`. Eseguilo nuovamente dopo aver modificato i tuoi oggetti e aver eseguito `yarn app:sync`, oppure quando effettui l'onboarding su un nuovo spazio di lavoro.
Il client viene rigenerato da `yarn app:generate`. Re-run after changing your objects or when onboarding to a new workspace.
#### Credenziali di runtime nelle funzioni serverless
@@ -679,25 +624,29 @@ Quindi aggiungi script come questi:
```json filename="package.json"
{
"scripts": {
"auth": "twenty auth login",
"generate": "twenty app generate",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
}
}
```
Ora puoi eseguire gli stessi comandi tramite Yarn, ad esempio `yarn app:dev`, `yarn app:sync`, ecc.
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
## Risoluzione dei problemi
* Errori di autenticazione: esegui `yarn 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: esegui `yarn app:generate` e poi `yarn app:dev`.
* Types or client missing/outdated: run `yarn app:generate`.
* Modalità di sviluppo non in sincronizzazione: assicurati che `yarn 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
@@ -49,26 +49,23 @@ yarn app:dev
そこで次のことができます:
```bash filename="Terminal"
# アプリケーションに新しいエンティティを追加(ガイド付き)
yarn app:create-entity
# Add a new entity to your application (guided)
yarn entity:add
# 型付きの Twenty クライアントとワークスペースのエンティティ型を生成
# Generate a typed Twenty client and workspace entity types
yarn app:generate
# 1回限りの同期を実行(ウォッチモードの代わり)
yarn app:sync
# アプリケーションの関数のログを監視
# Watch your application's function logs
yarn function:logs
# 名前で関数を実行
yarn function:execute -n my-function -p '{\"name\": \"test\"}'
# Execute a function by name
yarn function:execute -n my-function -p '{"name": "test"}'
# 現在のワークスペースからアプリケーションをアンインストール
# Uninstall the application from the current workspace
yarn app:uninstall
# コマンドのヘルプを表示
yarn app:help
# Display commands' help
yarn help
```
参考: [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) および [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk) の CLI リファレンスページをご覧ください。
@@ -97,22 +94,23 @@ my-twenty-app/
tsconfig.json
README.md
src/
app/
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
// your entities (*.object.ts, *.function.ts, *.role.ts)
utils/ # Optional - handler implementations & utilities
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
hello-world.function.ts # Example serverless function
hello-world.front-component.tsx # Example front component
// your entities (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
```
### コンベンション優先
アプリケーションは **コンベンション優先(設定より規約)** のアプローチを採用し、エンティティはファイルのサフィックスで検出されます。 これにより、`src/app/` フォルダー内を柔軟に構成できます:
| ファイルサフィックス | エンティティタイプ |
| --------------- | ------------- |
| `*.object.ts` | カスタムオブジェクトの定義 |
| `*.function.ts` | サーバーレス関数の定義 |
| `*.role.ts` | ロールの定義 |
| ファイルサフィックス | エンティティタイプ |
| ----------------------- | --------------------------- |
| `*.object.ts` | カスタムオブジェクトの定義 |
| `*.function.ts` | サーバーレス関数の定義 |
| `*.front-component.tsx` | Front component definitions |
| `*.role.ts` | ロールの定義 |
### サポートされるフォルダー構成
@@ -121,12 +119,14 @@ my-twenty-app/
**従来型(タイプ別):**
```text
src/app/
src/
├── application.config.ts
├── objects/
│ └── postCard.object.ts
├── functions/
│ └── createPostCard.function.ts
├── components/
│ └── card.front-component.tsx
└── roles/
└── admin.role.ts
```
@@ -134,44 +134,45 @@ src/app/
**機能単位:**
```text
src/app/
src/
├── application.config.ts
└── post-card/
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── postCardAdmin.role.ts
```
**フラット:**
```text
src/app/
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.ts
```
概要:
* **package.json**: アプリ名、バージョン、エンジン(Node 24+Yarn 4)を宣言し、`twenty-sdk` と、`dev`、`sync`、`generate`、`create-entity`、`logs`、`uninstall`、`auth` などのスクリプトを追加します。これらはローカルの `twenty` CLI に委譲されます。
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **.gitignore**: `node_modules`、`.yarn`、`generated/`(型付きクライアント)、`dist/`、`build/`、カバレッジ用フォルダー、ログファイル、`.env*` ファイルなどの一般的な生成物を無視します。
* **yarn.lock**、**.yarnrc.yml**、**.yarn/**: プロジェクトで使用する Yarn 4 ツールチェーンをロックおよび構成します。
* **.nvmrc**: プロジェクトで想定する Node.js バージョンを固定します。
* **eslint.config.mjs** と **tsconfig.json**: アプリの TypeScript ソース向けの Lint と TypeScript 設定を提供します。
* **README.md**: アプリのルートにある、基本的な手順を記した短い README。
* **src/app/**: アプリケーションをコードとして定義する主な場所:
* **src/**: The main place where you define your application-as-code:
* `application.config.ts`: アプリのグローバル設定(メタデータとランタイムの接続)。 「アプリケーション設定」を参照してください。
* `*.role.ts`: サーバーレス関数で使用するロール定義。 「デフォルトの関数ロール」を参照してください。
* `*.object.ts`: カスタムオブジェクトの定義。
* `*.function.ts`: サーバーレス関数の定義。
* **src/utils/**: ハンドラーの実装やユーティリティ用の任意フォルダー。
* `*.front-component.tsx`: Front component definitions.
後続のコマンドにより、さらにファイルやフォルダーが追加されます:
* `yarn app:generate` は `generated/` フォルダー(型付きの Twenty クライアント + ワークスペースの型)を作成します。
* `yarn app:create-entity` は、カスタムオブジェクト、関数、ロール用のエンティティ定義ファイルを `src/app/` 配下に追加します。
l
* `yarn entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
## 認証
@@ -302,63 +303,12 @@ export default defineObject({
* `universalIdentifier` は、デプロイをまたいで一意かつ安定している必要があります。
* 各フィールドには、`name`、`type`、`label`、および自身の安定した `universalIdentifier` が必要です。
* `fields` 配列は任意です。カスタムフィールドなしでオブジェクトを定義できます。
* `yarn app:create-entity` を使用すれば、新しいオブジェクトをスキャフォルドできます。名前、フィールド、リレーションシップの設定がガイドされます。
* You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
<Note>
**ベースフィールドは自動作成されます。** カスタムオブジェクトを定義すると、Twenty は `name`、`createdAt`、`updatedAt`、`createdBy`、`position`、`deletedAt` などの標準フィールドを自動的に追加します。 これらを `fields` 配列で定義する必要はありません。カスタムフィールドのみを追加してください。
</Note>
<Accordion title="代替: デコレーター ベースの構文">
TypeScript のデコレーターを使ってオブジェクトを定義することもできます。 この方法では、`@Object`、`@Field`、`@Relation` デコレーターを用いたクラスベースの構文を使用します:
```typescript
import {
type AddressField,
Field,
FieldType,
type FullNameField,
Object,
OnDeleteAction,
Relation,
RelationType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
import { type Note } from '../../generated';
@Object({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post card',
labelPlural: 'Post cards',
description: 'A post card object',
icon: 'IconMail',
})
export class PostCard {
@Field({
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
})
content: string;
@Relation({
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
type: RelationType.ONE_TO_MANY,
label: 'Notes',
icon: 'IconComment',
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
onDelete: OnDeleteAction.CASCADE,
})
notes: Note[];
}
```
注記: デコレーター方式では、TypeScript 設定で `experimentalDecorators` が必要です。
</Accordion>
### アプリケーション設定(application.config.ts
すべてのアプリには、次の内容を記述する単一の `application.config.ts` ファイルがあります:
@@ -469,14 +419,9 @@ export default defineRole({
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '../../generated';
import Twenty, { type Person } from '~/generated';
const handler = async (
params:
| RoutePayload
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
| CronPayload,
) => {
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'
@@ -507,18 +452,18 @@ export default defineFunction({
isAuthRequired: false,
},
// Cron trigger (CRON pattern)
{
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
type: 'cron',
pattern: '0 0 1 1 *',
},
// {
// 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'],
},
// {
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
// type: 'databaseEvent',
// eventName: 'person.updated',
// updatedFields: ['name'],
// },
],
});
```
@@ -633,7 +578,7 @@ const handler = async (event: RoutePayload) => {
新しい関数は次の 2 通りで作成できます:
* **スキャフォルド**: `yarn app:create-entity` を実行し、新しい関数を追加するオプションを選択します。 これにより、ハンドラーと設定を備えたスターターファイルが生成されます。
* **Scaffolded**: Run `yarn entity:add` and choose the option to add a new function. これにより、ハンドラーと設定を備えたスターターファイルが生成されます。
* **手動**: 新しい `*.function.ts` ファイルを作成し、同じパターンで `defineFunction()` を使用します。
### 生成された型付きクライアント
@@ -641,13 +586,13 @@ const handler = async (event: RoutePayload) => {
ワークスペースのスキーマに基づき、generated/ にローカルの型付きクライアントを作成するには yarn app:generate を実行します。 関数内で使用します:
```typescript
import Twenty from './generated';
import Twenty from '~/generated';
const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
```
このクライアントは `yarn app:generate` によって再生成されます。 オブジェクトを変更して `yarn app:sync` した後、または新しいワークスペースにオンボードする際には再実行してください。
このクライアントは `yarn app:generate` によって再生成されます。 Re-run after changing your objects or when onboarding to a new workspace.
#### サーバーレス関数における実行時認証情報
@@ -679,25 +624,29 @@ yarn add -D twenty-sdk
```json filename="package.json"
{
"scripts": {
"auth": "twenty auth login",
"generate": "twenty app generate",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
}
}
```
これで Yarn 経由で同じコマンド(例:`yarn app:dev``yarn app:sync` など)を実行できます。
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
## トラブルシューティング
* 認証エラー: `yarn auth:login` を実行し、API キーに必要な権限があることを確認してください。
* サーバーに接続できません: API URL と、Twenty サーバーに到達可能であることを確認してください。
* 型やクライアントがない/古い: `yarn app:generate` を実行してから `yarn app:dev` を実行してください。
* Types or client missing/outdated: run `yarn app:generate`.
* 開発モードで同期されない: `yarn app:dev` が実行中であり、環境によって変更が無視されていないことを確認してください。
Discord ヘルプチャンネル: https://discord.com/channels/1130383047699738754/1130386664812982322
@@ -50,15 +50,12 @@ yarn app:dev
```bash filename="Terminal"
# Add a new entity to your application (guided)
yarn app:create-entity
yarn entity:add
# Generate a typed Twenty client and workspace entity types
yarn app:generate
# Run a onetime sync (instead of watch mode)
yarn app:sync
# Watch your application's functions logs
# Watch your application's function logs
yarn function:logs
# Execute a function by name
@@ -68,7 +65,7 @@ yarn function:execute -n my-function -p '{"name": "test"}'
yarn app:uninstall
# Display commands' help
yarn app:help
yarn help
```
참고: [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) 및 [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk)의 CLI 참고 페이지도 확인하세요.
@@ -97,22 +94,23 @@ my-twenty-app/
tsconfig.json
README.md
src/
app/
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
// your entities (*.object.ts, *.function.ts, *.role.ts)
utils/ # Optional - handler implementations & utilities
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
hello-world.function.ts # Example serverless function
hello-world.front-component.tsx # Example front component
// your entities (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
```
### 설정보다 관례
애플리케이션은 파일 접미사로 엔티티를 감지하는 **관례 우선** 접근 방식을 사용합니다. 이를 통해 `src/app/` 폴더 내에서 유연하게 구성할 수 있습니다:
| 파일 접미사 | 엔티티 유형 |
| --------------- | ------------ |
| `*.object.ts` | 사용자 정의 객체 정의 |
| `*.function.ts` | 서버리스 함수 정의 |
| `*.role.ts` | 역할 정의 |
| 파일 접미사 | 엔티티 유형 |
| ----------------------- | --------------------------- |
| `*.object.ts` | 사용자 정의 객체 정의 |
| `*.function.ts` | 서버리스 함수 정의 |
| `*.front-component.tsx` | Front component definitions |
| `*.role.ts` | 역할 정의 |
### 지원되는 폴더 구성 방식
@@ -121,12 +119,14 @@ my-twenty-app/
**전통적(유형별):**
```text
src/app/
src/
├── application.config.ts
├── objects/
│ └── postCard.object.ts
├── functions/
│ └── createPostCard.function.ts
├── components/
│ └── card.front-component.tsx
└── roles/
└── admin.role.ts
```
@@ -134,44 +134,45 @@ src/app/
**기능 기반:**
```text
src/app/
src/
├── application.config.ts
└── post-card/
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── postCardAdmin.role.ts
```
**플랫:**
```text
src/app/
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.ts
```
개요:
* **package.json**: 앱 이름, 버전, 엔진(Node 24+, Yarn 4)을 선언하고, `twenty-sdk`와 함께 `dev`, `sync`, `generate`, `create-entity`, `logs`, `uninstall`, `auth` 같은 스크립트를 추가합니다. 이 스크립트들은 로컬 `twenty` CLI에 위임됩니다.
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **.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입니다.
* **src/app/**: 애플리케이션을 코드로 정의하는 주요 위치:
* **src/**: The main place where you define your application-as-code:
* `application.config.ts`: 앱의 전역 구성(메타데이터 및 런타임 연결)입니다. 아래의 "Application config"를 참조하세요.
* `*.role.ts`: 서버리스 함수에서 사용하는 역할 정의. 아래의 "Default function role"을 참조하세요.
* `*.object.ts`: 사용자 정의 객체 정의.
* `*.function.ts`: 서버리스 함수 정의.
* **src/utils/**: 핸들러 구현 및 유틸리티를 위한 선택적 폴더.
* `*.front-component.tsx`: Front component definitions.
이후 명령을 실행하면 더 많은 파일과 폴더가 추가됩니다:
* `yarn app:generate`는 `generated/` 폴더를 생성합니다(타입드 Twenty 클라이언트 + 워크스페이스 타입).
* `yarn app:create-entity`는 사용자 정의 객체, 함수, 역할에 대한 엔티티 정의 파일을 `src/app/` 아래에 추가합니다.
l
* `yarn entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
## 인증
@@ -302,63 +303,12 @@ export default defineObject({
* `universalIdentifier`는 배포 전반에서 고유하고 안정적이어야 합니다.
* 각 필드는 `name`, `type`, `label` 및 고유하고 안정적인 `universalIdentifier`가 필요합니다.
* `fields` 배열은 선택 사항입니다. 사용자 정의 필드 없이도 객체를 정의할 수 있습니다.
* `yarn app:create-entity`를 사용하여 새 객체를 스캐폴딩할 수 있으며, 이름, 필드, 관계 설정 과정을 안내합니다.
* You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
<Note>
**기본 필드는 자동으로 생성됩니다.** 사용자 정의 객체를 정의하면 Twenty가 `name`, `createdAt`, `updatedAt`, `createdBy`, `position`, `deletedAt` 등의 표준 필드를 자동으로 추가합니다. 이 필드들은 `fields` 배열에 정의할 필요가 없습니다. 사용자 정의 필드만 추가하세요.
</Note>
<Accordion title="대안: 데코레이터 기반 문법">
TypeScript 데코레이터를 사용하여 객체를 정의할 수도 있습니다. 이 접근 방식은 `@Object`, `@Field`, `@Relation` 데코레이터를 사용하는 클래스 기반 문법을 사용합니다:
```typescript
import {
type AddressField,
Field,
FieldType,
type FullNameField,
Object,
OnDeleteAction,
Relation,
RelationType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
import { type Note } from '../../generated';
@Object({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post card',
labelPlural: 'Post cards',
description: 'A post card object',
icon: 'IconMail',
})
export class PostCard {
@Field({
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
})
content: string;
@Relation({
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
type: RelationType.ONE_TO_MANY,
label: 'Notes',
icon: 'IconComment',
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
onDelete: OnDeleteAction.CASCADE,
})
notes: Note[];
}
```
참고: 데코레이터 접근 방식은 TypeScript 구성에서 `experimentalDecorators`가 필요합니다.
</Accordion>
### 애플리케이션 구성(application.config.ts)
모든 앱에는 다음을 설명하는 단일 `application.config.ts` 파일이 있습니다:
@@ -469,14 +419,9 @@ export default defineRole({
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '../../generated';
import Twenty, { type Person } from '~/generated';
const handler = async (
params:
| RoutePayload
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
| CronPayload,
) => {
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'
@@ -507,18 +452,18 @@ export default defineFunction({
isAuthRequired: false,
},
// Cron trigger (CRON pattern)
{
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
type: 'cron',
pattern: '0 0 1 1 *',
},
// {
// 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'],
},
// {
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
// type: 'databaseEvent',
// eventName: 'person.updated',
// updatedFields: ['name'],
// },
],
});
```
@@ -633,7 +578,7 @@ const handler = async (event: RoutePayload) => {
새 함수를 만드는 방법은 두 가지입니다:
* **스캐폴딩**: `yarn app:create-entity`를 실행하고 새 함수를 추가하는 옵션을 선택하세요. 이렇게 하면 핸들러와 구성이 포함된 시작 파일이 생성됩니다.
* **Scaffolded**: Run `yarn entity:add` and choose the option to add a new function. 이렇게 하면 핸들러와 구성이 포함된 시작 파일이 생성됩니다.
* **수동**: 새 `*.function.ts` 파일을 만들고 동일한 패턴에 따라 `defineFunction()`을 사용하세요.
### 생성된 타입드 클라이언트
@@ -641,13 +586,13 @@ const handler = async (event: RoutePayload) => {
워크스페이스 스키마를 기반으로 generated/에 로컬 타입드 클라이언트를 생성하려면 yarn app:generate를 실행하세요. 함수에서 사용하세요:
```typescript
import Twenty from './generated';
import Twenty from '~/generated';
const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
```
클라이언트는 `yarn app:generate`로 다시 생성됩니다. 객체를 변경하고 `yarn app:sync`를 실행한 후 또는 새 워크스페이스에 온보딩할 때 다시 실행하세요.
클라이언트는 `yarn app:generate`로 다시 생성됩니다. Re-run after changing your objects or when onboarding to a new workspace.
#### 서버리스 함수의 런타임 자격 증명
@@ -679,25 +624,29 @@ yarn add -D twenty-sdk
```json filename="package.json"
{
"scripts": {
"auth": "twenty auth login",
"generate": "twenty app generate",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
}
}
```
이제 Yarn을 통해 동일한 명령을 실행할 수 있습니다. 예: `yarn app:dev`, `yarn app:sync` 등
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
## 문제 해결
* 인증 오류: `yarn auth:login`를 실행하고 API 키에 필요한 권한이 있는지 확인하세요.
* 서버에 연결할 수 없음: API URL과 Twenty 서버에 접근 가능한지 확인하세요.
* 타입 또는 클라이언트가 없거나 오래됨: `yarn app:generate`를 실행한 다음 `yarn app:dev`를 실행하세요.
* Types or client missing/outdated: run `yarn app:generate`.
* 개발 모드가 동기화되지 않음: `yarn app:dev`가 실행 중인지, 환경에서 변경 사항을 무시하지 않는지 확인하세요.
Discord 도움말 채널: https://discord.com/channels/1130383047699738754/1130386664812982322
@@ -49,26 +49,23 @@ yarn app:dev
A partir daqui você pode:
```bash filename="Terminal"
# Adicionar uma nova entidade à sua aplicação (assistido)
yarn app:create-entity
# Add a new entity to your application (guided)
yarn entity:add
# Gerar um cliente Twenty tipado e tipos de entidades do espaço de trabalho
# Generate a typed Twenty client and workspace entity types
yarn app:generate
# Executar uma sincronização única (em vez do modo de monitoramento)
yarn app:sync
# Acompanhar os logs das funções da sua aplicação
# Watch your application's function logs
yarn function:logs
# Executar uma função pelo nome
# Execute a function by name
yarn function:execute -n my-function -p '{"name": "test"}'
# Desinstalar a aplicação do espaço de trabalho atual
# Uninstall the application from the current workspace
yarn app:uninstall
# Exibir a ajuda dos comandos
yarn app:help
# Display commands' help
yarn 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).
@@ -97,22 +94,23 @@ my-twenty-app/
tsconfig.json
README.md
src/
app/
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
// your entities (*.object.ts, *.function.ts, *.role.ts)
utils/ # Optional - handler implementations & utilities
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
hello-world.function.ts # Example serverless function
hello-world.front-component.tsx # Example front component
// your entities (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
```
### Convenção sobre configuração
Os aplicativos usam uma abordagem de **convenção sobre configuração** em que as entidades são detectadas pelo sufixo do arquivo. Isso permite organização flexível dentro da pasta `src/app/`:
| Sufixo de arquivo | Tipo de entidade |
| ----------------- | ------------------------------------ |
| `*.object.ts` | Definições de objetos personalizados |
| `*.function.ts` | Definições de funções serverless |
| `*.role.ts` | Definições de papéis |
| Sufixo de arquivo | Tipo de entidade |
| ----------------------- | ------------------------------------ |
| `*.object.ts` | Definições de objetos personalizados |
| `*.function.ts` | Definições de funções serverless |
| `*.front-component.tsx` | Front component definitions |
| `*.role.ts` | Definições de papéis |
### Organizações de pastas suportadas
@@ -121,12 +119,14 @@ Você pode organizar suas entidades em qualquer um destes padrões:
**Tradicional (por tipo):**
```text
src/app/
src/
├── application.config.ts
├── objects/
│ └── postCard.object.ts
├── functions/
│ └── createPostCard.function.ts
├── components/
│ └── card.front-component.tsx
└── roles/
└── admin.role.ts
```
@@ -134,44 +134,45 @@ src/app/
**Baseada em funcionalidades:**
```text
src/app/
src/
├── application.config.ts
└── post-card/
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── postCardAdmin.role.ts
```
**Plana:**
```text
src/app/
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.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 scripts como `dev`, `sync`, `generate`, `create-entity`, `logs`, `uninstall` e `auth` que delegam para a CLI `twenty` local.
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **.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.
* **eslint.config.mjs** 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.
* **src/app/**: O local principal onde você define seu aplicativo como código:
* **src/**: The main place where you define your application-as-code:
* `application.config.ts`: Configuração global do seu aplicativo (metadados e conexões de execução). Veja "Configuração do aplicativo" abaixo.
* `*.role.ts`: Definições de papéis usados pelas suas funções serverless. Veja "Papel de função padrão" abaixo.
* `*.object.ts`: Definições de objetos personalizados.
* `*.function.ts`: Definições de funções serverless.
* **src/utils/**: Pasta opcional para implementações de handlers e utilitários.
* `*.front-component.tsx`: Front component definitions.
Comandos posteriores adicionarão mais arquivos e pastas:
* `yarn app:generate` criará uma pasta `generated/` (cliente tipado do Twenty + tipos do workspace).
* `yarn app:create-entity` adicionará arquivos de definição de entidades em `src/app/` para seus objetos, funções ou papéis personalizados.
l
* `yarn entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
## Autenticação
@@ -302,63 +303,12 @@ Pontos-chave:
* 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 app:create-entity`, que orienta você sobre nomeação, campos e relacionamentos.
* You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
<Note>
**Os campos base são criados automaticamente.** Quando você define um objeto personalizado, o Twenty adiciona automaticamente campos padrão como `name`, `createdAt`, `updatedAt`, `createdBy`, `position` e `deletedAt`. Você não precisa definir esses no seu array `fields` — adicione apenas seus campos personalizados.
</Note>
<Accordion title="Alternativa: Sintaxe baseada em decoradores">
Você também pode definir objetos usando decoradores do TypeScript. Essa abordagem usa sintaxe baseada em classe com os decoradores `@Object`, `@Field` e `@Relation`:
```typescript
import {
type AddressField,
Field,
FieldType,
type FullNameField,
Object,
OnDeleteAction,
Relation,
RelationType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
import { type Note } from '../../generated';
@Object({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post card',
labelPlural: 'Post cards',
description: 'A post card object',
icon: 'IconMail',
})
export class PostCard {
@Field({
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
})
content: string;
@Relation({
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
type: RelationType.ONE_TO_MANY,
label: 'Notes',
icon: 'IconComment',
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
onDelete: OnDeleteAction.CASCADE,
})
notes: Note[];
}
```
Observação: A abordagem com decoradores requer `experimentalDecorators` na sua configuração do TypeScript.
</Accordion>
### Configuração do aplicativo (application.config.ts)
Todo aplicativo tem um único arquivo `application.config.ts` que descreve:
@@ -469,14 +419,9 @@ Cada arquivo de função usa `defineFunction()` para exportar uma configuração
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '../../generated';
import Twenty, { type Person } from '~/generated';
const handler = async (
params:
| RoutePayload
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
| CronPayload,
) => {
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'
@@ -507,18 +452,18 @@ export default defineFunction({
isAuthRequired: false,
},
// Cron trigger (CRON pattern)
{
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
type: 'cron',
pattern: '0 0 1 1 *',
},
// {
// 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'],
},
// {
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
// type: 'databaseEvent',
// eventName: 'person.updated',
// updatedFields: ['name'],
// },
],
});
```
@@ -633,7 +578,7 @@ const handler = async (event: RoutePayload) => {
Você pode criar novas funções de duas formas:
* **Gerado automaticamente**: Execute `yarn app:create-entity` e escolha a opção para adicionar uma nova função. Isso gera um arquivo inicial com um handler e configuração.
* **Scaffolded**: Run `yarn entity:add` and choose the option to add a new function. Isso gera um arquivo inicial com um handler e configuração.
* **Manual**: Crie um novo arquivo `*.function.ts` e use `defineFunction()`, seguindo o mesmo padrão.
### Cliente tipado gerado
@@ -641,13 +586,13 @@ Você pode criar novas funções de duas formas:
Execute yarn app:generate para criar um cliente tipado local em generated/ com base no esquema do seu workspace. Use-o em suas funções:
```typescript
import Twenty from './generated';
import Twenty from '~/generated';
const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
```
O cliente é regenerado pelo `yarn app:generate`. Execute novamente após alterar seus objetos e executar `yarn app:sync`, ou ao ingressar em um novo workspace.
O cliente é regenerado pelo `yarn app:generate`. Re-run after changing your objects or when onboarding to a new workspace.
#### Credenciais em tempo de execução em funções serverless
@@ -679,25 +624,29 @@ Em seguida, adicione scripts como estes:
```json filename="package.json"
{
"scripts": {
"auth": "twenty auth login",
"generate": "twenty app generate",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
}
}
```
Agora você pode executar os mesmos comandos via Yarn, por exemplo, `yarn app:dev`, `yarn app:sync`, etc.
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
## Resolução de Problemas
* Erros de autenticação: execute `yarn 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: execute `yarn app:generate` e depois `yarn app:dev`.
* Types or client missing/outdated: run `yarn app:generate`.
* Modo de desenvolvimento não sincronizando: certifique-se de que `yarn 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
@@ -49,26 +49,23 @@ yarn app:dev
De aici puteți:
```bash filename="Terminal"
# Add a new entity to your application (guided)
yarn app:create-entity
# Adaugă o entitate nouă în aplicația ta (ghidat)
yarn entity:add
# Generate a typed Twenty client and workspace entity types
# Generează un client Twenty tipat și tipurile de entități ale spațiului de lucru
yarn app:generate
# Run a onetime sync (instead of watch mode)
yarn app:sync
# Watch your application's functions logs
# Urmărește jurnalele funcțiilor aplicației tale
yarn function:logs
# Execute a function by name
# Execută o funcție după nume
yarn function:execute -n my-function -p '{"name": "test"}'
# Uninstall the application from the current workspace
# Dezinstalează aplicația din spațiul de lucru curent
yarn app:uninstall
# Display commands' help
yarn app:help},{
# Afișează ajutorul pentru comenzi
yarn 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).
@@ -97,22 +94,23 @@ my-twenty-app/
tsconfig.json
README.md
src/
app/
application.config.ts # Obligatoriu - configurația principală a aplicației
default-function.role.ts # Rolul implicit pentru funcțiile serverless
// entitățile tale (*.object.ts, *.function.ts, *.role.ts)
utils/ # Opțional - implementări de handleri și utilitare
application.config.ts # Obligatoriu - configurația principală a aplicației
default-function.role.ts # Rolul implicit pentru funcțiile serverless
hello-world.function.ts # Exemplu de funcție serverless
hello-world.front-component.tsx # Exemplu de componentă de interfață
// entitățile tale (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
```
### Convenție în locul configurării
Aplicațiile folosesc o abordare bazată pe convenție în locul configurării, în care entitățile sunt detectate după sufixul fișierului. Aceasta permite o organizare flexibilă în folderul `src/app/`:
| Sufixul fișierului | Tipul entității |
| ------------------ | ---------------------------------- |
| `*.object.ts` | Definiții de obiecte personalizate |
| `*.function.ts` | Definiții de funcții serverless |
| `*.role.ts` | Definiții de rol |
| Sufixul fișierului | Tipul entității |
| ----------------------- | ---------------------------------------- |
| `*.object.ts` | Definiții de obiecte personalizate |
| `*.function.ts` | Definiții de funcții serverless |
| `*.front-component.tsx` | Definiții ale componentelor de interfață |
| `*.role.ts` | Definiții de rol |
### Structuri de foldere acceptate
@@ -121,12 +119,14 @@ Vă puteți organiza entitățile în oricare dintre aceste modele:
**Tradițional (după tip):**
```text
src/app/
src/
├── application.config.ts
├── objects/
│ └── postCard.object.ts
├── functions/
│ └── createPostCard.function.ts
├── components/
│ └── card.front-component.tsx
└── roles/
└── admin.role.ts
```
@@ -134,44 +134,45 @@ src/app/
**Bazat pe funcționalități:**
```text
src/app/
src/
├── application.config.ts
└── post-card/
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── postCardAdmin.role.ts
```
**Plat:**
```text
src/app/
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.ts
```
Pe scurt:
* **package.json**: Declară numele aplicației, versiunea, motoarele (Node 24+, Yarn 4) și adaugă `twenty-sdk` plus scripturi precum `dev`, `sync`, `generate`, `create-entity`, `logs`, `uninstall` și `auth` care deleagă către CLI-ul local `twenty`.
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **.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.
* **eslint.config.mjs** ș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ă.
* **src/app/**: Locul principal unde vă definiți aplicația sub formă de cod:
* **src/**: The main place where you define your application-as-code:
* `application.config.ts`: Configurație globală pentru aplicație (metadate și conectare la runtime). Vezi "Configurația aplicației" mai jos.
* `*.role.ts`: Definiții de rol folosite de funcțiile dvs. serverless. Vezi "Rol implicit pentru funcții" mai jos.
* `*.object.ts`: Definiții de obiecte personalizate.
* `*.function.ts`: Definiții de funcții serverless.
* **src/utils/**: Folder opțional pentru implementări de handleri și utilitare.
* `*.front-component.tsx`: Front component definitions.
Comenzile ulterioare vor adăuga mai multe fișiere și foldere:
* `yarn app:generate` va crea un folder `generated/` (client Twenty tipizat + tipuri pentru spațiul de lucru).
* `yarn app:create-entity` va adăuga fișiere de definire a entităților în `src/app/` pentru obiectele, funcțiile sau rolurile personalizate.
l
* `yarn entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
## Autentificare
@@ -302,63 +303,12 @@ Puncte cheie:
* `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 app:create-entity`, care vă ghidează prin denumire, câmpuri și relații.
* You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
<Note>
**Câmpurile de bază sunt create automat.** Când definiți un obiect personalizat, Twenty adaugă automat câmpuri standard precum `name`, `createdAt`, `updatedAt`, `createdBy`, `position` și `deletedAt`. Nu trebuie să le definiți în tabloul `fields` — adăugați doar câmpurile personalizate proprii.
</Note>
<Accordion title="Alternativă: Sintaxă bazată pe decoratori">
Puteți defini obiecte și folosind decoratori TypeScript. Această abordare folosește o sintaxă bazată pe clase cu decoratorii `@Object`, `@Field` și `@Relation`:
```typescript
import {
type AddressField,
Field,
FieldType,
type FullNameField,
Object,
OnDeleteAction,
Relation,
RelationType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
import { type Note } from '../../generated';
@Object({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post card',
labelPlural: 'Post cards',
description: 'A post card object',
icon: 'IconMail',
})
export class PostCard {
@Field({
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
})
content: string;
@Relation({
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
type: RelationType.ONE_TO_MANY,
label: 'Notes',
icon: 'IconComment',
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
onDelete: OnDeleteAction.CASCADE,
})
notes: Note[];
}
```
Notă: Abordarea cu decoratori necesită `experimentalDecorators` în configurația TypeScript.
</Accordion>
### Configurația aplicației (application.config.ts)
Fiecare aplicație are un singur fișier `application.config.ts` care descrie:
@@ -469,14 +419,9 @@ Fiecare fișier de funcție folosește `defineFunction()` pentru a exporta o con
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '../../generated';
import Twenty, { type Person } from '~/generated';
const handler = async (
params:
| RoutePayload
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
| CronPayload,
) => {
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'
@@ -507,18 +452,18 @@ export default defineFunction({
isAuthRequired: false,
},
// Cron trigger (CRON pattern)
{
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
type: 'cron',
pattern: '0 0 1 1 *',
},
// {
// 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'],
},
// {
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
// type: 'databaseEvent',
// eventName: 'person.updated',
// updatedFields: ['name'],
// },
],
});
```
@@ -633,7 +578,7 @@ const handler = async (event: RoutePayload) => {
Puteți crea funcții noi în două moduri:
* **Generat**: Rulați `yarn app:create-entity` și alegeți opțiunea de a adăuga o funcție nouă. Aceasta generează un fișier inițial cu un handler și o configurație.
* **Scaffolded**: Run `yarn entity:add` and choose the option to add a new function. Aceasta generează un fișier inițial cu un handler și o configurație.
* **Manual**: Creați un fișier nou `*.function.ts` și folosiți `defineFunction()`, urmând același model.
### Client tipizat generat
@@ -641,13 +586,13 @@ Puteți crea funcții noi în două moduri:
Rulați yarn app:generate pentru a crea un client tipizat local în generated/, pe baza schemei spațiului de lucru. Folosiți-l în funcțiile dvs.:
```typescript
import Twenty from './generated';
import Twenty from '~/generated';
const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
```
Clientul este regenerat de `yarn app:generate`. Rulați din nou după ce vă modificați obiectele și rulați `yarn app:sync` sau când vă integrați într-un spațiu de lucru nou.
Clientul este regenerat de `yarn app:generate`. Re-run after changing your objects or when onboarding to a new workspace.
#### Acreditări la runtime în funcțiile serverless
@@ -679,25 +624,29 @@ Apoi adăugați scripturi ca acestea:
```json filename="package.json"
{
"scripts": {
"auth": "twenty auth login",
"generate": "twenty app generate",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
}
}
```
Acum puteți rula aceleași comenzi prin Yarn, de ex. `yarn app:dev`, `yarn app:sync`, etc.
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
## Depanare
* Erori de autentificare: rulați `yarn 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: rulați `yarn app:generate` și apoi `yarn app:dev`.
* Types or client missing/outdated: run `yarn app:generate`.
* Modul dev nu sincronizează: asigurați-vă că `yarn app:dev` rulează și că modificările nu sunt ignorate de mediul dvs.
Canal de ajutor pe Discord: https://discord.com/channels/1130383047699738754/1130386664812982322
@@ -49,26 +49,23 @@ yarn app:dev
Отсюда вы можете:
```bash filename="Terminal"
# Добавить новую сущность в ваше приложение (с мастером)
yarn app:create-entity
# Add a new entity to your application (guided)
yarn entity:add
# Сгенерировать типизированный клиент Twenty и типы сущностей рабочего пространства
# Generate a typed Twenty client and workspace entity types
yarn app:generate
# Выполнить разовую синхронизацию (вместо watch‑режима)
yarn app:sync
# Просматривать логи функций вашего приложения
# Watch your application's function logs
yarn function:logs
# Выполнить функцию по имени
# Execute a function by name
yarn function:execute -n my-function -p '{"name": "test"}'
# Удалить приложение из текущего рабочего пространства
# Uninstall the application from the current workspace
yarn app:uninstall
# Показать справку по командам
yarn app:help
# Display commands' help
yarn help
```
Смотрите также: страницы справки CLI для [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) и [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -97,22 +94,23 @@ my-twenty-app/
tsconfig.json
README.md
src/
app/
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
// your entities (*.object.ts, *.function.ts, *.role.ts)
utils/ # Optional - handler implementations & utilities
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
hello-world.function.ts # Example serverless function
hello-world.front-component.tsx # Example front component
// your entities (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
```
### Соглашения важнее конфигурации
Приложения используют подход **соглашения важнее конфигурации**, при котором сущности определяются по суффиксу файла. Это позволяет гибко организовать структуру в папке `src/app/`:
| Суффикс файла | Тип сущности |
| --------------- | ------------------------------------- |
| `*.object.ts` | Определения пользовательских объектов |
| `*.function.ts` | Определения бессерверных функций |
| `*.role.ts` | Определения ролей |
| Суффикс файла | Тип сущности |
| ----------------------- | ------------------------------------- |
| `*.object.ts` | Определения пользовательских объектов |
| `*.function.ts` | Определения бессерверных функций |
| `*.front-component.tsx` | Front component definitions |
| `*.role.ts` | Определения ролей |
### Поддерживаемые способы организации папок
@@ -121,12 +119,14 @@ my-twenty-app/
**Традиционный (по типам):**
```text
src/app/
src/
├── application.config.ts
├── objects/
│ └── postCard.object.ts
├── functions/
│ └── createPostCard.function.ts
├── components/
│ └── card.front-component.tsx
└── roles/
└── admin.role.ts
```
@@ -134,44 +134,45 @@ src/app/
**По функциональности:**
```text
src/app/
src/
├── application.config.ts
└── post-card/
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── postCardAdmin.role.ts
```
**Плоский:**
```text
src/app/
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.ts
```
В общих чертах:
* **package.json**: Объявляет имя приложения, версию, движки (Node 24+, Yarn 4) и добавляет `twenty-sdk`, а также скрипты вроде `dev`, `sync`, `generate`, `create-entity`, `logs`, `uninstall` и `auth`, которые делегируют выполнение локальному CLI `twenty`.
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **.gitignore**: Игнорирует распространённые артефакты, такие как `node_modules`, `.yarn`, `generated/` (типизированный клиент), `dist/`, `build/`, каталоги coverage, файлы журналов и файлы `.env*`.
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Фиксируют и настраивают используемый в проекте инструментарий Yarn 4.
* **.nvmrc**: Фиксирует версию Node.js, ожидаемую проектом.
* **eslint.config.mjs** и **tsconfig.json**: Обеспечивают линтинг и конфигурацию TypeScript для исходников вашего приложения на TypeScript.
* **README.md**: Короткий README в корне приложения с базовыми инструкциями.
* **src/app/**: Основное место, где вы определяете приложение как код:
* **src/**: The main place where you define your application-as-code:
* `application.config.ts`: Глобальная конфигурация вашего приложения (метаданные и параметры выполнения). См. раздел «Конфигурация приложения» ниже.
* `*.role.ts`: Определения ролей, используемых вашими бессерверными функциями. См. раздел «Роль функции по умолчанию» ниже.
* `*.object.ts`: Определения пользовательских объектов.
* `*.function.ts`: Определения бессерверных функций.
* **src/utils/**: Необязательная папка для реализаций обработчиков и утилит.
* `*.front-component.tsx`: Front component definitions.
Позднее команды добавят больше файлов и папок:
* `yarn app:generate` создаст папку `generated/` (типизированный клиент Twenty + типы рабочего пространства).
* `yarn app:create-entity` добавит файлы определений сущностей в `src/app/` для ваших пользовательских объектов, функций или ролей.
l
* `yarn entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
## Аутентификация
@@ -302,63 +303,12 @@ export default defineObject({
* `universalIdentifier` должен быть уникальным и стабильным между развёртываниями.
* Каждому полю требуются `name`, `type`, `label` и собственный стабильный `universalIdentifier`.
* Массив `fields` необязателен — вы можете определять объекты без пользовательских полей.
* Вы можете сгенерировать новые объекты с помощью `yarn app:create-entity`, который проведёт вас через выбор именования, полей и связей.
* You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
<Note>
**Базовые поля создаются автоматически.** Когда вы определяете пользовательский объект, Twenty автоматически добавляет стандартные поля, такие как `name`, `createdAt`, `updatedAt`, `createdBy`, `position` и `deletedAt`. Вам не нужно определять их в массиве `fields` — добавляйте только свои пользовательские поля.
</Note>
<Accordion title="Альтернатива: синтаксис на декораторах">
Вы также можете определять объекты с помощью декораторов TypeScript. Этот подход использует классовый синтаксис с декораторами `@Object`, `@Field` и `@Relation`:
```typescript
import {
type AddressField,
Field,
FieldType,
type FullNameField,
Object,
OnDeleteAction,
Relation,
RelationType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
import { type Note } from '../../generated';
@Object({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post card',
labelPlural: 'Post cards',
description: 'A post card object',
icon: 'IconMail',
})
export class PostCard {
@Field({
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
})
content: string;
@Relation({
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
type: RelationType.ONE_TO_MANY,
label: 'Notes',
icon: 'IconComment',
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
onDelete: OnDeleteAction.CASCADE,
})
notes: Note[];
}
```
Примечание: подход с декораторами требует `experimentalDecorators` в конфигурации TypeScript.
</Accordion>
### Конфигурация приложения (application.config.ts)
У каждого приложения есть единственный файл `application.config.ts`, который описывает:
@@ -469,14 +419,9 @@ export default defineRole({
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '../../generated';
import Twenty, { type Person } from '~/generated';
const handler = async (
params:
| RoutePayload
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
| CronPayload,
) => {
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'
@@ -507,18 +452,18 @@ export default defineFunction({
isAuthRequired: false,
},
// Cron trigger (CRON pattern)
{
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
type: 'cron',
pattern: '0 0 1 1 *',
},
// {
// 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'],
},
// {
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
// type: 'databaseEvent',
// eventName: 'person.updated',
// updatedFields: ['name'],
// },
],
});
```
@@ -633,7 +578,7 @@ const handler = async (event: RoutePayload) => {
Вы можете создать новые функции двумя способами:
* **Сгенерировано**: Запустите `yarn app:create-entity` и выберите опцию добавления новой функции. Это создаёт стартовый файл с обработчиком и конфигурацией.
* **Scaffolded**: Run `yarn entity:add` and choose the option to add a new function. Это создаёт стартовый файл с обработчиком и конфигурацией.
* **Вручную**: Создайте новый файл `*.function.ts` и используйте `defineFunction()`, следуя тому же шаблону.
### Сгенерированный типизированный клиент
@@ -641,13 +586,13 @@ const handler = async (event: RoutePayload) => {
Запустите yarn app:generate, чтобы создать локальный типизированный клиент в generated/ на основе схемы вашего рабочего пространства. Используйте его в своих функциях:
```typescript
import Twenty from './generated';
import Twenty from '~/generated';
const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
```
Клиент повторно генерируется командой `yarn app:generate`. Запускайте повторно после изменения ваших объектов и `yarn app:sync` или при подключении к новому рабочему пространству.
Клиент повторно генерируется командой `yarn app:generate`. Re-run after changing your objects or when onboarding to a new workspace.
#### Учётные данные времени выполнения в бессерверных функциях
@@ -679,25 +624,29 @@ yarn add -D twenty-sdk
```json filename="package.json"
{
"scripts": {
"auth": "twenty auth login",
"generate": "twenty app generate",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
}
}
```
Теперь вы можете запускать те же команды через Yarn, например, `yarn app:dev`, `yarn app:sync` и т. д.
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
## Устранение неполадок
* Ошибки аутентификации: выполните `yarn auth:login` и убедитесь, что у вашего ключа API есть необходимые права.
* Не удаётся подключиться к серверу: проверьте URL API и доступность сервера Twenty.
* Отсутствующие/устаревшие типы или клиент: выполните `yarn app:generate`, затем `yarn app:dev`.
* Types or client missing/outdated: run `yarn app:generate`.
* Режим разработки не синхронизируется: убедитесь, что запущен `yarn app:dev`, и что ваша среда не игнорирует изменения.
Канал помощи в Discord: https://discord.com/channels/1130383047699738754/1130386664812982322
@@ -50,15 +50,12 @@ Buradan şunları yapabilirsiniz:
```bash filename="Terminal"
# Add a new entity to your application (guided)
yarn app:create-entity
yarn entity:add
# Generate a typed Twenty client and workspace entity types
yarn app:generate
# Run a onetime sync (instead of watch mode)
yarn app:sync
# Watch your application's functions logs
# Watch your application's function logs
yarn function:logs
# Execute a function by name
@@ -68,7 +65,7 @@ yarn function:execute -n my-function -p '{"name": "test"}'
yarn app:uninstall
# Display commands' help
yarn app:help
yarn 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ı.
@@ -97,22 +94,23 @@ my-twenty-app/
tsconfig.json
README.md
src/
app/
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
// your entities (*.object.ts, *.function.ts, *.role.ts)
utils/ # Optional - handler implementations & utilities
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
hello-world.function.ts # Example serverless function
hello-world.front-component.tsx # Example front component
// your entities (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
```
### Sözleşme-öncelikli yapılandırma
Uygulamalar, varlıkların dosya sonekiyle algılandığı **sözleşme-öncelikli yapılandırma** yaklaşımını kullanır. Bu, `src/app/` klasörü içinde esnek bir düzenlemeye olanak tanır:
| Dosya soneki | Varlık türü |
| --------------- | ----------------------------- |
| `*.object.ts` | Özel nesne tanımları |
| `*.function.ts` | Sunucusuz fonksiyon tanımları |
| `*.role.ts` | Rol tanımları |
| Dosya soneki | Varlık türü |
| ----------------------- | ----------------------------- |
| `*.object.ts` | Özel nesne tanımları |
| `*.function.ts` | Sunucusuz fonksiyon tanımları |
| `*.front-component.tsx` | Front component definitions |
| `*.role.ts` | Rol tanımları |
### Desteklenen klasör düzenleri
@@ -121,12 +119,14 @@ Varlıklarınızı şu desenlerden herhangi birine göre düzenleyebilirsiniz:
**Geleneksel (türe göre):**
```text
src/app/
src/
├── application.config.ts
├── objects/
│ └── postCard.object.ts
├── functions/
│ └── createPostCard.function.ts
├── components/
│ └── card.front-component.tsx
└── roles/
└── admin.role.ts
```
@@ -134,44 +134,45 @@ src/app/
**Özelliğe dayalı:**
```text
src/app/
src/
├── application.config.ts
└── post-card/
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── postCardAdmin.role.ts
```
**Düz:**
```text
src/app/
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.ts
```
Genel hatlarıyla:
* **package.json**: Uygulama adını, sürümünü, motorları (Node 24+, Yarn 4) bildirir ve yerel `twenty` CLI’ına yetki devreden `dev`, `sync`, `generate`, `create-entity`, `logs`, `uninstall` ve `auth` gibi betiklerin yanı sıra `twenty-sdk` ekler.
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **.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.
* **eslint.config.mjs** 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.
* **src/app/**: Uygulamanızı kod olarak tanımladığınız ana yer:
* **src/**: The main place where you define your application-as-code:
* `application.config.ts`: Uygulamanız için genel yapılandırma (meta veriler ve çalışma zamanı bağlantıları). Aşağıda "Uygulama yapılandırması"na bakın.
* `*.role.ts`: Sunucusuz fonksiyonlarınız tarafından kullanılan rol tanımları. Aşağıda "Varsayılan fonksiyon rolü"ne bakın.
* `*.object.ts`: Özel nesne tanımları.
* `*.function.ts`: Sunucusuz fonksiyon tanımları.
* **src/utils/**: İşleyici uygulamaları ve yardımcılar için isteğe bağlı klasör.
* `*.front-component.tsx`: Front component definitions.
İlerideki komutlar daha fazla dosya ve klasör ekleyecektir:
* `yarn app:generate`, `generated/` klasörünü oluşturur (türlendirilmiş Twenty istemcisi + çalışma alanı türleri).
* `yarn app:create-entity`, özel nesneleriniz, fonksiyonlarınız veya rolleriniz için `src/app/` altında varlık tanım dosyaları ekler.
l
* `yarn entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
## Kimlik Doğrulama
@@ -302,63 +303,12 @@ export default defineObject({
* `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 app:create-entity` kullanarak, adlandırma, alanlar ve ilişkiler konusunda sizi yönlendirerek yeni nesneler oluşturabilirsiniz.
* You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
<Note>
**Temel alanlar otomatik olarak oluşturulur.** Özel bir nesne tanımladığınızda Twenty, `name`, `createdAt`, `updatedAt`, `createdBy`, `position` ve `deletedAt` gibi standart alanları otomatik olarak ekler. Bunları `fields` dizinizde tanımlamanız gerekmez — yalnızca özel alanlarınızı ekleyin.
</Note>
<Accordion title="Alternatif: Dekoratör tabanlı söz dizimi">
Nesneleri TypeScript dekoratörlerini kullanarak da tanımlayabilirsiniz. Bu yaklaşım, `@Object`, `@Field` ve `@Relation` dekoratörleriyle sınıf tabanlı söz dizimi kullanır:
```typescript
import {
type AddressField,
Field,
FieldType,
type FullNameField,
Object,
OnDeleteAction,
Relation,
RelationType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
import { type Note } from '../../generated';
@Object({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post card',
labelPlural: 'Post cards',
description: 'A post card object',
icon: 'IconMail',
})
export class PostCard {
@Field({
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
})
content: string;
@Relation({
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
type: RelationType.ONE_TO_MANY,
label: 'Notes',
icon: 'IconComment',
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
onDelete: OnDeleteAction.CASCADE,
})
notes: Note[];
}
```
Not: Dekoratör yaklaşımı, TypeScript yapılandırmanızda `experimentalDecorators` gerektirir.
</Accordion>
### Uygulama yapılandırması (application.config.ts)
Her uygulamanın aşağıdakileri açıklayan tek bir `application.config.ts` dosyası vardır:
@@ -469,14 +419,9 @@ Her fonksiyon dosyası, bir işleyici ve isteğe bağlı tetikleyiciler içeren
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '../../generated';
import Twenty, { type Person } from '~/generated';
const handler = async (
params:
| RoutePayload
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
| CronPayload,
) => {
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'
@@ -507,18 +452,18 @@ export default defineFunction({
isAuthRequired: false,
},
// Cron trigger (CRON pattern)
{
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
type: 'cron',
pattern: '0 0 1 1 *',
},
// {
// 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'],
},
// {
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
// type: 'databaseEvent',
// eventName: 'person.updated',
// updatedFields: ['name'],
// },
],
});
```
@@ -633,7 +578,7 @@ const handler = async (event: RoutePayload) => {
Yeni fonksiyonları iki şekilde oluşturabilirsiniz:
* **Şablondan**: `yarn app:create-entity` çalıştırın ve yeni bir fonksiyon ekleme seçeneğini seçin. Bu, bir işleyici ve yapılandırma içeren bir başlangıç dosyası oluşturur.
* **Scaffolded**: Run `yarn entity:add` and choose the option to add a new function. Bu, bir işleyici ve yapılandırma içeren bir başlangıç dosyası oluşturur.
* **Manuel**: Yeni bir `*.function.ts` dosyası oluşturun ve aynı deseni izleyerek `defineFunction()` kullanın.
### Oluşturulmuş türlendirilmiş istemci
@@ -641,13 +586,13 @@ Yeni fonksiyonları iki şekilde oluşturabilirsiniz:
Çalışma alanı şemanıza göre generated/ içinde yerel bir türlendirilmiş istemci oluşturmak için yarn app:generate çalıştırın. Fonksiyonlarınızda kullanın:
```typescript
import Twenty from './generated';
import Twenty from '~/generated';
const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
```
İstemci `yarn app:generate` tarafından yeniden oluşturulur. Nesnelerinizi değiştirip `yarn app:sync` çalıştırdıktan sonra veya yeni bir çalışma alanına katılırken yeniden çalıştırın.
İstemci `yarn app:generate` tarafından yeniden oluşturulur. Re-run after changing your objects or when onboarding to a new workspace.
#### Sunucusuz fonksiyonlarda çalışma zamanı kimlik bilgileri
@@ -679,25 +624,29 @@ Ardından şu gibi betikler ekleyin:
```json filename="package.json"
{
"scripts": {
"auth": "twenty auth login",
"generate": "twenty app generate",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
}
}
```
Artık aynı komutları Yarn üzerinden çalıştırabilirsiniz; örn. `yarn app:dev`, `yarn app:sync` vb.
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
## Sorun Giderme
* Kimlik doğrulama hataları: `yarn 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 URLsini ve Twenty sunucusunun erişilebilir olduğunu doğrulayın.
* Türler veya istemci eksik/eski: `yarn app:generate` ve ardından `yarn app:dev` çalıştırın.
* Types or client missing/outdated: run `yarn app:generate`.
* Geliştirme modu eşitlenmiyor: `yarn 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
@@ -50,15 +50,12 @@ yarn app:dev
```bash filename="Terminal"
# Add a new entity to your application (guided)
yarn app:create-entity
yarn entity:add
# Generate a typed Twenty client and workspace entity types
yarn app:generate
# Run a onetime sync (instead of watch mode)
yarn app:sync
# Watch your application's functions logs
# Watch your application's function logs
yarn function:logs
# Execute a function by name
@@ -68,7 +65,7 @@ yarn function:execute -n my-function -p '{"name": "test"}'
yarn app:uninstall
# Display commands' help
yarn app:help
yarn help
```
另请参阅:[create-twenty-app](https://www.npmjs.com/package/create-twenty-app) 和 [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk) 的 CLI 参考页面。
@@ -97,22 +94,23 @@ my-twenty-app/
tsconfig.json
README.md
src/
app/
application.config.ts # 必需 - 主应用程序配置
default-function.role.ts # 用于无服务器函数的默认角色
// 你的实体 (*.object.ts, *.function.ts, *.role.ts)
utils/ # 可选 - 处理器实现与实用工具
application.config.ts # Required - main application configuration
default-function.role.ts # Default role for serverless functions
hello-world.function.ts # Example serverless function
hello-world.front-component.tsx # Example front component
// your entities (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
```
### 约定优于配置
应用采用**约定优于配置**的方式,根据文件后缀检测实体。 这使得可以在 `src/app/` 文件夹内灵活组织:
| 文件后缀 | 实体类型 |
| --------------- | -------- |
| `*.object.ts` | 自定义对象定义 |
| `*.function.ts` | 无服务器函数定义 |
| `*.role.ts` | 角色定义 |
| 文件后缀 | 实体类型 |
| ----------------------- | --------------------------- |
| `*.object.ts` | 自定义对象定义 |
| `*.function.ts` | 无服务器函数定义 |
| `*.front-component.tsx` | Front component definitions |
| `*.role.ts` | 角色定义 |
### 支持的文件夹组织方式
@@ -121,12 +119,14 @@ my-twenty-app/
**传统(按类型):**
```text
src/app/
src/
├── application.config.ts
├── objects/
│ └── postCard.object.ts
├── functions/
│ └── createPostCard.function.ts
├── components/
│ └── card.front-component.tsx
└── roles/
└── admin.role.ts
```
@@ -134,44 +134,45 @@ src/app/
**基于特性:**
```text
src/app/
src/
├── application.config.ts
└── post-card/
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── postCardAdmin.role.ts
```
**扁平:**
```text
src/app/
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.ts
```
总体来说:
* **package.json**:声明应用名称、版本、运行时(Node 24+Yarn 4),并添加 `twenty-sdk` 以及 `dev`、`sync`、`generate`、`create-entity`、`logs`、`uninstall`、`auth` 等脚本,这些脚本会委托给本地的 `twenty` CLI
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **.gitignore**:忽略常见产物,如 `node_modules`、`.yarn`、`generated/`(类型化客户端)、`dist/`、`build/`、覆盖率文件夹、日志文件以及 `.env*` 文件。
* **yarn.lock**、**.yarnrc.yml**、**.yarn/**:锁定并配置项目使用的 Yarn 4 工具链。
* **.nvmrc**:固定项目期望的 Node.js 版本。
* **eslint.config.mjs** 和 **tsconfig.json**:为应用的 TypeScript 源码提供 Lint 与 TypeScript 配置。
* **README.md**:应用根目录中的简短 README,包含基本说明。
* **src/app/**:你以代码形式定义应用的主要位置:
* **src/**: The main place where you define your application-as-code:
* `application.config.ts`:应用的全局配置(元数据和运行时关联)。 参见下方“应用配置”。
* `*.role.ts`:你的无服务器函数所使用的角色定义。 参见下方“默认函数角色”。
* `*.object.ts`:自定义对象定义。
* `*.function.ts`:无服务器函数定义。
* **src/utils/**:可选文件夹,用于处理程序实现和实用工具。
* `*.front-component.tsx`: Front component definitions.
后续命令将添加更多文件和文件夹:
* `yarn app:generate` 将创建一个 `generated/` 文件夹(类型化 Twenty 客户端 + 工作空间类型)。
* `yarn app:create-entity` 将为你的自定义对象、函数或角色在 `src/app/` 下添加实体定义文件。
l
* `yarn entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
## 身份验证
@@ -302,63 +303,12 @@ export default defineObject({
* `universalIdentifier` 必须在各次部署间保持唯一且稳定。
* 每个字段都需要 `name`、`type`、`label` 以及其自身稳定的 `universalIdentifier`。
* `fields` 数组是可选的——你可以定义没有自定义字段的对象。
* 你可以使用 `yarn app:create-entity` 脚手架创建新对象,它会引导你完成命名、字段和关系。
* You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
<Note>
**基础字段会自动创建。** 当你定义自定义对象时,Twenty 会自动添加 `name`、`createdAt`、`updatedAt`、`createdBy`、`position`、`deletedAt` 等标准字段。 你无需在 `fields` 数组中定义这些字段——只需添加你的自定义字段。
</Note>
<Accordion title="替代方案:基于装饰器的语法">
你也可以使用 TypeScript 装饰器来定义对象。 该方式使用基于类的语法以及 `@Object`、`@Field`、`@Relation` 装饰器:
```typescript
import {
type AddressField,
Field,
FieldType,
type FullNameField,
Object,
OnDeleteAction,
Relation,
RelationType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
import { type Note } from '../../generated';
@Object({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post card',
labelPlural: 'Post cards',
description: 'A post card object',
icon: 'IconMail',
})
export class PostCard {
@Field({
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
})
content: string;
@Relation({
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
type: RelationType.ONE_TO_MANY,
label: 'Notes',
icon: 'IconComment',
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
onDelete: OnDeleteAction.CASCADE,
})
notes: Note[];
}
```
注意:装饰器方式需要在 TypeScript 配置中启用 `experimentalDecorators`。
</Accordion>
### 应用配置(application.config.ts
每个应用都有一个 `application.config.ts` 文件,用于描述:
@@ -469,14 +419,9 @@ export default defineRole({
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '../../generated';
import Twenty, { type Person } from '~/generated';
const handler = async (
params:
| RoutePayload
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
| CronPayload,
) => {
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'
@@ -507,18 +452,18 @@ export default defineFunction({
isAuthRequired: false,
},
// Cron trigger (CRON pattern)
{
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
type: 'cron',
pattern: '0 0 1 1 *',
},
// {
// 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'],
},
// {
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
// type: 'databaseEvent',
// eventName: 'person.updated',
// updatedFields: ['name'],
// },
],
});
```
@@ -633,7 +578,7 @@ const handler = async (event: RoutePayload) => {
你可以通过两种方式创建新函数:
* **脚手架生成**:运行 `yarn app:create-entity` 并选择添加新函数的选项。 这将生成一个包含处理程序和配置的入门文件。
* **Scaffolded**: Run `yarn entity:add` and choose the option to add a new function. 这将生成一个包含处理程序和配置的入门文件。
* **手动**:创建一个新的 `*.function.ts` 文件,并使用 `defineFunction()`,遵循相同的模式。
### 生成的类型化客户端
@@ -641,13 +586,13 @@ const handler = async (event: RoutePayload) => {
运行 yarn app:generate,根据你的工作空间模式在 generated/ 中创建本地类型化客户端。 在你的函数中使用它:
```typescript
import Twenty from './generated';
import Twenty from '~/generated';
const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
```
客户端会通过 `yarn app:generate` 重新生成。 在更改对象并执行 `yarn app:sync` 之后,或在接入新工作空间时,请重新运行。
客户端会通过 `yarn app:generate` 重新生成。 Re-run after changing your objects or when onboarding to a new workspace.
#### 无服务器函数中的运行时凭据
@@ -679,25 +624,29 @@ yarn add -D twenty-sdk
```json filename="package.json"
{
"scripts": {
"auth": "twenty auth login",
"generate": "twenty app generate",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
}
}
```
现在你可以通过 Yarn 运行相同的命令,例如 `yarn app:dev``yarn app:sync` 等。
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
## 故障排除
* 身份验证错误:运行 `yarn auth:login`,并确保你的 API 密钥具有所需权限。
* 无法连接到服务器:请验证 API URL,并确保 Twenty 服务器可达。
* 类型或客户端缺失/过期:运行 `yarn app:generate`,然后运行 `yarn app:dev`。
* Types or client missing/outdated: run `yarn app:generate`.
* 开发模式未同步:确保 `yarn app:dev` 正在运行,并且你的环境不会忽略变更。
Discord 帮助频道:https://discord.com/channels/1130383047699738754/1130386664812982322