i18n - docs translations (#18280)

Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
This commit is contained in:
github-actions[bot]
2026-02-27 23:12:39 +01:00
committed by GitHub
parent c0e6aa1c0b
commit 9f5a8735c9
46 changed files with 619 additions and 617 deletions
@@ -52,25 +52,25 @@ npx create-twenty-app@latest my-app --interactive
من هنا يمكنك:
```bash filename="Terminal"
# Add a new entity to your application (guided)
# أضف كيانًا جديدًا إلى تطبيقك (موجّه)
yarn twenty entity:add
# Watch your application's function logs
# راقب سجلات وظائف تطبيقك
yarn twenty function:logs
# Execute a function by name
# نفّذ وظيفة بالاسم
yarn twenty function:execute -n my-function -p '{"name": "test"}'
# Execute the pre-install function
# نفّذ دالة ما قبل التثبيت
yarn twenty function:execute --preInstall
# Execute the post-install function
# نفّذ دالة ما بعد التثبيت
yarn twenty function:execute --postInstall
# Uninstall the application from the current workspace
# أزل تثبيت التطبيق من مساحة العمل الحالية
yarn twenty app:uninstall
# Display commands' help
# اعرض مساعدة الأوامر
yarn twenty help
```
@@ -83,7 +83,7 @@ yarn twenty help
* ينسخ تطبيقًا أساسيًا مصغّرًا إلى `my-twenty-app/`
* يضيف اعتمادًا محليًا `twenty-sdk` وتهيئة Yarn 4
* ينشئ ملفات ضبط ونصوصًا مرتبطة بـ `twenty` CLI
* Generates core files (application config, default function role, pre-install and post-install functions) plus example files based on the scaffolding mode
* يُنشئ الملفات الأساسية (تهيئة التطبيق، دور الدالة الافتراضي، دالتا ما قبل التثبيت وما بعد التثبيت) بالإضافة إلى ملفات أمثلة استنادًا إلى وضع الإنشاء.
يبدو التطبيق المُنشأ حديثًا باستخدام الوضع الافتراضي `--exhaustive` كما يلي:
@@ -99,30 +99,30 @@ my-twenty-app/
eslint.config.mjs
tsconfig.json
README.md
public/ # Public assets folder (images, fonts, etc.)
public/ # مجلد الأصول العامة (صور، خطوط، إلخ)
src/
├── application-config.ts # Required - main application configuration
├── application-config.ts # مطلوب - إعدادات التطبيق الرئيسية
├── roles/
│ └── default-role.ts # Default role for logic functions
│ └── default-role.ts # الدور الافتراضي للدوال المنطقية
├── objects/
│ └── example-object.ts # Example custom object definition
│ └── example-object.ts # تعريف كائن مخصص — مثال
├── fields/
│ └── example-field.ts # Example standalone field definition
│ └── example-field.ts # تعريف حقل مستقل — مثال
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── pre-install.ts # Pre-install logic function
│ └── post-install.ts # Post-install logic function
│ ├── hello-world.ts # دالة منطقية — مثال
│ ├── pre-install.ts # دالة منطقية لما قبل التثبيت
│ └── post-install.ts # دالة منطقية لما بعد التثبيت
├── front-components/
│ └── hello-world.tsx # Example front component
│ └── hello-world.tsx # مكوّن واجهة أمامية — مثال
├── views/
│ └── example-view.ts # Example saved view definition
│ └── example-view.ts # تعريف عرض محفوظ — مثال
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
│ └── example-navigation-menu-item.ts # رابط تنقّل في الشريط الجانبي — مثال
└── skills/
└── example-skill.ts # Example AI agent skill definition
└── example-skill.ts # تعريف مهارة لوكيل الذكاء الاصطناعي — مثال
```
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`). مع `--interactive`، تختار ملفات الأمثلة التي تريد تضمينها.
مع `--minimal`، سيتم إنشاء الملفات الأساسية فقط (`application-config.ts`، `roles/default-role.ts`، `logic-functions/pre-install.ts`، و`logic-functions/post-install.ts`). مع `--interactive`، تختار ملفات الأمثلة التي تريد تضمينها.
بشكل عام:
@@ -139,18 +139,18 @@ With `--minimal`, only the core files are created (`application-config.ts`, `rol
يكتشف SDK الكيانات عبر تحليل ملفات TypeScript الخاصة بك بحثًا عن استدعاءات **`export default define<Entity>({...})`**. يحتوي كل نوع كيان على دالة مساعدة مقابلة يتم تصديرها من `twenty-sdk`:
| دالة مساعدة | نوع الكيان |
| ---------------------------------- | ----------------------------------------------------- |
| `defineObject()` | تعريفات كائنات مخصصة |
| `defineLogicFunction()` | تعريفات الوظائف المنطقية |
| `definePreInstallLogicFunction()` | Pre-install logic function (runs before installation) |
| `definePostInstallLogicFunction()` | Post-install logic function (runs after installation) |
| `defineFrontComponent()` | Front component definitions |
| `defineRole()` | تعريفات الأدوار |
| `defineField()` | امتدادات الحقول للكائنات الموجودة |
| `defineView()` | تعريفات العروض المحفوظة |
| `defineNavigationMenuItem()` | تعريفات عناصر قائمة التنقل |
| `defineSkill()` | تعريفات مهارات وكيل الذكاء الاصطناعي |
| دالة مساعدة | نوع الكيان |
| ---------------------------------- | ---------------------------------------------- |
| `defineObject()` | تعريفات كائنات مخصصة |
| `defineLogicFunction()` | تعريفات الوظائف المنطقية |
| `definePreInstallLogicFunction()` | دالة منطقية لما قبل التثبيت (تعمل قبل التثبيت) |
| `definePostInstallLogicFunction()` | دالة منطقية لما بعد التثبيت (تعمل بعد التثبيت) |
| `defineFrontComponent()` | Front component definitions |
| `defineRole()` | تعريفات الأدوار |
| `defineField()` | امتدادات الحقول للكائنات الموجودة |
| `defineView()` | تعريفات العروض المحفوظة |
| `defineNavigationMenuItem()` | تعريفات عناصر قائمة التنقل |
| `defineSkill()` | تعريفات مهارات وكيل الذكاء الاصطناعي |
<Note>
**تسمية الملفات مرنة.** يعتمد اكتشاف الكيانات على بنية الشجرة المجردة (AST) — إذ يقوم SDK بفحص ملفات المصدر لديك بحثًا عن النمط `export default define<Entity>({...})`. يمكنك تنظيم ملفاتك ومجلداتك كيفما تشاء. التجميع حسب نوع الكيان (مثلًا، `logic-functions/` و`roles/`) هو مجرد عرف لتنظيم الشيفرة، وليس مطلبًا إلزاميًا.
@@ -220,8 +220,8 @@ yarn twenty auth:status
| `defineApplication()` | تهيئة بيانات التعريف للتطبيق (مطلوب، واحد لكل تطبيق) |
| `defineObject()` | تعريف كائنات مخصصة مع حقول |
| `defineLogicFunction()` | تعريف وظائف منطقية مع معالجات |
| `definePreInstallLogicFunction()` | Define a pre-install logic function (one per app) |
| `definePostInstallLogicFunction()` | Define a post-install logic function (one per app) |
| `definePreInstallLogicFunction()` | تعريف دالة منطقية لما قبل التثبيت (واحدة لكل تطبيق) |
| `definePostInstallLogicFunction()` | تعريف دالة منطقية لما بعد التثبيت (واحدة لكل تطبيق) |
| `defineFrontComponent()` | عرِّف مكوّنات أمامية لواجهة مستخدم مخصّصة |
| `defineRole()` | تهيئة صلاحيات الدور والوصول إلى الكائنات |
| `defineField()` | وسّع الكائنات الموجودة بحقول إضافية |
@@ -327,7 +327,7 @@ export default defineObject({
* **هوية التطبيق**: المعرفات، اسم العرض، والوصف.
* **كيفية تشغيل وظائفه**: الدور الذي تستخدمه للأذونات.
* **متغيرات (اختياري)**: أزواج مفتاح-قيمة تُعرض لوظائفك كمتغيرات بيئة.
* **(Optional) pre-install function**: a logic function that runs before the app is installed.
* **(اختياري) دالة ما قبل التثبيت**: دالة منطقية تعمل قبل تثبيت التطبيق.
* **(Optional) post-install function**: a logic function that runs after the app is installed.
Use `defineApplication()` to define your application configuration:
@@ -359,7 +359,7 @@ export default defineApplication({
* حقول `universalIdentifier` هي معرّفات حتمية تخصك؛ أنشئها مرة واحدة واحتفظ بها ثابتة عبر عمليات المزامنة.
* `applicationVariables` تصبح متغيرات بيئة لوظائفك (على سبيل المثال، `DEFAULT_RECIPIENT_NAME` متاح كـ `process.env.DEFAULT_RECIPIENT_NAME`).
* `defaultRoleUniversalIdentifier` يجب أن يطابق ملف الدور (انظر أدناه).
* Pre-install and post-install functions are automatically detected during the manifest build. See [Pre-install functions](#pre-install-functions) and [Post-install functions](#post-install-functions).
* يتم اكتشاف دوال ما قبل التثبيت وما بعد التثبيت تلقائيًا أثناء إنشاء ملف البيان. راجع [دوال ما قبل التثبيت](#pre-install-functions) و[دوال ما بعد التثبيت](#post-install-functions).
#### الأدوار والصلاحيات
@@ -498,11 +498,11 @@ export default defineLogicFunction({
* المصفوفة `triggers` اختيارية. يمكن استخدام الوظائف بدون مشغلات كوظائف مساعدة تُستدعى بواسطة وظائف أخرى.
* يمكنك مزج أنواع متعددة من المشغلات في وظيفة واحدة.
### Pre-install functions
### دوال ما قبل التثبيت
A pre-install function is a logic function that runs automatically before your app is installed on a workspace. This is useful for validation tasks, prerequisite checks, or preparing workspace state before the main installation proceeds.
دالة ما قبل التثبيت هي دالة منطقية تعمل تلقائيًا قبل تثبيت تطبيقك على مساحة عمل. يفيد ذلك في مهام التحقق، وفحص المتطلبات المسبقة، أو تجهيز حالة مساحة العمل قبل متابعة التثبيت الرئيسي.
When you scaffold a new app with `create-twenty-app`, a pre-install function is generated for you at `src/logic-functions/pre-install.ts`:
عند إنشاء هيكل تطبيق جديد باستخدام `create-twenty-app`، يتم إنشاء دالة ما قبل التثبيت لك في `src/logic-functions/pre-install.ts`:
```typescript
// src/logic-functions/pre-install.ts
@@ -521,7 +521,7 @@ export default definePreInstallLogicFunction({
});
```
You can also manually execute the pre-install function at any time using the CLI:
يمكنك أيضًا تنفيذ دالة ما قبل التثبيت يدويًا في أي وقت باستخدام CLI:
```bash filename="Terminal"
yarn twenty function:execute --preInstall
@@ -529,12 +529,12 @@ yarn twenty function:execute --preInstall
النقاط الرئيسية:
* Pre-install functions use `definePreInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one pre-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `preInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* The default timeout is set to 300 seconds (5 minutes) to allow for longer preparation tasks.
* Pre-install functions do not need triggers — they are invoked by the platform before installation or manually via `function:execute --preInstall`.
* تستخدم دوال ما قبل التثبيت `definePreInstallLogicFunction()` — وهو إصدار متخصص يستبعد إعدادات المُشغِّل (`cronTriggerSettings` و`databaseEventTriggerSettings` و`httpRouteTriggerSettings` و`isTool`).
* يتلقى المُعالج `InstallLogicFunctionPayload` يحوي `{ previousVersion: string }` — إصدار التطبيق الذي كان مُثبّتًا سابقًا (أو سلسلة فارغة للتثبيتات الجديدة).
* يُسمح بدالة ما قبل التثبيت واحدة فقط لكل تطبيق. سيُنتج إنشاء ملف البيان خطأً إذا تم اكتشاف أكثر من واحدة.
* يتم تعيين `universalIdentifier` للدالة تلقائيًا كـ `preInstallLogicFunctionUniversalIdentifier` في بيان التطبيق أثناء الإنشاء — لست بحاجة إلى الإشارة إليه في `defineApplication()`.
* تم ضبط المهلة الافتراضية على 300 ثانية (5 دقائق) للسماح بمهام التحضير الأطول.
* لا تحتاج دوال ما قبل التثبيت إلى مُشغِّلات — إذ يستدعيها النظام الأساسي قبل التثبيت أو يدويًا عبر `function:execute --preInstall`.
### Post-install functions
@@ -567,10 +567,10 @@ yarn twenty function:execute --postInstall
النقاط الرئيسية:
* Post-install functions use `definePostInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one post-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `postInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* تستخدم دوال ما بعد التثبيت `definePostInstallLogicFunction()` — وهو إصدار متخصص يستبعد إعدادات المُشغِّل (`cronTriggerSettings` و`databaseEventTriggerSettings` و`httpRouteTriggerSettings` و`isTool`).
* يتلقى المُعالج `InstallLogicFunctionPayload` يحوي `{ previousVersion: string }` — إصدار التطبيق الذي كان مُثبّتًا سابقًا (أو سلسلة فارغة للتثبيتات الجديدة).
* يُسمح بدالة ما بعد التثبيت واحدة فقط لكل تطبيق. سيُنتج إنشاء ملف البيان خطأً إذا تم اكتشاف أكثر من واحدة.
* يتم تعيين `universalIdentifier` للدالة تلقائيًا كـ `postInstallLogicFunctionUniversalIdentifier` في بيان التطبيق أثناء الإنشاء — لست بحاجة إلى الإشارة إليه في `defineApplication()`.
* تم تعيين مهلة افتراضية إلى 300 ثانية (5 دقائق) للسماح بمهام الإعداد الأطول مثل تهيئة البيانات.
* لا تحتاج دوال ما بعد التثبيت إلى مُشغِّلات — حيث يستدعيها النظام الأساسي أثناء التثبيت أو يدويًا عبر `function:execute --postInstall`.
@@ -6,9 +6,9 @@ Tento dokument popisuje osvědčené postupy, které byste měli dodržovat při
## Správa stavu
React and Jotai handle state management in the codebase.
React a Jotai zajišťují správu stavu v kódu.
### Use Jotai atoms to store state
### Použijte atomy Jotai k ukládání stavu
Je dobrým zvykem vytvořit tolik atomů, kolik potřebujete ke správě stavu.
@@ -45,7 +45,7 @@ export const MyComponent = () => {
Vyhněte se používání `useRef` k ukládání stavu.
If you want to store state, you should use `useState` or Jotai atoms with `useAtomState`.
Pokud chcete ukládat stav, měli byste použít `useState` nebo atomy Jotai s `useAtomState`.
Podívejte se, jak spravovat překreslení, pokud máte pocit, že potřebujete `useRef`, abyste zabránili některým překreslením.
@@ -82,8 +82,8 @@ If you feel like you need to add a `useEffect` in your root component, you shoul
Stejný postup můžete aplikovat na logiku získávání dat pomocí Apollo hooks.
```tsx
// ❌ Bad, will cause re-renders even if data is not changing,
// because useEffect needs to be re-evaluated
// ❌ Špatně, způsobí překreslení, i když se data nemění,
// protože useEffect je třeba znovu vyhodnotit
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
const [someDependency] = useAtomState(someDependencyState);
@@ -103,8 +103,8 @@ export const App = () => (
```
```tsx
// ✅ Good, will not cause re-renders if data is not changing,
// because useEffect is re-evaluated in another sibling component
// ✅ Dobře, nezpůsobí překreslení, pokud se data nemění,
// protože useEffect je znovu vyhodnocen v jiné sourozenecké komponentě
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
@@ -132,9 +132,9 @@ export const App = () => (
);
```
### Use atom family states and selectors
### Použijte rodiny atomů a selektory
Atom family states and selectors are a great way to avoid re-renders.
Rodiny atomů a selektory jsou skvělým způsobem, jak se vyhnout překreslování.
Jsou užitečné, když potřebujete uložit seznam položek.
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/cs/developers/contribute/capabilities/front
### Správa stavu
[Jotai](https://jotai.org/) handles state management.
[Jotai](https://jotai.org/) zajišťuje správu stavu.
Podívejte se na [osvědčené postupy](/l/cs/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) pro více informací o správě stavu.
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
}
```
Internally, the currently selected scope is stored in a Jotai atom that is shared across the application :
Interně je aktuálně vybraný rozsah uložen v Jotai atomu, který je sdílen napříč aplikací :
```tsx
export const currentHotkeyScopeState = createState<HotkeyScope>({
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
});
```
But this atom should never be handled manually ! Ukážeme si, jak jej používat v příští sekci.
Ale tento atom by se nikdy neměl spravovat ručně ! Ukážeme si, jak jej používat v příští sekci.
## Jak to funguje interně?
Vytvořili jsme tenkou vrstvu nad [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro), která je výkonnější a vyhýbá se zbytečným překreslením.
We also create a Jotai atom to handle the hotkey scope state and make it available everywhere in the application.
Také vytváříme Jotai atom, abychom mohli řídit stav rozsahu klávesových zkratek a učinit jej dostupným kdekoli v aplikaci.
@@ -52,25 +52,25 @@ npx create-twenty-app@latest my-app --interactive
Odtud můžete:
```bash filename="Terminal"
# Add a new entity to your application (guided)
# Přidejte do vaší aplikace novou entitu (s průvodcem)
yarn twenty entity:add
# Watch your application's function logs
# Sledujte logy funkcí vaší aplikace
yarn twenty function:logs
# Execute a function by name
# Spusťte funkci podle názvu
yarn twenty function:execute -n my-function -p '{"name": "test"}'
# Execute the pre-install function
# Spusťte předinstalační funkci
yarn twenty function:execute --preInstall
# Execute the post-install function
# Spusťte postinstalační funkci
yarn twenty function:execute --postInstall
# Uninstall the application from the current workspace
# Odinstalujte aplikaci z aktuálního pracovního prostoru
yarn twenty app:uninstall
# Display commands' help
# Zobrazte nápovědu k příkazům
yarn twenty help
```
@@ -83,7 +83,7 @@ Když spustíte `npx create-twenty-app@latest my-twenty-app`, scaffolder:
* Zkopíruje minimální základní aplikaci do `my-twenty-app/`
* Přidá lokální závislost `twenty-sdk` a konfiguraci pro Yarn 4
* Vytvoří konfigurační soubory a skripty napojené na `twenty` CLI
* Generates core files (application config, default function role, pre-install and post-install functions) plus example files based on the scaffolding mode
* Vygeneruje základní soubory (konfigurace aplikace, výchozí role funkcí, předinstalační a postinstalační funkce) a k nim ukázkové soubory podle zvoleného režimu generování kostry
Čerstvě vygenerovaná aplikace s výchozím režimem `--exhaustive` vypadá takto:
@@ -99,30 +99,30 @@ my-twenty-app/
eslint.config.mjs
tsconfig.json
README.md
public/ # Public assets folder (images, fonts, etc.)
public/ # Složka s veřejnými prostředky (obrázky, písma apod.)
src/
├── application-config.ts # Required - main application configuration
├── application-config.ts # Povinné hlavní konfigurace aplikace
├── roles/
│ └── default-role.ts # Default role for logic functions
│ └── default-role.ts # Výchozí role pro logic funkce
├── objects/
│ └── example-object.ts # Example custom object definition
│ └── example-object.ts # Ukázková definice vlastního objektu
├── fields/
│ └── example-field.ts # Example standalone field definition
│ └── example-field.ts # Ukázková samostatná definice pole
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── pre-install.ts # Pre-install logic function
│ └── post-install.ts # Post-install logic function
│ ├── hello-world.ts # Ukázková logic funkce
│ ├── pre-install.ts # Předinstalační logic funkce
│ └── post-install.ts # Postinstalační logic funkce
├── front-components/
│ └── hello-world.tsx # Example front component
│ └── hello-world.tsx # Ukázková front-endová komponenta
├── views/
│ └── example-view.ts # Example saved view definition
│ └── example-view.ts # Ukázková definice uloženého zobrazení
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
│ └── example-navigation-menu-item.ts # Ukázkový odkaz postranní navigace
└── skills/
└── example-skill.ts # Example AI agent skill definition
└── example-skill.ts # Ukázková definice dovednosti agenta AI
```
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`). S volbou `--interactive` si vyberete, které ukázkové soubory chcete zahrnout.
S volbou `--minimal` se vytvoří pouze základní soubory (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` a `logic-functions/post-install.ts`). S volbou `--interactive` si vyberete, které ukázkové soubory chcete zahrnout.
V kostce:
@@ -139,18 +139,18 @@ V kostce:
SDK detekuje entity analýzou vašich souborů TypeScript a hledá volání **`export default define<Entity>({...})`**. Každý typ entity má odpovídající pomocnou funkci exportovanou z `twenty-sdk`:
| Pomocná funkce | Typ entity |
| ---------------------------------- | ----------------------------------------------------- |
| `defineObject()` | Definice vlastních objektů |
| `defineLogicFunction()` | Definice logických funkcí |
| `definePreInstallLogicFunction()` | Pre-install logic function (runs before installation) |
| `definePostInstallLogicFunction()` | Post-install logic function (runs after installation) |
| `defineFrontComponent()` | Definice frontendových komponent |
| `defineRole()` | Definice rolí |
| `defineField()` | Rozšíření polí u existujících objektů |
| `defineView()` | Definice uložených zobrazení |
| `defineNavigationMenuItem()` | Definice položek navigační nabídky |
| `defineSkill()` | Definice dovedností agenta AI |
| Pomocná funkce | Typ entity |
| ---------------------------------- | --------------------------------------------------------- |
| `defineObject()` | Definice vlastních objektů |
| `defineLogicFunction()` | Definice logických funkcí |
| `definePreInstallLogicFunction()` | Předinstalační logic funkce (spouští se před instalací) |
| `definePostInstallLogicFunction()` | Postinstalační logic funkce (spouští se po instalaci) |
| `defineFrontComponent()` | Definice frontendových komponent |
| `defineRole()` | Definice rolí |
| `defineField()` | Rozšíření polí u existujících objektů |
| `defineView()` | Definice uložených zobrazení |
| `defineNavigationMenuItem()` | Definice položek navigační nabídky |
| `defineSkill()` | Definice dovedností agenta AI |
<Note>
**Pojmenování souborů je flexibilní.** Detekce entit je založená na AST — SDK prochází vaše zdrojové soubory a hledá vzor `export default define<Entity>({...})`. Soubory a složky můžete organizovat, jak chcete. Seskupování podle typu entity (např. `logic-functions/`, `roles/`) je pouze konvence pro organizaci kódu, nikoli požadavek.
@@ -220,8 +220,8 @@ SDK poskytuje pomocné funkce pro definování entit vaší aplikace. Jak je pop
| `defineApplication()` | Nakonfigurujte metadata aplikace (povinné, jedno na aplikaci) |
| `defineObject()` | Definice vlastních objektů s poli |
| `defineLogicFunction()` | Definice logických funkcí s obslužnými funkcemi |
| `definePreInstallLogicFunction()` | Define a pre-install logic function (one per app) |
| `definePostInstallLogicFunction()` | Define a post-install logic function (one per app) |
| `definePreInstallLogicFunction()` | Definujte předinstalační logickou funkci (jedna na aplikaci) |
| `definePostInstallLogicFunction()` | Definujte postinstalační logickou funkci (jedna na aplikaci) |
| `defineFrontComponent()` | Definujte frontendové komponenty pro vlastní uživatelské rozhraní |
| `defineRole()` | Konfigurace oprávnění rolí a přístupu k objektům |
| `defineField()` | Rozšiřte existující objekty o další pole |
@@ -327,7 +327,7 @@ Každá aplikace má jeden soubor `application-config.ts`, který popisuje:
* **Identitu aplikace**: identifikátory, zobrazovaný název a popis.
* **Jak běží její funkce**: kterou roli používají pro oprávnění.
* **(Volitelné) proměnné**: dvojice klíč–hodnota zpřístupněné vašim funkcím jako proměnné prostředí.
* **(Optional) pre-install function**: a logic function that runs before the app is installed.
* **(Volitelná) předinstalační funkce**: logic funkce, která se spouští před instalací aplikace.
* **(Volitelná) postinstalační funkce**: logická funkce, která se spouští po instalaci aplikace.
Use `defineApplication()` to define your application configuration:
@@ -359,7 +359,7 @@ Poznámky:
* Pole `universalIdentifier` jsou deterministická ID, která vlastníte; vygenerujte je jednou a udržujte je stabilní napříč synchronizacemi.
* `applicationVariables` se stanou proměnnými prostředí pro vaše funkce (například `DEFAULT_RECIPIENT_NAME` je dostupné jako `process.env.DEFAULT_RECIPIENT_NAME`).
* `defaultRoleUniversalIdentifier` se musí shodovat se souborem role (viz níže).
* Pre-install and post-install functions are automatically detected during the manifest build. See [Pre-install functions](#pre-install-functions) and [Post-install functions](#post-install-functions).
* Předinstalační a postinstalační funkce jsou při sestavování manifestu automaticky detekovány. Viz [Předinstalační funkce](#pre-install-functions) a [Postinstalační funkce](#post-install-functions).
#### Role a oprávnění
@@ -498,11 +498,11 @@ Poznámky:
* Pole `triggers` je volitelné. Funkce bez spouštěčů lze použít jako pomocné funkce volané jinými funkcemi.
* V jedné funkci můžete kombinovat více typů spouštěčů.
### Pre-install functions
### Předinstalační funkce
A pre-install function is a logic function that runs automatically before your app is installed on a workspace. This is useful for validation tasks, prerequisite checks, or preparing workspace state before the main installation proceeds.
Předinstalační funkce je logic funkce, která se automaticky spouští před instalací vaší aplikace v pracovním prostoru. To je užitečné pro validační úlohy, kontrolu předpokladů nebo přípravu stavu pracovního prostoru před zahájením hlavní instalace.
When you scaffold a new app with `create-twenty-app`, a pre-install function is generated for you at `src/logic-functions/pre-install.ts`:
Když vygenerujete kostru nové aplikace pomocí `create-twenty-app`, vytvoří se pro vás předinstalační funkce v `src/logic-functions/pre-install.ts`:
```typescript
// src/logic-functions/pre-install.ts
@@ -521,7 +521,7 @@ export default definePreInstallLogicFunction({
});
```
You can also manually execute the pre-install function at any time using the CLI:
Předinstalační funkci můžete také kdykoli spustit ručně pomocí CLI:
```bash filename="Terminal"
yarn twenty function:execute --preInstall
@@ -529,12 +529,12 @@ yarn twenty function:execute --preInstall
Hlavní body:
* Pre-install functions use `definePreInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one pre-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `preInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* The default timeout is set to 300 seconds (5 minutes) to allow for longer preparation tasks.
* Pre-install functions do not need triggers — they are invoked by the platform before installation or manually via `function:execute --preInstall`.
* Předinstalační funkce používají `definePreInstallLogicFunction()` — specializovanou variantu, která vynechává nastavení spouštěčů (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* Obslužná funkce (handler) obdrží `InstallLogicFunctionPayload` s `{ previousVersion: string }` — verzi aplikace, která byla dříve nainstalována (nebo prázdný řetězec při čisté instalaci).
* Na jednu aplikaci je povolena pouze jedna předinstalační funkce. Sestavení manifestu skončí chybou, pokud je zjištěna více než jedna.
* Identifikátor `universalIdentifier` funkce se během sestavení automaticky nastaví v manifestu aplikace jako `preInstallLogicFunctionUniversalIdentifier` — není potřeba jej uvádět v `defineApplication()`.
* Výchozí časový limit je nastaven na 300 sekund (5 minut), aby umožnil delší přípravné úlohy.
* Předinstalační funkce nepotřebují spouštěče — platforma je vyvolává před instalací nebo je lze spustit ručně pomocí `function:execute --preInstall`.
### Postinstalační funkce
@@ -567,10 +567,10 @@ yarn twenty function:execute --postInstall
Hlavní body:
* Post-install functions use `definePostInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one post-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `postInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* Postinstalační funkce používají `definePostInstallLogicFunction()` — specializovanou variantu, která vynechává nastavení spouštěčů (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* Obslužná funkce (handler) obdrží `InstallLogicFunctionPayload` s `{ previousVersion: string }` — verzi aplikace, která byla dříve nainstalována (nebo prázdný řetězec při čisté instalaci).
* Na jednu aplikaci je povolena pouze jedna postinstalační funkce. Sestavení manifestu skončí chybou, pokud je zjištěna více než jedna.
* Identifikátor `universalIdentifier` funkce se během sestavení automaticky nastaví v manifestu aplikace jako `postInstallLogicFunctionUniversalIdentifier` — není potřeba jej uvádět v `defineApplication()`.
* Výchozí časový limit je nastaven na 300 sekund (5 minut), aby umožnil delší úlohy nastavení, jako je naplnění daty.
* Postinstalační funkce nepotřebují spouštěče — jsou spouštěny platformou během instalace nebo ručně pomocí `function:execute --postInstall`.
@@ -23,10 +23,10 @@ export const MyComponent = () => {
<Select
className
disabled={false}
label="Select an option"
label="Vyberte možnost"
options={[
{ value: 'option1', label: 'Option A', Icon: IconTwentyStar },
{ value: 'option2', label: 'Option B', Icon: IconTwentyStar },
{ value: 'option1', label: 'Možnost A', Icon: IconTwentyStar },
{ value: 'option2', label: 'Možnost B', Icon: IconTwentyStar },
]}
value="option1"
/>
@@ -20,27 +20,27 @@ import { TextInput } from "@/ui/input/components/TextInput";
export const MyComponent = () => {
const handleChange = (text) => {
console.log("Input changed:", text);
console.log("Změněn vstup:", text);
};
const handleKeyDown = (event) => {
console.log("Key pressed:", event.key);
console.log("Stisknutá klávesa:", event.key);
};
return (
<TextInput
className
label="Username"
label="Uživatelské jméno"
onChange={handleChange}
fullWidth={false}
disableHotkeys={false}
error="Invalid username"
error="Neplatné uživatelské jméno"
onKeyDown={handleKeyDown}
RightIcon={null}
/>
);
};
},{
```
@@ -83,13 +83,13 @@ import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
export const MyComponent = () => {
return (
<AutosizeTextInput
onValidate={() => console.log("onValidate function fired")}
onValidate={() => console.log("Funkce onValidate spuštěna")}
minRows={1}
placeholder="Write a comment"
onFocus={() => console.log("onFocus function fired")}
placeholder="Napište komentář"
onFocus={() => console.log("Funkce onFocus spuštěna")}
variant="icon"
buttonTitle
value="Task: "
value="Úkol: "
/>
);
};
@@ -6,9 +6,9 @@ Dieses Dokument beschreibt die besten Praktiken, die Sie beim Arbeiten am Fronte
## Zustandsverwaltung
React and Jotai handle state management in the codebase.
React und Jotai übernehmen die Zustandsverwaltung im Code.
### Use Jotai atoms to store state
### Verwenden Sie Jotai-Atome, um den Zustand zu speichern
Es ist eine gute Praxis, so viele Atome zu erstellen, wie Sie benötigen, um Ihren Zustand zu speichern.
@@ -45,7 +45,7 @@ export const MyComponent = () => {
Vermeiden Sie die Verwendung von `useRef`, um den Zustand zu speichern.
If you want to store state, you should use `useState` or Jotai atoms with `useAtomState`.
Wenn Sie den Zustand speichern möchten, sollten Sie `useState` oder Jotai-Atome mit `useAtomState` verwenden.
Sehen Sie sich [an, wie Re-Renderings verwaltet werden können](#managing-re-renders), falls Sie das Gefühl haben, dass Sie `useRef` benötigen, um einige Re-Renderings zu verhindern.
@@ -82,8 +82,8 @@ If you feel like you need to add a `useEffect` in your root component, you shoul
Dasselbe können Sie auch für die Datenabruflogik mit Apollo-Hooks anwenden.
```tsx
// ❌ Bad, will cause re-renders even if data is not changing,
// because useEffect needs to be re-evaluated
// ❌ Schlecht, verursacht Re-Renders, auch wenn sich die Daten nicht ändern,
// weil useEffect neu ausgewertet werden muss
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
const [someDependency] = useAtomState(someDependencyState);
@@ -103,8 +103,8 @@ export const App = () => (
```
```tsx
// ✅ Good, will not cause re-renders if data is not changing,
// because useEffect is re-evaluated in another sibling component
// ✅ Gut, verursacht keine Re-Renders, wenn sich die Daten nicht ändern,
// weil useEffect in einer anderen Geschwisterkomponente neu ausgewertet wird
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
@@ -132,9 +132,9 @@ export const App = () => (
);
```
### Use atom family states and selectors
### Verwenden Sie Atom-Familienzustände und Selektoren
Atom family states and selectors are a great way to avoid re-renders.
Atom-Familienzustände und Selektoren sind eine großartige Möglichkeit, Re-Renders zu vermeiden.
Sie sind nützlich, wenn Sie eine Liste von Elementen speichern müssen.
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/de/developers/contribute/capabilities/front
### Zustandsverwaltung
[Jotai](https://jotai.org/) handles state management.
[Jotai](https://jotai.org/) übernimmt die Zustandsverwaltung.
Siehe [Best Practices](/l/de/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) für mehr Informationen zur Zustandsverwaltung.
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
}
```
Internally, the currently selected scope is stored in a Jotai atom that is shared across the application :
Intern wird der aktuell ausgewählte Bereich in einem Jotai-Atom gespeichert, das in der gesamten Anwendung geteilt wird:
```tsx
export const currentHotkeyScopeState = createState<HotkeyScope>({
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
});
```
But this atom should never be handled manually ! Wir werden im nächsten Abschnitt sehen, wie man es verwendet.
Aber dieses Atom sollte niemals manuell bearbeitet werden! Wir werden im nächsten Abschnitt sehen, wie man es verwendet.
## Wie funktioniert es intern?
Wir haben eine dünne Schicht über [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) erstellt, die es leistungsfähiger macht und unnötige Neu-Renderings vermeidet.
We also create a Jotai atom to handle the hotkey scope state and make it available everywhere in the application.
Wir erstellen außerdem ein Jotai-Atom, um den Zustand des Tastenkombinationsbereichs zu verwalten und in der gesamten Anwendung verfügbar zu machen.
@@ -52,26 +52,26 @@ npx create-twenty-app@latest my-app --interactive
Von hier aus können Sie:
```bash filename="Terminal"
# Add a new entity to your application (guided)
# Eine neue Entität zu Ihrer Anwendung hinzufügen (geführt)
yarn twenty entity:add
# Watch your application's function logs
# Die Funktionsprotokolle Ihrer Anwendung überwachen
yarn twenty function:logs
# Execute a function by name
# Eine Funktion anhand ihres Namens ausführen
yarn twenty function:execute -n my-function -p '{"name": "test"}'
# Execute the pre-install function
# Die Pre-Installationsfunktion ausführen
yarn twenty function:execute --preInstall
# Execute the post-install function
# Die Post-Installationsfunktion ausführen
yarn twenty function:execute --postInstall
# Uninstall the application from the current workspace
# Die Anwendung aus dem aktuellen Arbeitsbereich deinstallieren
yarn twenty app:uninstall
# Display commands' help
yarn twenty help
# Hilfe zu Befehlen anzeigen
yarn twenty help},{
```
Siehe auch: die CLI-Referenzseiten für [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) und [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -83,7 +83,7 @@ Wenn Sie `npx create-twenty-app@latest my-twenty-app` ausführen, erledigt der S
* Kopiert eine minimale Basisanwendung nach `my-twenty-app/`
* Fügt eine lokale `twenty-sdk`-Abhängigkeit und die Yarn-4-Konfiguration hinzu
* Erstellt Konfigurationsdateien und Skripte, die an die `twenty`-CLI angebunden sind
* Generates core files (application config, default function role, pre-install and post-install functions) plus example files based on the scaffolding mode
* Erzeugt Kerndateien (Anwendungskonfiguration, Standardrolle für Logikfunktionen, Pre-Installations- und Post-Installationsfunktionen) sowie Beispieldateien entsprechend dem Scaffolding-Modus
Eine frisch erstellte App mit dem Standardmodus `--exhaustive` sieht so aus:
@@ -99,30 +99,30 @@ my-twenty-app/
eslint.config.mjs
tsconfig.json
README.md
public/ # Public assets folder (images, fonts, etc.)
public/ # Ordner für öffentliche Assets (Bilder, Schriftarten usw.)
src/
├── application-config.ts # Required - main application configuration
├── application-config.ts # Erforderlich - Hauptkonfiguration der Anwendung
├── roles/
│ └── default-role.ts # Default role for logic functions
│ └── default-role.ts # Standardrolle für Logikfunktionen
├── objects/
│ └── example-object.ts # Example custom object definition
│ └── example-object.ts # Beispiel für eine benutzerdefinierte Objektdefinition
├── fields/
│ └── example-field.ts # Example standalone field definition
│ └── example-field.ts # Beispiel für eine eigenständige Felddefinition
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── pre-install.ts # Pre-install logic function
│ └── post-install.ts # Post-install logic function
│ ├── hello-world.ts # Beispiel für eine Logikfunktion
│ ├── pre-install.ts # Pre-Installations-Logikfunktion
│ └── post-install.ts # Post-Installations-Logikfunktion
├── front-components/
│ └── hello-world.tsx # Example front component
│ └── hello-world.tsx # Beispiel für eine Frontend-Komponente
├── views/
│ └── example-view.ts # Example saved view definition
│ └── example-view.ts # Beispiel für eine gespeicherte View-Definition
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
│ └── example-navigation-menu-item.ts # Beispiel für einen Navigationslink in der Seitenleiste
└── skills/
└── example-skill.ts # Example AI agent skill definition
└── example-skill.ts # Beispiel für eine Skill-Definition eines KI-Agenten
```
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`). Mit `--interactive` wählst du aus, welche Beispieldateien enthalten sein sollen.
Mit `--minimal` werden nur die Kerndateien erstellt (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` und `logic-functions/post-install.ts`). Mit `--interactive` wählst du aus, welche Beispieldateien enthalten sein sollen.
Auf hoher Ebene:
@@ -139,18 +139,18 @@ Auf hoher Ebene:
Das SDK erkennt Entitäten, indem es Ihre TypeScript-Dateien nach Aufrufen von **`export default define<Entity>({...})`** parst. Für jeden Entitätstyp gibt es eine entsprechende Hilfsfunktion, die aus `twenty-sdk` exportiert wird:
| Hilfsfunktion | Entitätstyp |
| ---------------------------------- | ----------------------------------------------------- |
| `defineObject()` | Benutzerdefinierte Objektdefinitionen |
| `defineLogicFunction()` | Definitionen von Logikfunktionen |
| `definePreInstallLogicFunction()` | Pre-install logic function (runs before installation) |
| `definePostInstallLogicFunction()` | Post-install logic function (runs after installation) |
| `defineFrontComponent()` | Definitionen von Frontend-Komponenten |
| `defineRole()` | Rollendefinitionen |
| `defineField()` | Felderweiterungen für bestehende Objekte |
| `defineView()` | Gespeicherte View-Definitionen |
| `defineNavigationMenuItem()` | Definitionen von Navigationsmenüeinträgen |
| `defineSkill()` | Skill-Definitionen für KI-Agenten |
| Hilfsfunktion | Entitätstyp |
| ---------------------------------- | ------------------------------------------------------------------------ |
| `defineObject()` | Benutzerdefinierte Objektdefinitionen |
| `defineLogicFunction()` | Definitionen von Logikfunktionen |
| `definePreInstallLogicFunction()` | Pre-Installations-Logikfunktion (wird vor der Installation ausgeführt) |
| `definePostInstallLogicFunction()` | Post-Installations-Logikfunktion (wird nach der Installation ausgeführt) |
| `defineFrontComponent()` | Definitionen von Frontend-Komponenten |
| `defineRole()` | Rollendefinitionen |
| `defineField()` | Felderweiterungen für bestehende Objekte |
| `defineView()` | Gespeicherte View-Definitionen |
| `defineNavigationMenuItem()` | Definitionen von Navigationsmenüeinträgen |
| `defineSkill()` | Skill-Definitionen für KI-Agenten |
<Note>
**Dateibenennung ist flexibel.** Die Entitätserkennung ist AST-basiert — das SDK durchsucht Ihre Quelldateien nach dem Muster `export default define<Entity>({...})`. Sie können Ihre Dateien und Ordner nach Belieben organisieren. Die Gruppierung nach Entitätstyp (z. B. `logic-functions/`, `roles/`) ist lediglich eine Konvention zur Codeorganisation, keine Voraussetzung.
@@ -215,19 +215,19 @@ Das twenty-sdk stellt typisierte Bausteine und Hilfsfunktionen bereit, die Sie i
Das SDK stellt Hilfsfunktionen bereit, um die Entitäten Ihrer App zu definieren. Wie in [Entitätserkennung](#entity-detection) beschrieben, müssen Sie `export default define<Entity>({...})` verwenden, damit Ihre Entitäten erkannt werden:
| Funktion | Zweck |
| ---------------------------------- | -------------------------------------------------------------- |
| `defineApplication()` | Anwendungsmetadaten konfigurieren (erforderlich, eine pro App) |
| `defineObject()` | Benutzerdefinierte Objekte mit Feldern definieren |
| `defineLogicFunction()` | Logikfunktionen mit Handlern definieren |
| `definePreInstallLogicFunction()` | Define a pre-install logic function (one per app) |
| `definePostInstallLogicFunction()` | Define a post-install logic function (one per app) |
| `defineFrontComponent()` | Frontend-Komponenten für benutzerdefinierte UI definieren |
| `defineRole()` | Rollenberechtigungen und Objektzugriff konfigurieren |
| `defineField()` | Bestehende Objekte mit zusätzlichen Feldern erweitern |
| `defineView()` | Gespeicherte Views für Objekte definieren |
| `defineNavigationMenuItem()` | Seitenleisten-Navigationslinks definieren |
| `defineSkill()` | Definieren Sie Skills für KI-Agenten |
| Funktion | Zweck |
| ---------------------------------- | --------------------------------------------------------------- |
| `defineApplication()` | Anwendungsmetadaten konfigurieren (erforderlich, eine pro App) |
| `defineObject()` | Benutzerdefinierte Objekte mit Feldern definieren |
| `defineLogicFunction()` | Logikfunktionen mit Handlern definieren |
| `definePreInstallLogicFunction()` | Eine Pre-Installations-Logikfunktion definieren (eine pro App) |
| `definePostInstallLogicFunction()` | Eine Post-Installations-Logikfunktion definieren (eine pro App) |
| `defineFrontComponent()` | Frontend-Komponenten für benutzerdefinierte UI definieren |
| `defineRole()` | Rollenberechtigungen und Objektzugriff konfigurieren |
| `defineField()` | Bestehende Objekte mit zusätzlichen Feldern erweitern |
| `defineView()` | Gespeicherte Views für Objekte definieren |
| `defineNavigationMenuItem()` | Seitenleisten-Navigationslinks definieren |
| `defineSkill()` | Definieren Sie Skills für KI-Agenten |
Diese Funktionen validieren Ihre Konfiguration zur Build-Zeit und bieten IDE-Autovervollständigung sowie Typsicherheit.
@@ -327,7 +327,7 @@ Jede App hat eine einzelne Datei `application-config.ts`, die Folgendes beschrei
* **Was die App ist**: Bezeichner, Anzeigename und Beschreibung.
* **Wie ihre Funktionen ausgeführt werden**: welche Rolle sie für Berechtigungen verwenden.
* **(Optional) Variablen**: SchlüsselWert-Paare, die Ihren Funktionen als Umgebungsvariablen zur Verfügung gestellt werden.
* **(Optional) pre-install function**: a logic function that runs before the app is installed.
* **(Optional) Pre-Installationsfunktion**: eine Logikfunktion, die vor der Installation der App ausgeführt wird.
* **(Optional) Post-Installationsfunktion**: eine Logikfunktion, die nach der Installation der App ausgeführt wird.
Verwenden Sie `defineApplication()`, um Ihre Anwendungskonfiguration zu definieren:
@@ -359,7 +359,7 @@ Notizen:
* `universalIdentifier`-Felder sind deterministische IDs, die Sie besitzen; generieren Sie sie einmal und halten Sie sie über Synchronisierungen hinweg stabil.
* `applicationVariables` werden zu Umgebungsvariablen für Ihre Funktionen (zum Beispiel ist `DEFAULT_RECIPIENT_NAME` als `process.env.DEFAULT_RECIPIENT_NAME` verfügbar).
* `defaultRoleUniversalIdentifier` muss mit der Rollendatei übereinstimmen (siehe unten).
* Pre-install and post-install functions are automatically detected during the manifest build. See [Pre-install functions](#pre-install-functions) and [Post-install functions](#post-install-functions).
* Pre-Installations- und Post-Installationsfunktionen werden während des Manifest-Builds automatisch erkannt. Siehe [Pre-Installationsfunktionen](#pre-install-functions) und [Post-Installationsfunktionen](#post-install-functions).
#### Rollen und Berechtigungen
@@ -498,11 +498,11 @@ Notizen:
* Das Array `triggers` ist optional. Funktionen ohne Trigger können als von anderen Funktionen aufgerufene Utility-Funktionen verwendet werden.
* Sie können mehrere Trigger-Typen in einer Funktion kombinieren.
### Pre-install functions
### Pre-Installationsfunktionen
A pre-install function is a logic function that runs automatically before your app is installed on a workspace. This is useful for validation tasks, prerequisite checks, or preparing workspace state before the main installation proceeds.
Eine Pre-Installationsfunktion ist eine Logikfunktion, die automatisch ausgeführt wird, bevor deine App in einem Arbeitsbereich installiert wird. Dies ist nützlich für Validierungsaufgaben, Überprüfungen von Voraussetzungen oder die Vorbereitung des Status des Arbeitsbereichs, bevor die Hauptinstallation fortgesetzt wird.
When you scaffold a new app with `create-twenty-app`, a pre-install function is generated for you at `src/logic-functions/pre-install.ts`:
Wenn du mit `create-twenty-app` eine neue App erstellst, wird für dich eine Pre-Installationsfunktion unter `src/logic-functions/pre-install.ts` erzeugt:
```typescript
// src/logic-functions/pre-install.ts
@@ -521,7 +521,7 @@ export default definePreInstallLogicFunction({
});
```
You can also manually execute the pre-install function at any time using the CLI:
Du kannst die Pre-Installationsfunktion auch jederzeit manuell über die CLI ausführen:
```bash filename="Terminal"
yarn twenty function:execute --preInstall
@@ -529,12 +529,12 @@ yarn twenty function:execute --preInstall
Hauptpunkte:
* Pre-install functions use `definePreInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one pre-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `preInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* The default timeout is set to 300 seconds (5 minutes) to allow for longer preparation tasks.
* Pre-install functions do not need triggersthey are invoked by the platform before installation or manually via `function:execute --preInstall`.
* Pre-Installationsfunktionen verwenden `definePreInstallLogicFunction()` — eine spezialisierte Variante, die Trigger-Einstellungen (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`) weglässt.
* Der Handler erhält ein `InstallLogicFunctionPayload` mit `{ previousVersion: string }` — die Version der App, die zuvor installiert war (oder eine leere Zeichenkette bei Neuinstallationen).
* Pro Anwendung ist nur eine Pre-Installationsfunktion zulässig. Der Manifest-Build schlägt fehl, wenn mehr als eine erkannt wird.
* Der `universalIdentifier` der Funktion wird während des Builds im Anwendungsmanifest automatisch als `preInstallLogicFunctionUniversalIdentifier` gesetzt — du musst ihn nicht in `defineApplication()` referenzieren.
* Das standardmäßige Timeout ist auf 300 Sekunden (5 Minuten) festgelegt, um längere Vorbereitungsvorgänge zu ermöglichen.
* Pre-Installationsfunktionen benötigen keine Trigger — sie werden von der Plattform vor der Installation oder manuell über `function:execute --preInstall` aufgerufen.
### Post-Installationsfunktionen
@@ -567,10 +567,10 @@ yarn twenty function:execute --postInstall
Hauptpunkte:
* Post-install functions use `definePostInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one post-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `postInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* Post-Installationsfunktionen verwenden `definePostInstallLogicFunction()` — eine spezialisierte Variante, die Trigger-Einstellungen (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`) weglässt.
* Der Handler erhält ein `InstallLogicFunctionPayload` mit `{ previousVersion: string }` — die Version der App, die zuvor installiert war (oder eine leere Zeichenkette bei Neuinstallationen).
* Pro Anwendung ist nur eine Post-Installationsfunktion zulässig. Der Manifest-Build schlägt fehl, wenn mehr als eine erkannt wird.
* Der `universalIdentifier` der Funktion wird während des Builds im Anwendungsmanifest automatisch als `postInstallLogicFunctionUniversalIdentifier` gesetzt — du musst ihn nicht in `defineApplication()` referenzieren.
* Das standardmäßige Timeout ist auf 300 Sekunden (5 Minuten) festgelegt, um längere Einrichtungsvorgänge wie Daten-Seeding zu ermöglichen.
* Post-Installationsfunktionen benötigen keine Trigger — sie werden von der Plattform während der Installation oder manuell über `function:execute --postInstall` aufgerufen.
File diff suppressed because one or more lines are too long
@@ -23,7 +23,7 @@ export const MyComponent = () => {
<Select
className
disabled={false}
label="Select an option"
label="Option auswählen"
options={[
{ value: 'option1', label: 'Option A', Icon: IconTwentyStar },
{ value: 'option2', label: 'Option B', Icon: IconTwentyStar },
@@ -20,27 +20,27 @@ import { TextInput } from "@/ui/input/components/TextInput";
export const MyComponent = () => {
const handleChange = (text) => {
console.log("Input changed:", text);
console.log("Eingabe geändert:", text);
};
const handleKeyDown = (event) => {
console.log("Key pressed:", event.key);
console.log("Taste gedrückt:", event.key);
};
return (
<TextInput
className
label="Username"
label="Benutzername"
onChange={handleChange}
fullWidth={false}
disableHotkeys={false}
error="Invalid username"
error="Ungültiger Benutzername"
onKeyDown={handleKeyDown}
RightIcon={null}
/>
);
};
},{
```
@@ -83,13 +83,13 @@ import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
export const MyComponent = () => {
return (
<AutosizeTextInput
onValidate={() => console.log("onValidate function fired")}
onValidate={() => console.log("onValidate-Funktion ausgelöst")}
minRows={1}
placeholder="Write a comment"
onFocus={() => console.log("onFocus function fired")}
placeholder="Kommentar schreiben"
onFocus={() => console.log("onFocus-Funktion ausgelöst")}
variant="icon"
buttonTitle
value="Task: "
value="Aufgabe: "
/>
);
};
@@ -6,9 +6,9 @@ Questo documento descrive le migliori pratiche da seguire quando si lavora sul f
## Gestione dello Stato
React and Jotai handle state management in the codebase.
React e Jotai gestiscono lo stato nella base di codice.
### Use Jotai atoms to store state
### Usa gli atomi di Jotai per memorizzare lo stato
È buona pratica creare tanti atomi quanti servono per memorizzare il tuo stato.
@@ -45,7 +45,7 @@ export const MyComponent = () => {
Evita di usare `useRef` per memorizzare lo stato.
If you want to store state, you should use `useState` or Jotai atoms with `useAtomState`.
Se vuoi memorizzare lo stato, dovresti usare `useState` o gli atomi di Jotai con `useAtomState`.
Consulta [come gestire i re-render](#managing-re-renders) se senti che hai bisogno di `useRef` per evitare alcuni re-render.
@@ -82,8 +82,8 @@ Se senti di dover aggiungere un `useEffect` nel tuo componente radice, dovresti
Puoi applicare lo stesso per la logica di recupero dati, con i hook di Apollo.
```tsx
// ❌ Bad, will cause re-renders even if data is not changing,
// because useEffect needs to be re-evaluated
// ❌ Sconsigliato, cause re-render anche se i dati non cambiano,
// perché useEffect deve essere ri-eseguito
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
const [someDependency] = useAtomState(someDependencyState);
@@ -103,8 +103,8 @@ export const App = () => (
```
```tsx
// ✅ Good, will not cause re-renders if data is not changing,
// because useEffect is re-evaluated in another sibling component
// ✅ Consigliato, non cause re-render se i dati non cambiano,
// perché useEffect viene ri-eseguito in un altro componente fratello
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
@@ -132,9 +132,9 @@ export const App = () => (
);
```
### Use atom family states and selectors
### Usa gli stati e i selettori della famiglia di atomi
Atom family states and selectors are a great way to avoid re-renders.
Gli stati e i selettori della famiglia di atomi sono un ottimo modo per evitare re-render.
Sono utili quando hai bisogno di memorizzare una lista di elementi.
@@ -77,7 +77,7 @@ Per evitare [re-render](/l/it/developers/contribute/capabilities/frontend-develo
### Gestione dello stato
[Jotai](https://jotai.org/) handles state management.
[Jotai](https://jotai.org/) gestisce lo stato.
Vedi [best practices](/l/it/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) per ulteriori informazioni sulla gestione dello stato.
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
}
```
Internally, the currently selected scope is stored in a Jotai atom that is shared across the application :
Internamente, l'ambito selezionato attualmente viene memorizzato in un atomo Jotai condiviso in tutta l'applicazione:
```tsx
export const currentHotkeyScopeState = createState<HotkeyScope>({
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
});
```
But this atom should never be handled manually ! Vedremo come usarlo nella sezione successiva.
Ma questo atomo non dovrebbe mai essere gestito manualmente! Vedremo come usarlo nella sezione successiva.
## Come funziona internamente?
Abbiamo creato un sottile wrapper su [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) che lo rende più performante ed evita rendering non necessari.
We also create a Jotai atom to handle the hotkey scope state and make it available everywhere in the application.
Creiamo anche un atomo Jotai per gestire lo stato dell'ambito del tasto di scelta rapida e renderlo disponibile ovunque nell'applicazione.
@@ -52,25 +52,25 @@ npx create-twenty-app@latest my-app --interactive
Da qui puoi:
```bash filename="Terminal"
# Add a new entity to your application (guided)
# Aggiungi una nuova entità alla tua applicazione (guidata)
yarn twenty entity:add
# Watch your application's function logs
# Monitora i log delle funzioni della tua applicazione
yarn twenty function:logs
# Execute a function by name
# Esegui una funzione per nome
yarn twenty function:execute -n my-function -p '{"name": "test"}'
# Execute the pre-install function
# Esegui la funzione di pre-installazione
yarn twenty function:execute --preInstall
# Execute the post-install function
# Esegui la funzione post-installazione
yarn twenty function:execute --postInstall
# Uninstall the application from the current workspace
# Disinstalla l'applicazione dallo spazio di lavoro corrente
yarn twenty app:uninstall
# Display commands' help
# Mostra l'aiuto dei comandi
yarn twenty help
```
@@ -83,7 +83,7 @@ Quando esegui `npx create-twenty-app@latest my-twenty-app`, lo scaffolder:
* Copia un'applicazione base minimale in `my-twenty-app/`
* Aggiunge una dipendenza locale `twenty-sdk` e la configurazione di Yarn 4
* Crea file di configurazione e script collegati alla CLI `twenty`
* Generates core files (application config, default function role, pre-install and post-install functions) plus example files based on the scaffolding mode
* Genera i file principali (configurazione dell'applicazione, ruolo predefinito per le funzioni logiche, funzioni di pre-installazione e post-installazione) più i file di esempio in base alla modalità di scaffolding
Un'app appena creata con la modalità predefinita `--exhaustive` si presenta così:
@@ -99,30 +99,30 @@ my-twenty-app/
eslint.config.mjs
tsconfig.json
README.md
public/ # Public assets folder (images, fonts, etc.)
public/ # Cartella delle risorse pubbliche (immagini, font, ecc.)
src/
├── application-config.ts # Required - main application configuration
├── application-config.ts # Obbligatorio - configurazione principale dell'applicazione
├── roles/
│ └── default-role.ts # Default role for logic functions
│ └── default-role.ts # Ruolo predefinito per le funzioni logiche
├── objects/
│ └── example-object.ts # Example custom object definition
│ └── example-object.ts # Definizione di oggetto personalizzato di esempio
├── fields/
│ └── example-field.ts # Example standalone field definition
│ └── example-field.ts # Definizione di campo autonomo di esempio
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── pre-install.ts # Pre-install logic function
│ └── post-install.ts # Post-install logic function
│ ├── hello-world.ts # Funzione logica di esempio
│ ├── pre-install.ts # Funzione logica di pre-installazione
│ └── post-install.ts # Funzione logica di post-installazione
├── front-components/
│ └── hello-world.tsx # Example front component
│ └── hello-world.tsx # Componente front-end di esempio
├── views/
│ └── example-view.ts # Example saved view definition
│ └── example-view.ts # Definizione di vista salvata di esempio
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
│ └── example-navigation-menu-item.ts # Link di navigazione della barra laterale di esempio
└── skills/
└── example-skill.ts # Example AI agent skill definition
└── example-skill.ts # Definizione di skill per agente IA di esempio
```
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`). Con `--interactive`, scegli quali file di esempio includere.
Con `--minimal`, vengono creati solo i file principali (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` e `logic-functions/post-install.ts`). Con `--interactive`, scegli quali file di esempio includere.
A livello generale:
@@ -139,18 +139,18 @@ A livello generale:
L'SDK rileva le entità analizzando i tuoi file TypeScript alla ricerca di chiamate **`export default define<Entity>({...})`**. Ogni tipo di entità ha una corrispondente funzione helper esportata da `twenty-sdk`:
| Funzione helper | Tipo di entità |
| ---------------------------------- | ----------------------------------------------------- |
| `defineObject()` | Definizioni di oggetti personalizzati |
| `defineLogicFunction()` | Definizioni di funzioni logiche |
| `definePreInstallLogicFunction()` | Pre-install logic function (runs before installation) |
| `definePostInstallLogicFunction()` | Post-install logic function (runs after installation) |
| `defineFrontComponent()` | Definizioni dei componenti front-end |
| `defineRole()` | Definizioni di ruoli |
| `defineField()` | Estensioni di campo per oggetti esistenti |
| `defineView()` | Definizioni di viste salvate |
| `defineNavigationMenuItem()` | Definizioni delle voci del menu di navigazione |
| `defineSkill()` | AI agent skill definitions |
| Funzione helper | Tipo di entità |
| ---------------------------------- | ------------------------------------------------------------------------------ |
| `defineObject()` | Definizioni di oggetti personalizzati |
| `defineLogicFunction()` | Definizioni di funzioni logiche |
| `definePreInstallLogicFunction()` | Funzione logica di pre-installazione (viene eseguita prima dell'installazione) |
| `definePostInstallLogicFunction()` | Funzione logica di post-installazione (viene eseguita dopo l'installazione) |
| `defineFrontComponent()` | Definizioni dei componenti front-end |
| `defineRole()` | Definizioni di ruoli |
| `defineField()` | Estensioni di campo per oggetti esistenti |
| `defineView()` | Definizioni di viste salvate |
| `defineNavigationMenuItem()` | Definizioni delle voci del menu di navigazione |
| `defineSkill()` | AI agent skill definitions |
<Note>
**La denominazione dei file è flessibile.** Il rilevamento delle entità è basato sull'AST — l'SDK esegue la scansione dei file sorgente alla ricerca del pattern `export default define<Entity>({...})`. Puoi organizzare file e cartelle come preferisci. Raggruppare per tipo di entità (ad es., `logic-functions/`, `roles/`) è solo una convenzione per l'organizzazione del codice, non un requisito.
@@ -215,19 +215,19 @@ Il pacchetto twenty-sdk fornisce blocchi tipizzati e funzioni helper da usare ne
L'SDK fornisce funzioni helper per definire le entità della tua app. Come descritto in [Rilevamento delle entità](#entity-detection), devi usare `export default define<Entity>({...})` affinché le tue entità vengano rilevate:
| Funzione | Scopo |
| ---------------------------------- | ----------------------------------------------------------------------- |
| `defineApplication()` | Configura i metadati dell'applicazione (obbligatorio, uno per app) |
| `defineObject()` | Definisci oggetti personalizzati con campi |
| `defineLogicFunction()` | Definisci funzioni logiche con handler |
| `definePreInstallLogicFunction()` | Define a pre-install logic function (one per app) |
| `definePostInstallLogicFunction()` | Define a post-install logic function (one per app) |
| `defineFrontComponent()` | Definisci componenti front-end per un'interfaccia utente personalizzata |
| `defineRole()` | Configura i permessi dei ruoli e l'accesso agli oggetti |
| `defineField()` | Estendi gli oggetti esistenti con campi aggiuntivi |
| `defineView()` | Definisce viste salvate per gli oggetti |
| `defineNavigationMenuItem()` | Definisce i link di navigazione della barra laterale |
| `defineSkill()` | Define AI agent skills |
| Funzione | Scopo |
| ---------------------------------- | -------------------------------------------------------------------------- |
| `defineApplication()` | Configura i metadati dell'applicazione (obbligatorio, uno per app) |
| `defineObject()` | Definisci oggetti personalizzati con campi |
| `defineLogicFunction()` | Definisci funzioni logiche con handler |
| `definePreInstallLogicFunction()` | Definisce una funzione logica di pre-installazione (una per applicazione) |
| `definePostInstallLogicFunction()` | Definisce una funzione logica di post-installazione (una per applicazione) |
| `defineFrontComponent()` | Definisci componenti front-end per un'interfaccia utente personalizzata |
| `defineRole()` | Configura i permessi dei ruoli e l'accesso agli oggetti |
| `defineField()` | Estendi gli oggetti esistenti con campi aggiuntivi |
| `defineView()` | Definisce viste salvate per gli oggetti |
| `defineNavigationMenuItem()` | Definisce i link di navigazione della barra laterale |
| `defineSkill()` | Define AI agent skills |
Queste funzioni convalidano la configurazione in fase di build e offrono il completamento automatico nell'IDE e la sicurezza dei tipi.
@@ -327,7 +327,7 @@ Ogni app ha un singolo file `application-config.ts` che descrive:
* **Identità dell'app**: identificatori, nome visualizzato e descrizione.
* **Come vengono eseguite le sue funzioni**: quale ruolo usano per i permessi.
* **Variabili (opzionali)**: coppie chiavevalore esposte alle funzioni come variabili d'ambiente.
* **(Optional) pre-install function**: a logic function that runs before the app is installed.
* **(Opzionale) funzione di pre-installazione**: una funzione logica che viene eseguita prima che l'app venga installata.
* **(Opzionale) funzione post-installazione**: una funzione logica che viene eseguita dopo l'installazione dell'app.
Usa `defineApplication()` per definire la configurazione della tua applicazione:
@@ -359,7 +359,7 @@ Note:
* I campi `universalIdentifier` sono ID deterministici sotto il tuo controllo; generali una volta e mantienili stabili tra le sincronizzazioni.
* `applicationVariables` diventano variabili d'ambiente per le tue funzioni (ad esempio, `DEFAULT_RECIPIENT_NAME` è disponibile come `process.env.DEFAULT_RECIPIENT_NAME`).
* `defaultRoleUniversalIdentifier` deve corrispondere al file del ruolo (vedi sotto).
* Pre-install and post-install functions are automatically detected during the manifest build. See [Pre-install functions](#pre-install-functions) and [Post-install functions](#post-install-functions).
* Le funzioni di pre-installazione e post-installazione vengono rilevate automaticamente durante la build del manifesto. Vedi [Funzioni di pre-installazione](#pre-install-functions) e [Funzioni di post-installazione](#post-install-functions).
#### Ruoli e permessi
@@ -498,11 +498,11 @@ Note:
* L'array `triggers` è facoltativo. Le funzioni senza trigger possono essere utilizzate come funzioni di utilità richiamate da altre funzioni.
* Puoi combinare più tipi di trigger in un'unica funzione.
### Pre-install functions
### Funzioni di pre-installazione
A pre-install function is a logic function that runs automatically before your app is installed on a workspace. This is useful for validation tasks, prerequisite checks, or preparing workspace state before the main installation proceeds.
Una funzione di pre-installazione è una funzione logica che viene eseguita automaticamente prima che la tua app venga installata in uno spazio di lavoro. È utile per attività di convalida, controlli dei prerequisiti o per preparare lo stato dello spazio di lavoro prima che proceda l'installazione principale.
When you scaffold a new app with `create-twenty-app`, a pre-install function is generated for you at `src/logic-functions/pre-install.ts`:
Quando esegui lo scaffolding di una nuova app con `create-twenty-app`, viene generata una funzione di pre-installazione in `src/logic-functions/pre-install.ts`:
```typescript
// src/logic-functions/pre-install.ts
@@ -521,7 +521,7 @@ export default definePreInstallLogicFunction({
});
```
You can also manually execute the pre-install function at any time using the CLI:
Puoi anche eseguire manualmente la funzione di pre-installazione in qualsiasi momento utilizzando la CLI:
```bash filename="Terminal"
yarn twenty function:execute --preInstall
@@ -529,12 +529,12 @@ yarn twenty function:execute --preInstall
Punti chiave:
* Pre-install functions use `definePreInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one pre-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `preInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* The default timeout is set to 300 seconds (5 minutes) to allow for longer preparation tasks.
* Pre-install functions do not need triggersthey are invoked by the platform before installation or manually via `function:execute --preInstall`.
* Le funzioni di pre-installazione utilizzano `definePreInstallLogicFunction()` — una variante specializzata che omette le impostazioni dei trigger (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* L'handler riceve un `InstallLogicFunctionPayload` con `{ previousVersion: string }` — la versione dell'app precedentemente installata (oppure una stringa vuota per nuove installazioni).
* È consentita una sola funzione di pre-installazione per applicazione. La build del manifesto genererà un errore se ne viene rilevata più di una.
* L'`universalIdentifier` della funzione viene impostato automaticamente come `preInstallLogicFunctionUniversalIdentifier` nel manifesto dell'applicazione durante la build — non è necessario farvi riferimento in `defineApplication()`.
* Il timeout predefinito è impostato a 300 secondi (5 minuti) per consentire attività di preparazione più lunghe.
* Le funzioni di pre-installazione non necessitano di trigger — vengono invocate dalla piattaforma prima dell'installazione o manualmente tramite `function:execute --preInstall`.
### Funzioni post-installazione
@@ -567,10 +567,10 @@ yarn twenty function:execute --postInstall
Punti chiave:
* Post-install functions use `definePostInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one post-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `postInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* Le funzioni di post-installazione utilizzano `definePostInstallLogicFunction()` — una variante specializzata che omette le impostazioni dei trigger (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* L'handler riceve un `InstallLogicFunctionPayload` con `{ previousVersion: string }` — la versione dell'app precedentemente installata (oppure una stringa vuota per nuove installazioni).
* È consentita una sola funzione di post-installazione per applicazione. La build del manifesto genererà un errore se ne viene rilevata più di una.
* L'`universalIdentifier` della funzione viene impostato automaticamente come `postInstallLogicFunctionUniversalIdentifier` nel manifesto dell'applicazione durante la build — non è necessario farvi riferimento in `defineApplication()`.
* Il timeout predefinito è impostato a 300 secondi (5 minuti) per consentire attività di configurazione più lunghe, come il popolamento dei dati.
* Le funzioni di post-installazione non necessitano di trigger — vengono invocate dalla piattaforma durante l'installazione o manualmente tramite `function:execute --postInstall`.
@@ -23,10 +23,10 @@ export const MyComponent = () => {
<Select
className
disabled={false}
label="Select an option"
label="Seleziona un'opzione"
options={[
{ value: 'option1', label: 'Option A', Icon: IconTwentyStar },
{ value: 'option2', label: 'Option B', Icon: IconTwentyStar },
{ value: 'option1', label: 'Opzione A', Icon: IconTwentyStar },
{ value: 'option2', label: 'Opzione B', Icon: IconTwentyStar },
]}
value="option1"
/>
@@ -6,9 +6,9 @@ Este documento descreve as melhores práticas que você deve seguir ao trabalhar
## Gerenciamento de Estado
React and Jotai handle state management in the codebase.
React e Jotai lidam com o gerenciamento de estado na base de código.
### Use Jotai atoms to store state
### Use átomos do Jotai para armazenar o estado
É uma boa prática criar tantos átomos quanto necessário para armazenar seu estado.
@@ -45,7 +45,7 @@ export const MyComponent = () => {
Evite usar `useRef` para armazenar estado.
If you want to store state, you should use `useState` or Jotai atoms with `useAtomState`.
Se quiser armazenar o estado, você deve usar `useState` ou átomos do Jotai com `useAtomState`.
Veja [como gerenciar re-renderizações](#managing-re-renders) se você sentir que precisa de `useRef` para evitar que algumas re-renderizações aconteçam.
@@ -82,8 +82,8 @@ If you feel like you need to add a `useEffect` in your root component, you shoul
Você pode aplicar o mesmo para lógica de busca de dados, com hooks do Apollo.
```tsx
// ❌ Bad, will cause re-renders even if data is not changing,
// because useEffect needs to be re-evaluated
// ❌ Ruim, causará re-renderizações mesmo se os dados não estiverem mudando,
// porque o useEffect precisa ser reavaliado
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
const [someDependency] = useAtomState(someDependencyState);
@@ -103,8 +103,8 @@ export const App = () => (
```
```tsx
// ✅ Good, will not cause re-renders if data is not changing,
// because useEffect is re-evaluated in another sibling component
// ✅ Bom, não causará re-renderizações se os dados não estiverem mudando,
// porque o useEffect é reavaliado em outro componente irmão
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
@@ -132,9 +132,9 @@ export const App = () => (
);
```
### Use atom family states and selectors
### Use famílias de átomos e seletores de família
Atom family states and selectors are a great way to avoid re-renders.
Famílias de átomos e seletores são uma ótima maneira de evitar re-renderizações.
Eles são úteis quando você precisa armazenar uma lista de itens.
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/pt/developers/contribute/capabilities/front
### Gerenciamento de Estado
[Jotai](https://jotai.org/) handles state management.
[Jotai](https://jotai.org/) gerencia o estado.
Veja [melhores práticas](/l/pt/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) para mais informações sobre gerenciamento de estado.
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
}
```
Internally, the currently selected scope is stored in a Jotai atom that is shared across the application :
Internamente, o escopo atualmente selecionado é armazenado em um átomo Jotai que é compartilhado por toda a aplicação :
```tsx
export const currentHotkeyScopeState = createState<HotkeyScope>({
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
});
```
But this atom should never be handled manually ! Veremos como usá-lo na próxima seção.
Mas esse átomo nunca deve ser manipulado manualmente! Veremos como usá-lo na próxima seção.
## Como funciona internamente?
Criamos um wrapper leve em cima de [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) que o torna mais eficiente e evita renderizações desnecessárias.
We also create a Jotai atom to handle the hotkey scope state and make it available everywhere in the application.
Também criamos um átomo Jotai para gerenciar o estado do escopo da tecla de atalho e torná-lo disponível em toda a aplicação.
@@ -17,11 +17,11 @@ Um seletor de ícones baseado em lista suspensa que permite aos usuários seleci
import React, { useState } from "react";
import { IconPicker } from "@/ui/input/components/IconPicker";
export const MyComponent = () => {
export const MeuComponente = () => {
const [selectedIcon, setSelectedIcon] = useState("");
const handleIconChange = ({ iconKey, Icon }) => {
console.log("Selected Icon:", iconKey);
console.log("Ícone Selecionado:", iconKey);
setSelectedIcon(iconKey);
};
@@ -23,10 +23,10 @@ export const MyComponent = () => {
<Select
className
disabled={false}
label="Select an option"
label="Selecione uma opção"
options={[
{ value: 'option1', label: 'Option A', Icon: IconTwentyStar },
{ value: 'option2', label: 'Option B', Icon: IconTwentyStar },
{ value: 'option1', label: 'Opção A', Icon: IconTwentyStar },
{ value: 'option2', label: 'Opção B', Icon: IconTwentyStar },
]}
value="option1"
/>
@@ -20,21 +20,21 @@ import { TextInput } from "@/ui/input/components/TextInput";
export const MyComponent = () => {
const handleChange = (text) => {
console.log("Input changed:", text);
console.log("Entrada alterada:", text);
};
const handleKeyDown = (event) => {
console.log("Key pressed:", event.key);
console.log("Tecla pressionada:", event.key);
};
return (
<TextInput
className
label="Username"
label="Nome de usuário"
onChange={handleChange}
fullWidth={false}
disableHotkeys={false}
error="Invalid username"
error="Nome de usuário inválido"
onKeyDown={handleKeyDown}
RightIcon={null}
/>
@@ -83,13 +83,13 @@ import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
export const MyComponent = () => {
return (
<AutosizeTextInput
onValidate={() => console.log("onValidate function fired")}
onValidate={() => console.log("função onValidate executada")}
minRows={1}
placeholder="Write a comment"
onFocus={() => console.log("onFocus function fired")}
placeholder="Escreva um comentário"
onFocus={() => console.log("função onFocus executada")}
variant="icon"
buttonTitle
value="Task: "
value="Tarefa: "
/>
);
};
@@ -52,26 +52,26 @@ npx create-twenty-app@latest my-app --interactive
De aici puteți:
```bash filename="Terminal"
# Add a new entity to your application (guided)
# Adaugă o entitate nouă în aplicația ta (ghidat)
yarn twenty entity:add
# Watch your application's function logs
# Urmărește jurnalele funcțiilor aplicației tale
yarn twenty function:logs
# Execute a function by name
# Execută o funcție după nume
yarn twenty function:execute -n my-function -p '{"name": "test"}'
# Execute the pre-install function
# Execută funcția de pre-instalare
yarn twenty function:execute --preInstall
# Execute the post-install function
# Execută funcția post-instalare
yarn twenty function:execute --postInstall
# Uninstall the application from the current workspace
# Dezinstalează aplicația din spațiul de lucru curent
yarn twenty app:uninstall
# Display commands' help
yarn twenty help
# Afișează ajutorul pentru comenzi
yarn twenty help},{
```
Consultați și: paginile de referință CLI pentru [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) și [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -83,7 +83,7 @@ Când rulați `npx create-twenty-app@latest my-twenty-app`, generatorul:
* Copiază o aplicație de bază minimală în `my-twenty-app/`
* Adaugă o dependență locală `twenty-sdk` și configurația Yarn 4
* Creează fișiere de configurare și scripturi conectate la CLI-ul `twenty`
* Generates core files (application config, default function role, pre-install and post-install functions) plus example files based on the scaffolding mode
* Generează fișierele de bază (configurația aplicației, rolul implicit al funcțiilor, funcțiile de pre-instalare și post-instalare) plus fișiere de exemplu în funcție de modul de generare a scheletului.
O aplicație proaspăt generată cu modul implicit `--exhaustive` arată astfel:
@@ -99,30 +99,30 @@ my-twenty-app/
eslint.config.mjs
tsconfig.json
README.md
public/ # Public assets folder (images, fonts, etc.)
public/ # Director pentru resurse publice (imagini, fonturi etc.)
src/
├── application-config.ts # Required - main application configuration
├── application-config.ts # Obligatoriu - configurația principală a aplicației
├── roles/
│ └── default-role.ts # Default role for logic functions
│ └── default-role.ts # Rol implicit pentru funcțiile logice
├── objects/
│ └── example-object.ts # Example custom object definition
│ └── example-object.ts # Exemplu de definiție a unui obiect personalizat
├── fields/
│ └── example-field.ts # Example standalone field definition
│ └── example-field.ts # Exemplu de definiție de câmp independent
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── pre-install.ts # Pre-install logic function
│ └── post-install.ts # Post-install logic function
│ ├── hello-world.ts # Exemplu de funcție logică
│ ├── pre-install.ts # Funcție logică de pre-instalare
│ └── post-install.ts # Funcție logică post-instalare
├── front-components/
│ └── hello-world.tsx # Example front component
│ └── hello-world.tsx # Exemplu de componentă de interfață
├── views/
│ └── example-view.ts # Example saved view definition
│ └── example-view.ts # Exemplu de definiție a unei vizualizări salvate
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
│ └── example-navigation-menu-item.ts # Exemplu de link de navigare în bara laterală
└── skills/
└── example-skill.ts # Example AI agent skill definition
└── example-skill.ts # Exemplu de definiție a unei abilități a agentului AI
```
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`). Cu `--interactive`, alegi ce fișiere de exemplu să incluzi.
Cu `--minimal`, sunt create doar fișierele de bază (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` și `logic-functions/post-install.ts`). Cu `--interactive`, alegi ce fișiere de exemplu să incluzi.
Pe scurt:
@@ -139,18 +139,18 @@ Pe scurt:
SDK-ul detectează entitățile analizând fișierele TypeScript pentru apeluri **`export default define<Entity>({...})`**. Fiecare tip de entitate are o funcție ajutătoare corespunzătoare, exportată din `twenty-sdk`:
| Funcție ajutătoare | Tipul entității |
| ---------------------------------- | ----------------------------------------------------- |
| `defineObject()` | Definiții de obiecte personalizate |
| `defineLogicFunction()` | Definiții de funcții de logică |
| `definePreInstallLogicFunction()` | Pre-install logic function (runs before installation) |
| `definePostInstallLogicFunction()` | Post-install logic function (runs after installation) |
| `defineFrontComponent()` | Definiții ale componentelor de interfață |
| `defineRole()` | Definiții de rol |
| `defineField()` | Extensii de câmp pentru obiectele existente |
| `defineView()` | Definiții pentru vizualizări salvate |
| `defineNavigationMenuItem()` | Definiții pentru elemente de meniu de navigare |
| `defineSkill()` | Definiții ale abilităților agentului AI |
| Funcție ajutătoare | Tipul entității |
| ---------------------------------- | -------------------------------------------------------------- |
| `defineObject()` | Definiții de obiecte personalizate |
| `defineLogicFunction()` | Definiții de funcții de logică |
| `definePreInstallLogicFunction()` | Funcție logică de pre-instalare (rulează înainte de instalare) |
| `definePostInstallLogicFunction()` | Funcție logică post-instalare (rulează după instalare) |
| `defineFrontComponent()` | Definiții ale componentelor de interfață |
| `defineRole()` | Definiții de rol |
| `defineField()` | Extensii de câmp pentru obiectele existente |
| `defineView()` | Definiții pentru vizualizări salvate |
| `defineNavigationMenuItem()` | Definiții pentru elemente de meniu de navigare |
| `defineSkill()` | Definiții ale abilităților agentului AI |
<Note>
**Denumirea fișierelor este flexibilă.** Detectarea entităților se bazează pe AST — SDK-ul scanează fișierele sursă pentru tiparul `export default define<Entity>({...})`. Puteți organiza fișierele și folderele cum doriți. Gruparea după tipul de entitate (de exemplu, `logic-functions/`, `roles/`) este doar o convenție pentru organizarea codului, nu o cerință.
@@ -220,8 +220,8 @@ SDK-ul oferă funcții ajutătoare pentru definirea entităților aplicației. D
| `defineApplication()` | Configurați metadatele aplicației (obligatoriu, una per aplicație) |
| `defineObject()` | Definiți obiecte personalizate cu câmpuri |
| `defineLogicFunction()` | Definiți funcții de logică cu handleri |
| `definePreInstallLogicFunction()` | Define a pre-install logic function (one per app) |
| `definePostInstallLogicFunction()` | Define a post-install logic function (one per app) |
| `definePreInstallLogicFunction()` | Definește o funcție logică de pre-instalare (una per aplicație) |
| `definePostInstallLogicFunction()` | Definește o funcție logică post-instalare (una per aplicație) |
| `defineFrontComponent()` | Definiți componente Front pentru interfața de utilizator personalizată |
| `defineRole()` | Configurați permisiunile rolurilor și accesul la obiecte |
| `defineField()` | Extindeți obiectele existente cu câmpuri suplimentare |
@@ -327,7 +327,7 @@ Fiecare aplicație are un singur fișier `application-config.ts` care descrie:
* **Cine este aplicația**: identificatori, nume de afișare și descriere.
* **Cum rulează funcțiile**: ce rol folosesc pentru permisiuni.
* **(Opțional) variabile**: perechi cheievaloare expuse funcțiilor ca variabile de mediu.
* **(Optional) pre-install function**: a logic function that runs before the app is installed.
* **(Opțional) funcție de pre-instalare**: o funcție logică care rulează înainte ca aplicația să fie instalată.
* **(Opțional) funcție post-instalare**: o funcție logică care rulează după instalarea aplicației.
Folosiți `defineApplication()` pentru a defini configurația aplicației:
@@ -359,7 +359,7 @@ Notițe:
* Câmpurile `universalIdentifier` sunt ID-uri deterministe pe care le dețineți; generați-le o singură dată și păstrați-le stabile între sincronizări.
* `applicationVariables` devin variabile de mediu pentru funcțiile dvs. (de exemplu, `DEFAULT_RECIPIENT_NAME` este disponibil ca `process.env.DEFAULT_RECIPIENT_NAME`).
* `defaultRoleUniversalIdentifier` trebuie să corespundă fișierului de rol (vedeți mai jos).
* Pre-install and post-install functions are automatically detected during the manifest build. See [Pre-install functions](#pre-install-functions) and [Post-install functions](#post-install-functions).
* Funcțiile de pre-instalare și post-instalare sunt detectate automat în timpul construirii manifestului. Vezi [Funcții de pre-instalare](#pre-install-functions) și [Funcții post-instalare](#post-install-functions).
#### Roluri și permisiuni
@@ -498,11 +498,11 @@ Notițe:
* Matricea `triggers` este opțională. Funcțiile fără declanșatoare pot fi folosite ca funcții utilitare apelate de alte funcții.
* Puteți combina mai multe tipuri de declanșatoare într-o singură funcție.
### Pre-install functions
### Funcții de pre-instalare
A pre-install function is a logic function that runs automatically before your app is installed on a workspace. This is useful for validation tasks, prerequisite checks, or preparing workspace state before the main installation proceeds.
O funcție de pre-instalare este o funcție logică ce rulează automat înainte ca aplicația ta să fie instalată într-un spațiu de lucru. Aceasta este utilă pentru sarcini de validare, verificări ale condițiilor prealabile sau pregătirea stării spațiului de lucru înainte ca instalarea principală să continue.
When you scaffold a new app with `create-twenty-app`, a pre-install function is generated for you at `src/logic-functions/pre-install.ts`:
Când creezi scheletul unei aplicații noi cu `create-twenty-app`, ți se generează o funcție de pre-instalare la `src/logic-functions/pre-install.ts`:
```typescript
// src/logic-functions/pre-install.ts
@@ -521,7 +521,7 @@ export default definePreInstallLogicFunction({
});
```
You can also manually execute the pre-install function at any time using the CLI:
Poți, de asemenea, să execuți manual funcția de pre-instalare oricând folosind CLI:
```bash filename="Terminal"
yarn twenty function:execute --preInstall
@@ -529,12 +529,12 @@ yarn twenty function:execute --preInstall
Puncte cheie:
* Pre-install functions use `definePreInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one pre-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `preInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* The default timeout is set to 300 seconds (5 minutes) to allow for longer preparation tasks.
* Pre-install functions do not need triggers — they are invoked by the platform before installation or manually via `function:execute --preInstall`.
* Funcțiile de pre-instalare folosesc `definePreInstallLogicFunction()` — o variantă specializată care omite setările de declanșare (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* Handlerul primește un `InstallLogicFunctionPayload` cu `{ previousVersion: string }` — versiunea aplicației care a fost instalată anterior (sau un șir gol pentru instalări noi).
* Este permisă o singură funcție de pre-instalare per aplicație. Construirea manifestului va genera o eroare dacă este detectată mai mult de una.
* Proprietatea `universalIdentifier` a funcției este setată automat ca `preInstallLogicFunctionUniversalIdentifier` în manifestul aplicației în timpul build-ului — nu este nevoie să o referi în `defineApplication()`.
* Timpul de expirare implicit este setat la 300 de secunde (5 minute) pentru a permite sarcini de pregătire mai lungi.
* Funcțiile de pre-instalare nu au nevoie de declanșatoare — sunt invocate de platformă înainte de instalare sau manual prin `function:execute --preInstall`.
### Funcții post-instalare
@@ -567,10 +567,10 @@ yarn twenty function:execute --postInstall
Puncte cheie:
* Post-install functions use `definePostInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one post-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `postInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* Funcțiile de post-instalare folosesc `definePostInstallLogicFunction()` — o variantă specializată care omite setările de declanșare (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* Handlerul primește un `InstallLogicFunctionPayload` cu `{ previousVersion: string }` — versiunea aplicației care a fost instalată anterior (sau un șir gol pentru instalări noi).
* Este permisă o singură funcție de post-instalare per aplicație. Construirea manifestului va genera o eroare dacă este detectată mai mult de una.
* Proprietatea `universalIdentifier` a funcției este setată automat ca `postInstallLogicFunctionUniversalIdentifier` în manifestul aplicației în timpul build-ului — nu este nevoie să o referi în `defineApplication()`.
* Timpul de expirare implicit este setat la 300 de secunde (5 minute) pentru a permite sarcini de configurare mai lungi, cum ar fi popularea datelor.
* Funcțiile post-instalare nu au nevoie de declanșatoare — sunt invocate de platformă în timpul instalării sau manual prin `function:execute --postInstall`.
@@ -6,9 +6,9 @@ title: Лучшие практики
## Управление состоянием
React and Jotai handle state management in the codebase.
React и Jotai отвечают за управление состоянием в коде.
### Use Jotai atoms to store state
### Используйте атомы Jotai для хранения состояния
Полезно создавать столько атомов, сколько вам нужно для хранения состояния.
@@ -45,7 +45,7 @@ export const MyComponent = () => {
Избегайте использования `useRef` для хранения состояния.
If you want to store state, you should use `useState` or Jotai atoms with `useAtomState`.
Если вы хотите сохранять состояние, используйте `useState` или атомы Jotai с `useAtomState`.
Смотрите [как управлять повторными рендерами](#managing-re-renders), если вы считаете, что вам нужен `useRef`, чтобы предотвратить их.
@@ -82,8 +82,8 @@ If you want to store state, you should use `useState` or Jotai atoms with `useAt
Вы можете применять то же самое для логики получения данных, с хуками Apollo.
```tsx
// ❌ Bad, will cause re-renders even if data is not changing,
// because useEffect needs to be re-evaluated
// ❌ Плохо, вызовет повторные рендеры, даже если данные не меняются,
// потому что useEffect нужно повторно вычислять
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
const [someDependency] = useAtomState(someDependencyState);
@@ -100,11 +100,12 @@ export const PageComponent = () => {
export const App = () => (
<PageComponent />
);
```
```tsx
// ✅ Good, will not cause re-renders if data is not changing,
// because useEffect is re-evaluated in another sibling component
// ✅ Хорошо, не вызовет повторные рендеры, если данные не меняются,
// потому что useEffect пересчитывается в другом соседнем компоненте
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
@@ -130,11 +131,12 @@ export const App = () => (
<PageComponent />
</>
);
```
### Use atom family states and selectors
### Используйте состояния семейства атомов и селекторы
Atom family states and selectors are a great way to avoid re-renders.
Состояния семейства атомов и селекторы — отличный способ избежать повторных рендеров.
Они полезны, когда нужно хранить список элементов.
@@ -77,7 +77,7 @@ npx nx run twenty-front:storybook:coverage # (требуется yarn storybook:
### Управление состоянием
[Jotai](https://jotai.org/) handles state management.
[Jotai](https://jotai.org/) отвечает за управление состоянием.
[лучшие практики](/l/ru/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) для получения дополнительной информации об управлении состоянием.
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
}
```
Internally, the currently selected scope is stored in a Jotai atom that is shared across the application :
Внутренне текущая выбранная область действия хранится в атоме Jotai, который используется по всему приложению:
```tsx
export const currentHotkeyScopeState = createState<HotkeyScope>({
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
});
```
But this atom should never be handled manually ! Мы увидим, как использовать это в следующем разделе.
Но этот атом никогда не следует обрабатывать вручную! Мы увидим, как использовать это в следующем разделе.
## Как это работает внутренне?
Мы сделали тонкую обертку поверх [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro), которая делает его более производительным и избегает ненужных повторных рендеров.
We also create a Jotai atom to handle the hotkey scope state and make it available everywhere in the application.
Мы также создаем атом Jotai, чтобы управлять состоянием области действия горячих клавиш и сделать его доступным везде в приложении.
@@ -52,25 +52,25 @@ npx create-twenty-app@latest my-app --interactive
Отсюда вы можете:
```bash filename="Terminal"
# Add a new entity to your application (guided)
# Добавить новую сущность в ваше приложение (с мастером)
yarn twenty entity:add
# Watch your application's function logs
# Просматривать логи функций вашего приложения
yarn twenty function:logs
# Execute a function by name
# Выполнить функцию по имени
yarn twenty function:execute -n my-function -p '{"name": "test"}'
# Execute the pre-install function
# Выполнить предустановочную функцию
yarn twenty function:execute --preInstall
# Execute the post-install function
# Выполнить послеустановочную функцию
yarn twenty function:execute --postInstall
# Uninstall the application from the current workspace
# Удалить приложение из текущего рабочего пространства
yarn twenty app:uninstall
# Display commands' help
# Показать справку по командам
yarn twenty help
```
@@ -83,7 +83,7 @@ yarn twenty help
* Копирует минимальное базовое приложение в `my-twenty-app/`
* Добавляет локальную зависимость `twenty-sdk` и конфигурацию Yarn 4
* Создаёт файлы конфигурации и скрипты, подключённые к CLI `twenty`
* Generates core files (application config, default function role, pre-install and post-install functions) plus example files based on the scaffolding mode
* Генерирует основные файлы (конфигурацию приложения, роль функций по умолчанию, предустановочную и послеустановочную функции), а также примерные файлы в зависимости от выбранного режима создания каркаса
Сгенерированное с помощью каркаса приложение с режимом по умолчанию `--exhaustive` выглядит так:
@@ -99,30 +99,30 @@ my-twenty-app/
eslint.config.mjs
tsconfig.json
README.md
public/ # Public assets folder (images, fonts, etc.)
public/ # Папка публичных ресурсов (изображения, шрифты и т. д.)
src/
├── application-config.ts # Required - main application configuration
├── application-config.ts # Обязательный — основная конфигурация приложения
├── roles/
│ └── default-role.ts # Default role for logic functions
│ └── default-role.ts # Роль по умолчанию для логических функций
├── objects/
│ └── example-object.ts # Example custom object definition
│ └── example-object.ts # Пример определения пользовательского объекта
├── fields/
│ └── example-field.ts # Example standalone field definition
│ └── example-field.ts # Пример определения отдельного поля
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── pre-install.ts # Pre-install logic function
│ └── post-install.ts # Post-install logic function
│ ├── hello-world.ts # Пример логической функции
│ ├── pre-install.ts # Предустановочная логическая функция
│ └── post-install.ts # Послеустановочная логическая функция
├── front-components/
│ └── hello-world.tsx # Example front component
│ └── hello-world.tsx # Пример фронтенд-компонента
├── views/
│ └── example-view.ts # Example saved view definition
│ └── example-view.ts # Пример определения сохранённого представления
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
│ └── example-navigation-menu-item.ts # Пример ссылки боковой панели навигации
└── skills/
└── example-skill.ts # Example AI agent skill definition
└── example-skill.ts # Пример определения навыка агента ИИ
```
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`). С `--interactive` вы выбираете, какие примерные файлы включить.
С `--minimal` создаются только основные файлы (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` и `logic-functions/post-install.ts`). С `--interactive` вы выбираете, какие примерные файлы включить.
В общих чертах:
@@ -139,18 +139,18 @@ With `--minimal`, only the core files are created (`application-config.ts`, `rol
SDK обнаруживает сущности, разбирая ваши файлы TypeScript в поисках вызовов **`export default define<Entity>({...})`**. Для каждого типа сущности существует соответствующая вспомогательная функция, экспортируемая из `twenty-sdk`:
| Вспомогательная функция | Тип сущности |
| ---------------------------------- | ----------------------------------------------------- |
| `defineObject()` | Определения пользовательских объектов |
| `defineLogicFunction()` | Определения логических функций |
| `definePreInstallLogicFunction()` | Pre-install logic function (runs before installation) |
| `definePostInstallLogicFunction()` | Post-install logic function (runs after installation) |
| `defineFrontComponent()` | Определения компонентов фронтенда |
| `defineRole()` | Определения ролей |
| `defineField()` | Расширения полей для существующих объектов |
| `defineView()` | Определения сохранённых представлений |
| `defineNavigationMenuItem()` | Определения пунктов меню навигации |
| `defineSkill()` | Определения навыков агента ИИ |
| Вспомогательная функция | Тип сущности |
| ---------------------------------- | ------------------------------------------------------------------ |
| `defineObject()` | Определения пользовательских объектов |
| `defineLogicFunction()` | Определения логических функций |
| `definePreInstallLogicFunction()` | Предустановочная логическая функция (запускается до установки) |
| `definePostInstallLogicFunction()` | Послеустановочная логическая функция (запускается после установки) |
| `defineFrontComponent()` | Определения компонентов фронтенда |
| `defineRole()` | Определения ролей |
| `defineField()` | Расширения полей для существующих объектов |
| `defineView()` | Определения сохранённых представлений |
| `defineNavigationMenuItem()` | Определения пунктов меню навигации |
| `defineSkill()` | Определения навыков агента ИИ |
<Note>
**Имена файлов заданы гибко.** Обнаружение сущностей основано на AST — SDK сканирует ваши исходные файлы в поисках шаблона `export default define<Entity>({...})`. Вы можете организовывать файлы и папки как угодно. Группировка по типу сущности (например, `logic-functions/`, `roles/`) — это лишь соглашение для организации кода, а не требование.
@@ -215,19 +215,19 @@ yarn twenty auth:status
SDK предоставляет вспомогательные функции для определения сущностей вашего приложения. Как описано в [Обнаружение сущностей](#entity-detection), вы должны использовать `export default define<Entity>({...})`, чтобы ваши сущности были обнаружены:
| Функция | Назначение |
| ---------------------------------- | ---------------------------------------------------------------------- |
| `defineApplication()` | Настройка метаданных приложения (обязательно, по одному на приложение) |
| `defineObject()` | Определяет пользовательские объекты с полями |
| `defineLogicFunction()` | Определение логических функций с обработчиками |
| `definePreInstallLogicFunction()` | Define a pre-install logic function (one per app) |
| `definePostInstallLogicFunction()` | Define a post-install logic function (one per app) |
| `defineFrontComponent()` | Определение фронт-компонентов для настраиваемого интерфейса |
| `defineRole()` | Настраивает права роли и доступ к объектам |
| `defineField()` | Расширение существующих объектов дополнительными полями |
| `defineView()` | Определяйте сохранённые представления для объектов |
| `defineNavigationMenuItem()` | Определяйте ссылки боковой панели навигации |
| `defineSkill()` | Определение навыков агента ИИ |
| Функция | Назначение |
| ---------------------------------- | ------------------------------------------------------------------------ |
| `defineApplication()` | Настройка метаданных приложения (обязательно, по одному на приложение) |
| `defineObject()` | Определяет пользовательские объекты с полями |
| `defineLogicFunction()` | Определение логических функций с обработчиками |
| `definePreInstallLogicFunction()` | Определяет предустановочную логическую функцию (по одной на приложение) |
| `definePostInstallLogicFunction()` | Определяет послеустановочную логическую функцию (по одной на приложение) |
| `defineFrontComponent()` | Определение фронт-компонентов для настраиваемого интерфейса |
| `defineRole()` | Настраивает права роли и доступ к объектам |
| `defineField()` | Расширение существующих объектов дополнительными полями |
| `defineView()` | Определяйте сохранённые представления для объектов |
| `defineNavigationMenuItem()` | Определяйте ссылки боковой панели навигации |
| `defineSkill()` | Определение навыков агента ИИ |
Эти функции проверяют вашу конфигурацию на этапе сборки и обеспечивают автодополнение в IDE и безопасность типов.
@@ -327,7 +327,7 @@ export default defineObject({
* **Что это за приложение**: идентификаторы, отображаемое имя и описание.
* **Как запускаются его функции**: какую роль они используют для прав доступа.
* **(Необязательно) переменные**: пары ключ-значение, предоставляемые вашим функциям как переменные окружения.
* **(Optional) pre-install function**: a logic function that runs before the app is installed.
* **(Необязательно) предустановочная функция**: логическая функция, которая запускается до установки приложения.
* **(Необязательно) послеустановочная функция**: функция логики, которая запускается после установки приложения.
Используйте `defineApplication()` для определения конфигурации вашего приложения:
@@ -359,7 +359,7 @@ export default defineApplication({
* `universalIdentifier` — это детерминированные идентификаторы, которыми вы управляете; сгенерируйте их один раз и сохраняйте стабильными между синхронизациями.
* `applicationVariables` становятся переменными окружения для ваших функций (например, `DEFAULT_RECIPIENT_NAME` доступна как `process.env.DEFAULT_RECIPIENT_NAME`).
* `defaultRoleUniversalIdentifier` должен соответствовать файлу роли (см. ниже).
* Pre-install and post-install functions are automatically detected during the manifest build. See [Pre-install functions](#pre-install-functions) and [Post-install functions](#post-install-functions).
* Предустановочные и послеустановочные функции автоматически обнаруживаются во время сборки манифеста. См. [Предустановочные функции](#pre-install-functions) и [Послеустановочные функции](#post-install-functions).
#### Роли и разрешения
@@ -498,11 +498,11 @@ export default defineLogicFunction({
* Массив `triggers` необязателен. Функции без триггеров можно использовать как вспомогательные, вызываемые другими функциями.
* Вы можете сочетать несколько типов триггеров в одной функции.
### Pre-install functions
### Предустановочные функции
A pre-install function is a logic function that runs automatically before your app is installed on a workspace. This is useful for validation tasks, prerequisite checks, or preparing workspace state before the main installation proceeds.
Предустановочная функция — это логическая функция, которая автоматически выполняется до установки вашего приложения в рабочем пространстве. Это полезно для задач валидации, проверки предварительных условий или подготовки состояния рабочего пространства перед основной установкой.
When you scaffold a new app with `create-twenty-app`, a pre-install function is generated for you at `src/logic-functions/pre-install.ts`:
Когда вы создаёте каркас нового приложения с помощью `create-twenty-app`, для вас генерируется предустановочная функция по пути `src/logic-functions/pre-install.ts`:
```typescript
// src/logic-functions/pre-install.ts
@@ -521,7 +521,7 @@ export default definePreInstallLogicFunction({
});
```
You can also manually execute the pre-install function at any time using the CLI:
Вы также можете вручную выполнить предустановочную функцию в любое время с помощью CLI:
```bash filename="Terminal"
yarn twenty function:execute --preInstall
@@ -529,12 +529,12 @@ yarn twenty function:execute --preInstall
Основные моменты:
* Pre-install functions use `definePreInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one pre-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `preInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* The default timeout is set to 300 seconds (5 minutes) to allow for longer preparation tasks.
* Pre-install functions do not need triggers — they are invoked by the platform before installation or manually via `function:execute --preInstall`.
* Предустановочные функции используют `definePreInstallLogicFunction()` — специализированный вариант, который опускает настройки триггеров (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* Обработчик получает `InstallLogicFunctionPayload` с `{ previousVersion: string }` — версией приложения, которая была установлена ранее (или пустой строкой для новых установок).
* Для каждого приложения допускается только одна предустановочная функция. Сборка манифеста завершится ошибкой, если будет обнаружено более одной такой функции.
* Параметр `universalIdentifier` функции автоматически устанавливается как `preInstallLogicFunctionUniversalIdentifier` в манифесте приложения во время сборки — вам не нужно ссылаться на него в `defineApplication()`.
* Тайм-аут по умолчанию установлен на 300 секунд (5 минут), чтобы обеспечить выполнение более длительных задач подготовки.
* Предустановочным функциям не нужны триггеры — платформа вызывает их перед установкой или вручную через `function:execute --preInstall`.
### Послеустановочные функции
@@ -567,10 +567,10 @@ yarn twenty function:execute --postInstall
Основные моменты:
* Post-install functions use `definePostInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one post-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `postInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* Послеустановочные функции используют `definePostInstallLogicFunction()` — специализированный вариант, который опускает настройки триггеров (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* Обработчик получает `InstallLogicFunctionPayload` с `{ previousVersion: string }` — версией приложения, которая была установлена ранее (или пустой строкой для новых установок).
* Для каждого приложения допускается только одна послеустановочная функция. Сборка манифеста завершится ошибкой, если будет обнаружено более одной такой функции.
* Параметр `universalIdentifier` функции автоматически устанавливается как `postInstallLogicFunctionUniversalIdentifier` в манифесте приложения во время сборки — вам не нужно ссылаться на него в `defineApplication()`.
* Тайм-аут по умолчанию установлен на 300 секунд (5 минут), чтобы позволить выполнять более длительные задачи настройки, такие как инициализация данных.
* Постустановочным функциям не нужны триггеры — платформа вызывает их во время установки или вручную через `function:execute --postInstall`.
@@ -21,7 +21,7 @@ export const MyComponent = () => {
const [selectedIcon, setSelectedIcon] = useState("");
const handleIconChange = ({ iconKey, Icon }) => {
console.log("Selected Icon:", iconKey);
console.log("Выбранная иконка:", iconKey);
setSelectedIcon(iconKey);
};
@@ -23,10 +23,10 @@ export const MyComponent = () => {
<Select
className
disabled={false}
label="Select an option"
label="Выберите вариант"
options={[
{ value: 'option1', label: 'Option A', Icon: IconTwentyStar },
{ value: 'option2', label: 'Option B', Icon: IconTwentyStar },
{ value: 'option1', label: 'Вариант A', Icon: IconTwentyStar },
{ value: 'option2', label: 'Вариант B', Icon: IconTwentyStar },
]}
value="option1"
/>
@@ -20,21 +20,21 @@ import { TextInput } from "@/ui/input/components/TextInput";
export const MyComponent = () => {
const handleChange = (text) => {
console.log("Input changed:", text);
console.log("Ввод изменён:", text);
};
const handleKeyDown = (event) => {
console.log("Key pressed:", event.key);
console.log("Нажата клавиша:", event.key);
};
return (
<TextInput
className
label="Username"
label="Имя пользователя"
onChange={handleChange}
fullWidth={false}
disableHotkeys={false}
error="Invalid username"
error="Недопустимое имя пользователя"
onKeyDown={handleKeyDown}
RightIcon={null}
/>
@@ -83,13 +83,13 @@ import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
export const MyComponent = () => {
return (
<AutosizeTextInput
onValidate={() => console.log("onValidate function fired")}
onValidate={() => console.log("Функция onValidate вызвана")}
minRows={1}
placeholder="Write a comment"
onFocus={() => console.log("onFocus function fired")}
placeholder="Напишите комментарий"
onFocus={() => console.log("Функция onFocus вызвана")}
variant="icon"
buttonTitle
value="Task: "
value="Задача: "
/>
);
};
@@ -6,9 +6,9 @@ Bu belge, ön yüz üzerinde çalışırken takip etmeniz gereken en iyi uygulam
## Durum Yönetimi
React and Jotai handle state management in the codebase.
React ve Jotai, kod tabanında durumu yönetir.
### Use Jotai atoms to store state
### Durumu depolamak için Jotai atomlarını kullanın
Durumunuzu depolamak için ihtiyaç duyduğunuz kadar atom oluşturmak iyi bir uygulamadır.
@@ -45,7 +45,7 @@ export const MyComponent = () => {
Durum saklamak için `useRef` kullanmaktan kaçının.
If you want to store state, you should use `useState` or Jotai atoms with `useAtomState`.
Durum saklamak istiyorsanız, `useState` veya `useAtomState` ile Jotai atomlarını kullanmalısınız.
Bazı yeniden render edilmelerin olmasını önlemek için `useRef`'e ihtiyacınız varmış gibi hissediyorsanız, [yeniden render yönetimi](#managing-re-renders) konusuna bakın.
@@ -82,8 +82,8 @@ Kök bileşenize bir `useEffect` eklemeniz gerektiğini hissediyorsanız, bunu b
Aynısını Apollo kancaları ile veri çekme mantığı için de uygulayabilirsiniz.
```tsx
// ❌ Bad, will cause re-renders even if data is not changing,
// because useEffect needs to be re-evaluated
// ❌ Kötü, veri değişmese bile yeniden render'a neden olacak,
// çünkü useEffect'in yeniden değerlendirilmesi gerekiyor
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
const [someDependency] = useAtomState(someDependencyState);
@@ -103,8 +103,8 @@ export const App = () => (
```
```tsx
// ✅ Good, will not cause re-renders if data is not changing,
// because useEffect is re-evaluated in another sibling component
// ✅ İyi, veri değişmiyorsa yeniden render'a neden olmaz,
// çünkü useEffect başka bir kardeş bileşende yeniden değerlendirilir
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
@@ -132,9 +132,9 @@ export const App = () => (
);
```
### Use atom family states and selectors
### Atom aile durumlarını ve seçimcilerini kullanın
Atom family states and selectors are a great way to avoid re-renders.
Atom aile durumları ve seçimcileri, yeniden render'ları önlemenin harika bir yoludur.
Bir öğe listesini saklamanız gerektiğinde kullanılabilirdir.
@@ -77,7 +77,7 @@ Gereksiz [yeniden renderların](/l/tr/developers/contribute/capabilities/fronten
### Durum Yönetimi
[Jotai](https://jotai.org/) handles state management.
[Jotai](https://jotai.org/) durum yönetimini ele alır.
Durum yönetimi hakkında daha fazla bilgi için [en iyi uygulamalar](/l/tr/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) bölümüne bakın.
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
}
```
Internally, the currently selected scope is stored in a Jotai atom that is shared across the application :
Dahili olarak, şu anda seçili olan kapsam, uygulama genelinde paylaşılan bir Jotai atomunda saklanır:
```tsx
export const currentHotkeyScopeState = createState<HotkeyScope>({
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
});
```
But this atom should never be handled manually ! Bunu bir sonraki bölümde nasıl kullanacağımızı göreceğiz.
Ancak bu atom asla el ile yönetilmemelidir! Bunu bir sonraki bölümde nasıl kullanacağımızı göreceğiz.
## İçsel olarak nasıl çalışıyor?
Gereksiz yeniden render etme işlemlerinden kaçınarak daha performanslı hale getiren [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) üzerine ince bir sarmalayıcı yaptık.
We also create a Jotai atom to handle the hotkey scope state and make it available everywhere in the application.
Ayrıca, kısayol kapsamı durumunu yönetmek ve uygulamanın her yerinde kullanılabilir hale getirmek için bir Jotai atomu oluşturuyoruz.
@@ -83,7 +83,7 @@ Ayrıca bkz.: [create-twenty-app](https://www.npmjs.com/package/create-twenty-ap
* Minimal bir temel uygulamayı `my-twenty-app/` içine kopyalar
* Yerel bir `twenty-sdk` bağımlılığı ve Yarn 4 yapılandırması ekler
* `twenty` CLI ile bağlantılı yapılandırma dosyaları ve betikler oluşturur
* Generates core files (application config, default function role, pre-install and post-install functions) plus example files based on the scaffolding mode
* İskelet oluşturma moduna bağlı olarak çekirdek dosyaları (uygulama yapılandırması, varsayılan işlev rolü, kurulum öncesi ve kurulum sonrası işlevler) ile örnek dosyaları üretir
Varsayılan `--exhaustive` moduyla yeni oluşturulmuş bir uygulama şu şekilde görünür:
@@ -99,30 +99,30 @@ my-twenty-app/
eslint.config.mjs
tsconfig.json
README.md
public/ # Public assets folder (images, fonts, etc.)
public/ # Genel varlıklar klasörü (görseller, yazı tipleri vb.)
src/
├── application-config.ts # Required - main application configuration
├── application-config.ts # Gerekli - ana uygulama yapılandırması
├── roles/
│ └── default-role.ts # Default role for logic functions
│ └── default-role.ts # Mantık fonksiyonları için varsayılan rol
├── objects/
│ └── example-object.ts # Example custom object definition
│ └── example-object.ts # Örnek özel nesne tanımı
├── fields/
│ └── example-field.ts # Example standalone field definition
│ └── example-field.ts # Örnek bağımsız alan tanımı
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── pre-install.ts # Pre-install logic function
│ └── post-install.ts # Post-install logic function
│ ├── hello-world.ts # Örnek mantık fonksiyonu
│ ├── pre-install.ts # Kurulum öncesi mantık fonksiyonu
│ └── post-install.ts # Kurulum sonrası mantık fonksiyonu
├── front-components/
│ └── hello-world.tsx # Example front component
│ └── hello-world.tsx # Örnek ön bileşen
├── views/
│ └── example-view.ts # Example saved view definition
│ └── example-view.ts # Örnek kaydedilmiş görünüm tanımı
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
│ └── example-navigation-menu-item.ts # Örnek kenar çubuğu gezinme bağlantısı
└── skills/
└── example-skill.ts # Example AI agent skill definition
└── example-skill.ts # Örnek yapay zekâ ajanı yetenek tanımı
```
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`). `--interactive` ile hangi örnek dosyaların dahil edileceğini siz seçersiniz.
`--minimal` ile yalnızca çekirdek dosyalar oluşturulur (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` ve `logic-functions/post-install.ts`). `--interactive` ile hangi örnek dosyaların dahil edileceğini siz seçersiniz.
Genel hatlarıyla:
@@ -139,18 +139,18 @@ Genel hatlarıyla:
SDK, TypeScript dosyalarınızı **`export default define<Entity>({...})`** çağrılarını arayarak ayrıştırıp varlıkları algılar. Her varlık türünün, `twenty-sdk` tarafından dışa aktarılan karşılık gelen bir yardımcı fonksiyonu vardır:
| Yardımcı fonksiyon | Varlık türü |
| ---------------------------------- | ----------------------------------------------------- |
| `defineObject()` | Özel nesne tanımları |
| `defineLogicFunction()` | Mantık fonksiyon tanımları |
| `definePreInstallLogicFunction()` | Pre-install logic function (runs before installation) |
| `definePostInstallLogicFunction()` | Post-install logic function (runs after installation) |
| `defineFrontComponent()` | Front component definitions |
| `defineRole()` | Rol tanımları |
| `defineField()` | Mevcut nesneler için alan genişletmeleri |
| `defineView()` | Kaydedilmiş görünüm tanımları |
| `defineNavigationMenuItem()` | Gezinme menüsü öğesi tanımları |
| `defineSkill()` | Yapay zekâ ajanı yetenek tanımları |
| Yardımcı fonksiyon | Varlık türü |
| ---------------------------------- | -------------------------------------------------------- |
| `defineObject()` | Özel nesne tanımları |
| `defineLogicFunction()` | Mantık fonksiyon tanımları |
| `definePreInstallLogicFunction()` | Kurulum öncesi mantık işlevi (kurulumdan önce çalışır) |
| `definePostInstallLogicFunction()` | Kurulum sonrası mantık işlevi (kurulumdan sonra çalışır) |
| `defineFrontComponent()` | Front component definitions |
| `defineRole()` | Rol tanımları |
| `defineField()` | Mevcut nesneler için alan genişletmeleri |
| `defineView()` | Kaydedilmiş görünüm tanımları |
| `defineNavigationMenuItem()` | Gezinme menüsü öğesi tanımları |
| `defineSkill()` | Yapay zekâ ajanı yetenek tanımları |
<Note>
**Dosya adlandırma esnektir.** Varlık algılama AST tabanlıdır — SDK, kaynak dosyalarınızı `export default define<Entity>({...})` desenini bulmak için tarar. Dosyalarınızı ve klasörlerinizi dilediğiniz gibi düzenleyebilirsiniz. Varlık türüne göre gruplama (örn. `logic-functions/`, `roles/`) bir gereklilik değil, yalnızca kod organizasyonu için bir gelenektir.
@@ -220,8 +220,8 @@ SDK, uygulama varlıklarınızı tanımlamak için yardımcı fonksiyonlar sağl
| `defineApplication()` | Uygulama meta verilerini yapılandırın (zorunlu, uygulama başına bir adet) |
| `defineObject()` | Alanlara sahip özel nesneler tanımlayın |
| `defineLogicFunction()` | İşleyicilerle mantık fonksiyonları tanımlayın |
| `definePreInstallLogicFunction()` | Define a pre-install logic function (one per app) |
| `definePostInstallLogicFunction()` | Define a post-install logic function (one per app) |
| `definePreInstallLogicFunction()` | Bir kurulum öncesi mantık işlevi tanımlayın (uygulama başına bir adet) |
| `definePostInstallLogicFunction()` | Bir kurulum sonrası mantık işlevi tanımlayın (uygulama başına bir adet) |
| `defineFrontComponent()` | Özel kullanıcı arayüzü için ön uç bileşenlerini tanımlayın |
| `defineRole()` | Rol izinlerini ve nesne erişimini yapılandırın |
| `defineField()` | Mevcut nesneleri ek alanlarla genişletin |
@@ -327,7 +327,7 @@ Her uygulamanın aşağıdakileri açıklayan tek bir `application-config.ts` do
* **Uygulamanın kim olduğu**: tanımlayıcılar, görünen ad ve açıklama.
* **Fonksiyonlarının nasıl çalıştığı**: izinler için hangi rolü kullandıkları.
* **(İsteğe bağlı) değişkenler**: fonksiyonlarınıza ortam değişkenleri olarak sunulan anahtardeğer çiftleri.
* **(Optional) pre-install function**: a logic function that runs before the app is installed.
* **(İsteğe bağlı) kurulum öncesi işlev**: uygulama yüklenmeden önce çalışan bir mantık işlevi.
* **(İsteğe bağlı) kurulum sonrası işlev**: uygulama yüklendikten sonra çalışan bir mantık işlevi.
Uygulama yapılandırmanızı tanımlamak için `defineApplication()` kullanın:
@@ -359,7 +359,7 @@ Notlar:
* `universalIdentifier` alanları size ait belirleyici kimliklerdir; bunları bir kez oluşturun ve eşitlemeler boyunca kararlı tutun.
* `applicationVariables`, fonksiyonlarınız için ortam değişkenlerine dönüşür (örneğin, `DEFAULT_RECIPIENT_NAME` değeri `process.env.DEFAULT_RECIPIENT_NAME` olarak kullanılabilir).
* `defaultRoleUniversalIdentifier`, rol dosyasıyla eşleşmelidir (aşağıya bakın).
* Pre-install and post-install functions are automatically detected during the manifest build. See [Pre-install functions](#pre-install-functions) and [Post-install functions](#post-install-functions).
* Kurulum öncesi ve kurulum sonrası işlevler, manifest oluşturma sırasında otomatik olarak algılanır. Bkz. [Kurulum öncesi işlevler](#pre-install-functions) ve [Kurulum sonrası işlevler](#post-install-functions).
#### Roller ve izinler
@@ -498,11 +498,11 @@ Notlar:
* `triggers` dizisi isteğe bağlıdır. Tetikleyicisi olmayan fonksiyonlar, diğer fonksiyonlar tarafından çağrılan yardımcı fonksiyonlar olarak kullanılabilir.
* Tek bir fonksiyonda birden çok tetikleyici türünü birleştirebilirsiniz.
### Pre-install functions
### Kurulum öncesi işlevler
A pre-install function is a logic function that runs automatically before your app is installed on a workspace. This is useful for validation tasks, prerequisite checks, or preparing workspace state before the main installation proceeds.
Kurulum öncesi işlev, uygulamanız bir çalışma alanına yüklenmeden önce otomatik olarak çalışan bir mantık işlevidir. Bu, doğrulama görevleri, önkoşul kontrolleri veya ana kurulum başlamadan önce çalışma alanı durumunun hazırlanması için yararlıdır.
When you scaffold a new app with `create-twenty-app`, a pre-install function is generated for you at `src/logic-functions/pre-install.ts`:
`create-twenty-app` ile yeni bir uygulama iskeleti oluşturduğunuzda, `src/logic-functions/pre-install.ts` konumunda sizin için bir kurulum öncesi işlev oluşturulur:
```typescript
// src/logic-functions/pre-install.ts
@@ -521,7 +521,7 @@ export default definePreInstallLogicFunction({
});
```
You can also manually execute the pre-install function at any time using the CLI:
Ayrıca kurulum öncesi işlevi istediğiniz zaman CLI kullanarak manuel olarak çalıştırabilirsiniz:
```bash filename="Terminal"
yarn twenty function:execute --preInstall
@@ -529,12 +529,12 @@ yarn twenty function:execute --preInstall
Önemli noktalar:
* Pre-install functions use `definePreInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one pre-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `preInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* The default timeout is set to 300 seconds (5 minutes) to allow for longer preparation tasks.
* Pre-install functions do not need triggers — they are invoked by the platform before installation or manually via `function:execute --preInstall`.
* Kurulum öncesi işlevler `definePreInstallLogicFunction()` kullanır — tetikleyici ayarlarını atlayan (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`) özel bir varyanttır.
* İşleyici, `{ previousVersion: string }` içeren bir `InstallLogicFunctionPayload` alır — daha önce yüklü olan uygulamanın sürümü (veya yeni kurulumlar için boş bir dize).
* Uygulama başına yalnızca bir kurulum öncesi işlevine izin verilir. Birden fazla tespit edilirse manifest oluşturma hataya düşer.
* İşlevin `universalIdentifier` değeri, oluşturma sırasında uygulama manifestinde otomatik olarak `preInstallLogicFunctionUniversalIdentifier` olarak ayarlanır — `defineApplication()` içinde buna atıfta bulunmanıza gerek yoktur.
* Varsayılan zaman aşımı, daha uzun hazırlık görevlerine izin vermek için 300 saniye (5 dakika) olarak ayarlanmıştır.
* Kurulum öncesi işlevlerin tetikleyicilere ihtiyacı yoktur — kurulumdan önce platform tarafından veya `function:execute --preInstall` aracılığıyla manuel olarak çağrılırlar.
### Kurulum sonrası işlevler
@@ -567,10 +567,10 @@ yarn twenty function:execute --postInstall
Önemli noktalar:
* Post-install functions use `definePostInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one post-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `postInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* Kurulum sonrası işlevler `definePostInstallLogicFunction()` kullanır — tetikleyici ayarlarını atlayan (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`) özel bir varyanttır.
* İşleyici, `{ previousVersion: string }` içeren bir `InstallLogicFunctionPayload` alır — daha önce yüklü olan uygulamanın sürümü (veya yeni kurulumlar için boş bir dize).
* Uygulama başına yalnızca bir kurulum sonrası işlevine izin verilir. Birden fazla tespit edilirse manifest oluşturma hataya düşer.
* İşlevin `universalIdentifier` değeri, oluşturma sırasında uygulama manifestinde otomatik olarak `postInstallLogicFunctionUniversalIdentifier` olarak ayarlanır — `defineApplication()` içinde buna atıfta bulunmanıza gerek yoktur.
* Varsayılan zaman aşımı, veri tohumlama gibi daha uzun kurulum görevlerine izin vermek için 300 saniye (5 dakika) olarak ayarlanmıştır.
* Kurulum sonrası işlevlerin tetikleyicilere ihtiyacı yoktur — kurulum sırasında platform tarafından veya `function:execute --postInstall` aracılığıyla manuel olarak çağrılırlar.
@@ -21,7 +21,7 @@ export const MyComponent = () => {
const [selectedIcon, setSelectedIcon] = useState("");
const handleIconChange = ({ iconKey, Icon }) => {
console.log("Selected Icon:", iconKey);
console.log("Seçilen Simge:", iconKey);
setSelectedIcon(iconKey);
};
@@ -23,10 +23,10 @@ export const MyComponent = () => {
<Select
className
disabled={false}
label="Select an option"
label="Bir seçenek seçin"
options={[
{ value: 'option1', label: 'Option A', Icon: IconTwentyStar },
{ value: 'option2', label: 'Option B', Icon: IconTwentyStar },
{ value: 'option1', label: 'Seçenek A', Icon: IconTwentyStar },
{ value: 'option2', label: 'Seçenek B', Icon: IconTwentyStar },
]}
value="option1"
/>
@@ -20,27 +20,27 @@ import { TextInput } from "@/ui/input/components/TextInput";
export const MyComponent = () => {
const handleChange = (text) => {
console.log("Input changed:", text);
console.log("Girdi değişti:", text);
};
const handleKeyDown = (event) => {
console.log("Key pressed:", event.key);
console.log("Basılan tuş:", event.key);
};
return (
<TextInput
className
label="Username"
label="Kullanıcı adı"
onChange={handleChange}
fullWidth={false}
disableHotkeys={false}
error="Invalid username"
error="Geçersiz kullanıcı adı"
onKeyDown={handleKeyDown}
RightIcon={null}
/>
);
};
},{
```
@@ -83,13 +83,13 @@ import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
export const MyComponent = () => {
return (
<AutosizeTextInput
onValidate={() => console.log("onValidate function fired")}
onValidate={() => console.log("onValidate fonksiyonu tetiklendi")}
minRows={1}
placeholder="Write a comment"
onFocus={() => console.log("onFocus function fired")}
placeholder="Bir yorum yazın"
onFocus={() => console.log("onFocus fonksiyonu tetiklendi")}
variant="icon"
buttonTitle
value="Task: "
value="Görev: "
/>
);
};
@@ -6,9 +6,9 @@ title: 最佳实践
## 状态管理
React and Jotai handle state management in the codebase.
React Jotai 在代码库中处理状态管理。
### Use Jotai atoms to store state
### 使用 Jotai 原子来存储状态
根据需要创建足够多的原子来存储你的状态,是一种良好实践。
@@ -45,7 +45,7 @@ export const MyComponent = () => {
避免使用 `useRef` 来存储状态。
If you want to store state, you should use `useState` or Jotai atoms with `useAtomState`.
如果想存储状态,应该使用 `useState` 或配合 `useAtomState` Jotai 原子。
如果您觉得需要通过使用 `useRef` 来防止一些再渲染,请了解[如何管理再渲染](#managing-re-renders)。
@@ -82,8 +82,8 @@ If you feel like you need to add a `useEffect` in your root component, you shoul
对于数据获取逻辑也可以采用相同的方法,使用 Apollo hooks。
```tsx
// ❌ Bad, will cause re-renders even if data is not changing,
// because useEffect needs to be re-evaluated
// ❌ 不佳:即使数据未发生变化也会导致重新渲染,
// 因为需要重新评估 useEffect
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
const [someDependency] = useAtomState(someDependencyState);
@@ -103,8 +103,8 @@ export const App = () => (
```
```tsx
// ✅ Good, will not cause re-renders if data is not changing,
// because useEffect is re-evaluated in another sibling component
// ✅ 良好:如果数据未发生变化,将不会导致重新渲染,
// 因为 useEffect 会在另一个同级组件中重新评估
export const PageComponent = () => {
const [data, setData] = useAtomState(dataState);
@@ -132,9 +132,9 @@ export const App = () => (
);
```
### Use atom family states and selectors
### 使用原子族状态和选择器
Atom family states and selectors are a great way to avoid re-renders.
原子族状态和选择器是避免重新渲染的好方法。
当您需要存储项目列表时,它们很有用。
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/zh/developers/contribute/capabilities/front
### 状态管理
[Jotai](https://jotai.org/) handles state management.
[Jotai](https://jotai.org/) 处理状态管理。
查看[最佳实践](/l/zh/developers/contribute/capabilities/frontend-development/best-practices-front#state-management)以获取有关状态管理的更多信息。
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
}
```
Internally, the currently selected scope is stored in a Jotai atom that is shared across the application :
在内部,当前选择的范围存储在整个应用程序共享的 Jotai 原子中:
```tsx
export const currentHotkeyScopeState = createState<HotkeyScope>({
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
});
```
But this atom should never be handled manually ! 我们将在下一节中学习如何使用它。
但这个原子不应该手动处理! 我们将在下一节中学习如何使用它。
## 内部是如何运作的?
我们在 [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) 之上制作了一个薄包装,使其性能更高并避免不必要的重新渲染。
We also create a Jotai atom to handle the hotkey scope state and make it available everywhere in the application.
我们还创建了一个 Jotai 原子来处理快捷键范围状态,并使其在整个应用程序中可用。
@@ -52,25 +52,25 @@ npx create-twenty-app@latest my-app --interactive
从这里您可以:
```bash filename="Terminal"
# Add a new entity to your application (guided)
# 向你的应用添加一个新实体(引导式)
yarn twenty entity:add
# Watch your application's function logs
# 监听你的应用函数日志
yarn twenty function:logs
# Execute a function by name
# 按名称执行一个函数
yarn twenty function:execute -n my-function -p '{"name": "test"}'
# Execute the pre-install function
# 执行安装前函数
yarn twenty function:execute --preInstall
# Execute the post-install function
# 执行安装后函数
yarn twenty function:execute --postInstall
# Uninstall the application from the current workspace
# 从当前工作区卸载该应用
yarn twenty app:uninstall
# Display commands' help
# 显示命令帮助
yarn twenty help
```
@@ -83,7 +83,7 @@ yarn twenty help
* 将一个最小的基础应用复制到 `my-twenty-app/` 中
* 添加本地 `twenty-sdk` 依赖和 Yarn 4 配置
* 创建与 `twenty` CLI 关联的配置文件和脚本
* Generates core files (application config, default function role, pre-install and post-install functions) plus example files based on the scaffolding mode
* 生成核心文件(应用配置、默认函数角色、安装前/安装后函数),并基于脚手架模式生成示例文件
A freshly scaffolded app with the default `--exhaustive` mode looks like this:
@@ -99,30 +99,30 @@ my-twenty-app/
eslint.config.mjs
tsconfig.json
README.md
public/ # Public assets folder (images, fonts, etc.)
public/ # 公共资源文件夹(图片、字体等)
src/
├── application-config.ts # Required - main application configuration
├── application-config.ts # 必需 - 主应用配置
├── roles/
│ └── default-role.ts # Default role for logic functions
│ └── default-role.ts # 逻辑函数的默认角色
├── objects/
│ └── example-object.ts # Example custom object definition
│ └── example-object.ts # 示例自定义对象定义
├── fields/
│ └── example-field.ts # Example standalone field definition
│ └── example-field.ts # 示例独立字段定义
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── pre-install.ts # Pre-install logic function
│ └── post-install.ts # Post-install logic function
│ ├── hello-world.ts # 示例逻辑函数
│ ├── pre-install.ts # 安装前逻辑函数
│ └── post-install.ts # 安装后逻辑函数
├── front-components/
│ └── hello-world.tsx # Example front component
│ └── hello-world.tsx # 示例前端组件
├── views/
│ └── example-view.ts # Example saved view definition
│ └── example-view.ts # 示例已保存视图定义
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
│ └── example-navigation-menu-item.ts # 示例侧边栏导航链接
└── skills/
└── example-skill.ts # Example AI agent skill definition
└── example-skill.ts # 示例 AI 代理技能定义
```
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`). With `--interactive`, you choose which example files to include.
使用 `--minimal` 时,只会创建核心文件(`application-config.ts``roles/default-role.ts``logic-functions/pre-install.ts` `logic-functions/post-install.ts`)。 With `--interactive`, you choose which example files to include.
总体来说:
@@ -139,18 +139,18 @@ With `--minimal`, only the core files are created (`application-config.ts`, `rol
该 SDK 通过在你的 TypeScript 文件中解析 **`export default define<Entity>({...})`** 调用来检测实体。 每种实体类型都有一个从 `twenty-sdk` 导出的对应辅助函数:
| 辅助函数 | 实体类型 |
| ---------------------------------- | ----------------------------------------------------- |
| `defineObject()` | 自定义对象定义 |
| `defineLogicFunction()` | 逻辑函数定义 |
| `definePreInstallLogicFunction()` | Pre-install logic function (runs before installation) |
| `definePostInstallLogicFunction()` | Post-install logic function (runs after installation) |
| `defineFrontComponent()` | 前端组件定义 |
| `defineRole()` | 角色定义 |
| `defineField()` | 现有对象的字段扩展 |
| `defineView()` | Saved view definitions |
| `defineNavigationMenuItem()` | Navigation menu item definitions |
| `defineSkill()` | AI agent skill definitions |
| 辅助函数 | 实体类型 |
| ---------------------------------- | -------------------------------- |
| `defineObject()` | 自定义对象定义 |
| `defineLogicFunction()` | 逻辑函数定义 |
| `definePreInstallLogicFunction()` | 安装前逻辑函数(在安装之前运行) |
| `definePostInstallLogicFunction()` | 安装后逻辑函数(在安装之后运行) |
| `defineFrontComponent()` | 前端组件定义 |
| `defineRole()` | 角色定义 |
| `defineField()` | 现有对象的字段扩展 |
| `defineView()` | Saved view definitions |
| `defineNavigationMenuItem()` | Navigation menu item definitions |
| `defineSkill()` | AI agent skill definitions |
<Note>
**文件命名是灵活的。** 实体检测基于 AST — SDK 会扫描你的源文件以查找 `export default define<Entity>({...})` 模式。 你可以按照自己的喜好组织文件和文件夹。 按实体类型分组(例如 `logic-functions/`、`roles/`)只是代码组织的一种约定,并非必需。
@@ -215,19 +215,19 @@ twenty-sdk 提供你在应用中使用的类型化构件和辅助函数。 以
该 SDK 提供辅助函数用于定义你的应用实体。 如 [实体检测](#entity-detection) 中所述,你必须使用 `export default define<Entity>({...})` 才能让你的实体被检测到:
| 函数 | 目的 |
| ---------------------------------- | -------------------------------------------------- |
| `defineApplication()` | 配置应用元数据(必需,每个应用一个) |
| `defineObject()` | 定义带字段的自定义对象 |
| `defineLogicFunction()` | 定义带处理程序的逻辑函数 |
| `definePreInstallLogicFunction()` | Define a pre-install logic function (one per app) |
| `definePostInstallLogicFunction()` | Define a post-install logic function (one per app) |
| `defineFrontComponent()` | 为自定义 UI 定义前端组件 |
| `defineRole()` | 配置角色权限和对象访问 |
| `defineField()` | 为现有对象扩展额外字段 |
| `defineView()` | Define saved views for objects |
| `defineNavigationMenuItem()` | Define sidebar navigation links |
| `defineSkill()` | Define AI agent skills |
| 函数 | 目的 |
| ---------------------------------- | ------------------------------- |
| `defineApplication()` | 配置应用元数据(必需,每个应用一个) |
| `defineObject()` | 定义带字段的自定义对象 |
| `defineLogicFunction()` | 定义带处理程序的逻辑函数 |
| `definePreInstallLogicFunction()` | 定义一个安装前逻辑函数(每个应用一个) |
| `definePostInstallLogicFunction()` | 定义一个安装后逻辑函数(每个应用一个) |
| `defineFrontComponent()` | 为自定义 UI 定义前端组件 |
| `defineRole()` | 配置角色权限和对象访问 |
| `defineField()` | 为现有对象扩展额外字段 |
| `defineView()` | Define saved views for objects |
| `defineNavigationMenuItem()` | Define sidebar navigation links |
| `defineSkill()` | Define AI agent skills |
这些函数会在构建时校验你的配置,并提供 IDE 自动补全和类型安全。
@@ -327,7 +327,7 @@ export default defineObject({
* **应用的身份**:标识符、显示名称和描述。
* **函数如何运行**:它们用于权限的角色。
* **(可选)变量**:以环境变量形式提供给函数的键值对。
* **(Optional) pre-install function**: a logic function that runs before the app is installed.
* **(可选)安装前函数**:在应用安装之前运行的逻辑函数。
* **(可选)安装后函数**:在应用安装后运行的逻辑函数。
使用 `defineApplication()` 定义你的应用配置:
@@ -359,7 +359,7 @@ export default defineApplication({
* `universalIdentifier` 字段是你拥有的确定性 ID;生成一次并在多次同步中保持稳定。
* `applicationVariables` 会变成函数可用的环境变量(例如,`DEFAULT_RECIPIENT_NAME` 可作为 `process.env.DEFAULT_RECIPIENT_NAME` 使用)。
* `defaultRoleUniversalIdentifier` 必须与角色文件一致(见下文)。
* Pre-install and post-install functions are automatically detected during the manifest build. See [Pre-install functions](#pre-install-functions) and [Post-install functions](#post-install-functions).
* 清单构建期间会自动检测安装前和安装后函数。 参见 [安装前函数](#pre-install-functions) 和 [安装后函数](#post-install-functions)
#### 角色和权限
@@ -498,11 +498,11 @@ export default defineLogicFunction({
* `triggers` 数组是可选的。 没有触发器的函数可作为实用函数,被其他函数调用。
* 你可以在单个函数中混用多种触发器类型。
### Pre-install functions
### 安装前函数
A pre-install function is a logic function that runs automatically before your app is installed on a workspace. This is useful for validation tasks, prerequisite checks, or preparing workspace state before the main installation proceeds.
安装前函数是在你的应用安装到工作区之前自动运行的逻辑函数。 这对于执行验证任务、先决条件检查,或在主安装开始前准备工作区状态很有用。
When you scaffold a new app with `create-twenty-app`, a pre-install function is generated for you at `src/logic-functions/pre-install.ts`:
当你使用 `create-twenty-app` 脚手架创建一个新应用时,会在 `src/logic-functions/pre-install.ts` 为你生成一个安装前函数:
```typescript
// src/logic-functions/pre-install.ts
@@ -521,7 +521,7 @@ export default definePreInstallLogicFunction({
});
```
You can also manually execute the pre-install function at any time using the CLI:
你也可以随时使用 CLI 手动执行安装前函数:
```bash filename="Terminal"
yarn twenty function:execute --preInstall
@@ -529,12 +529,12 @@ yarn twenty function:execute --preInstall
关键点:
* Pre-install functions use `definePreInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one pre-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `preInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* The default timeout is set to 300 seconds (5 minutes) to allow for longer preparation tasks.
* Pre-install functions do not need triggers — they are invoked by the platform before installation or manually via `function:execute --preInstall`.
* 安装前函数使用 `definePreInstallLogicFunction()` —— 这是一个省略触发器设置(`cronTriggerSettings``databaseEventTriggerSettings``httpRouteTriggerSettings``isTool`)的专用变体。
* 处理器会接收一个 `InstallLogicFunctionPayload`,其包含 `{ previousVersion: string }` —— 即之前安装的应用版本(全新安装则为空字符串)。
* 每个应用仅允许一个安装前函数。 如果检测到多个,清单构建将报错。
* 在构建期间,函数的 `universalIdentifier` 会自动设置为应用清单上的 `preInstallLogicFunctionUniversalIdentifier` —— 你无需在 `defineApplication()` 中引用它。
* 默认超时时间设置为 300 秒(5 分钟),以便支持更长的准备任务。
* 安装前函数不需要触发器——它们会在安装前由平台调用,或通过 `function:execute --preInstall` 手动调用。
### 安装后函数
@@ -567,10 +567,10 @@ yarn twenty function:execute --postInstall
关键点:
* Post-install functions use `definePostInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
* The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
* Only one post-install function is allowed per application. The manifest build will error if more than one is detected.
* The function's `universalIdentifier` is automatically set as `postInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
* 安装后函数使用 `definePostInstallLogicFunction()` —— 这是一个省略触发器设置(`cronTriggerSettings``databaseEventTriggerSettings``httpRouteTriggerSettings``isTool`)的专用变体。
* 处理器会接收一个 `InstallLogicFunctionPayload`,其包含 `{ previousVersion: string }` —— 即之前安装的应用版本(全新安装则为空字符串)。
* 每个应用仅允许一个安装后函数。 如果检测到多个,清单构建将报错。
* 在构建期间,函数的 `universalIdentifier` 会自动设置为应用清单上的 `postInstallLogicFunctionUniversalIdentifier` —— 你无需在 `defineApplication()` 中引用它。
* The default timeout is set to 300 seconds (5 minutes) to allow for longer setup tasks like data seeding.
* Post-install functions do not need triggers — they are invoked by the platform during installation or manually via `function:execute --postInstall`.
@@ -23,10 +23,10 @@ export const MyComponent = () => {
<Select
className
disabled={false}
label="Select an option"
label="选择一个选项"
options={[
{ value: 'option1', label: 'Option A', Icon: IconTwentyStar },
{ value: 'option2', label: 'Option B', Icon: IconTwentyStar },
{ value: 'option1', label: '选项 A', Icon: IconTwentyStar },
{ value: 'option2', label: '选项 B', Icon: IconTwentyStar },
]}
value="option1"
/>
@@ -20,27 +20,27 @@ import { TextInput } from "@/ui/input/components/TextInput";
export const MyComponent = () => {
const handleChange = (text) => {
console.log("Input changed:", text);
console.log("输入已更改:", text);
};
const handleKeyDown = (event) => {
console.log("Key pressed:", event.key);
console.log("按下的键:", event.key);
};
return (
<TextInput
className
label="Username"
label="用户名"
onChange={handleChange}
fullWidth={false}
disableHotkeys={false}
error="Invalid username"
error="用户名无效"
onKeyDown={handleKeyDown}
RightIcon={null}
/>
);
};
},{
```
@@ -83,13 +83,13 @@ import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
export const MyComponent = () => {
return (
<AutosizeTextInput
onValidate={() => console.log("onValidate function fired")}
onValidate={() => console.log("onValidate 函数已触发")}
minRows={1}
placeholder="Write a comment"
onFocus={() => console.log("onFocus function fired")}
placeholder="写一条评论"
onFocus={() => console.log("onFocus 函数已触发")}
variant="icon"
buttonTitle
value="Task: "
value="任务: "
/>
);
};