From 6eb4c4ca4b49e68c6f13d75ab925463a8777a663 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 03:04:12 +0200 Subject: [PATCH] i18n - docs translations (#19227) Created by Github action Co-authored-by: github-actions --- .../l/ar/developers/extend/apps/building.mdx | 4 +- .../l/cs/developers/extend/apps/building.mdx | 36 +- .../l/de/developers/extend/apps/building.mdx | 537 +++++++++--------- .../l/it/developers/extend/apps/building.mdx | 525 +++++++++-------- .../l/ro/developers/extend/apps/building.mdx | 524 ++++++++--------- 5 files changed, 812 insertions(+), 814 deletions(-) diff --git a/packages/twenty-docs/l/ar/developers/extend/apps/building.mdx b/packages/twenty-docs/l/ar/developers/extend/apps/building.mdx index e3b02a54b2..5fc9a078dc 100644 --- a/packages/twenty-docs/l/ar/developers/extend/apps/building.mdx +++ b/packages/twenty-docs/l/ar/developers/extend/apps/building.mdx @@ -1299,7 +1299,7 @@ yarn twenty add frontComponent | مكوّن أمامي | `yarn twenty add frontComponent` | `src/front-components/.tsx` | | دور | `yarn twenty add role` | `src/roles/.ts` | | مهارة | `yarn twenty add skill` | `src/skills/.ts` | -| Agent | `yarn twenty add agent` | `src/agents/.ts` | +| وكيل | `yarn twenty add agent` | `src/agents/.ts` | | عرض | `yarn twenty add view` | `src/views/.ts` | | عنصر قائمة التنقّل | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/.ts` | | تخطيط الصفحة | `yarn twenty add pageLayout` | `src/page-layouts/.ts` | @@ -1436,7 +1436,7 @@ const { objects } = await metadataClient.query({ #### رفع الملفات -`MetadataApiClient` includes an `uploadFile` method for attaching files to file-type fields: +يتضمن `MetadataApiClient` طريقة `uploadFile` لإرفاق الملفات بالحقول من نوع الملف: ```ts import { MetadataApiClient } from 'twenty-client-sdk/metadata'; diff --git a/packages/twenty-docs/l/cs/developers/extend/apps/building.mdx b/packages/twenty-docs/l/cs/developers/extend/apps/building.mdx index 5d5640b137..fd6748b274 100644 --- a/packages/twenty-docs/l/cs/developers/extend/apps/building.mdx +++ b/packages/twenty-docs/l/cs/developers/extend/apps/building.mdx @@ -924,24 +924,24 @@ export default defineFrontComponent({ **Operátory** — kombinují proměnné do logických výrazů: -| Operátor | Popis | -| ----------------------------------- | -------------------------------------------------------------------- | -| `isDefined(value)` | `true`, pokud hodnota není null/undefined | -| `isNonEmptyString(value)` | `true`, pokud je hodnota neprázdný řetězec | -| `includes(array, value)` | `true`, pokud pole obsahuje danou hodnotu | -| `includesEvery(array, prop, value)` | `true`, pokud vlastnost každé položky zahrnuje danou hodnotu | -| `every(array, prop)` | `true`, pokud je vlastnost u každé položky pravdivá (truthy) | -| `everyDefined(array, prop)` | `true`, pokud je vlastnost definována u každé položky | -| `everyEquals(array, prop, value)` | `true`, pokud se vlastnost rovná hodnotě u každé položky | -| `some(array, prop)` | `true`, pokud je vlastnost pravdivá (truthy) alespoň u jedné položky | -| `someDefined(array, prop)` | `true`, pokud je vlastnost definována alespoň u jedné položky | -| `someEquals(array, prop, value)` | `true`, pokud se vlastnost rovná hodnotě alespoň u jedné položky | -| `someNonEmptyString(array, prop)` | `true`, pokud je vlastnost neprázdný řetězec alespoň u jedné položky | -| `none(array, prop)` | `true`, pokud je vlastnost u všech položek nepravdivá (falsy) | -| `noneDefined(array, prop)` | `true`, pokud je vlastnost u všech položek nedefinovaná | -| `noneEquals(array, prop, value)` | `true`, pokud se vlastnost nerovná hodnotě u žádné položky | +| Operátor | Popis | +| ----------------------------------- | ------------------------------------------------------------------------------ | +| `isDefined(value)` | `true`, pokud hodnota není null/undefined | +| `isNonEmptyString(value)` | `true`, pokud je hodnota neprázdný řetězec | +| `includes(array, value)` | `true`, pokud pole obsahuje danou hodnotu | +| `includesEvery(array, prop, value)` | `true`, pokud vlastnost každé položky zahrnuje danou hodnotu | +| `every(array, prop)` | `true`, pokud je vlastnost u každé položky pravdivá (truthy) | +| `everyDefined(array, prop)` | `true`, pokud je vlastnost definována u každé položky | +| `everyEquals(array, prop, value)` | `true`, pokud se vlastnost rovná hodnotě u každé položky | +| `some(array, prop)` | `true`, pokud je vlastnost pravdivá (truthy) alespoň u jedné položky | +| `someDefined(array, prop)` | `true`, pokud je vlastnost definována alespoň u jedné položky | +| `someEquals(array, prop, value)` | `true`, pokud se vlastnost rovná hodnotě alespoň u jedné položky | +| `someNonEmptyString(array, prop)` | `true`, pokud má vlastnost alespoň u jedné položky hodnotu neprázdného řetězce | +| `none(array, prop)` | `true`, pokud je vlastnost u všech položek nepravdivá (falsy) | +| `noneDefined(array, prop)` | `true`, pokud je vlastnost u všech položek nedefinovaná | +| `noneEquals(array, prop, value)` | `true`, pokud se vlastnost nerovná hodnotě u žádné položky | -#### Veřejná aktiva +#### Veřejné soubory Frontendové komponenty mohou přistupovat k souborům ze složky aplikace `public/` pomocí `getPublicAssetUrl`: @@ -957,7 +957,7 @@ export default defineFrontComponent({ }); ``` -Podrobnosti viz [sekce veřejných aktiv](#accessing-public-assets-with-getpublicasseturl). +Podrobnosti viz [sekci veřejných souborů](#accessing-public-assets-with-getpublicasseturl). #### Styling diff --git a/packages/twenty-docs/l/de/developers/extend/apps/building.mdx b/packages/twenty-docs/l/de/developers/extend/apps/building.mdx index b44951b8ef..dbc59b6bbb 100644 --- a/packages/twenty-docs/l/de/developers/extend/apps/building.mdx +++ b/packages/twenty-docs/l/de/developers/extend/apps/building.mdx @@ -4,24 +4,24 @@ description: Definieren Sie Objekte, Logikfunktionen, Frontend-Komponenten und m --- - Apps are currently in alpha. The feature works but is still evolving. + Apps befinden sich derzeit in der Alpha-Phase. Die Funktion ist funktionsfähig, entwickelt sich jedoch noch weiter. -The `twenty-sdk` package provides typed building blocks to create your app. This page covers every entity type and API client available in the SDK. +Das Paket `twenty-sdk` stellt typisierte Bausteine zum Erstellen Ihrer App bereit. Diese Seite behandelt alle im SDK verfügbaren Entitätstypen und API-Clients. -## DefineEntity functions +## DefineEntity-Funktionen -The SDK provides functions to define your app entities. You must use `export default defineEntity({...})` for the SDK to detect your entities. Diese Funktionen validieren Ihre Konfiguration zur Build-Zeit und bieten IDE-Autovervollständigung sowie Typsicherheit. +Das SDK stellt Funktionen bereit, um die Entitäten Ihrer App zu definieren. Sie müssen `export default defineEntity({...})` verwenden, damit das SDK Ihre Entitäten erkennt. Diese Funktionen validieren Ihre Konfiguration zur Build-Zeit und bieten IDE-Autovervollständigung sowie Typsicherheit. - **File organization is up to you.** - Entity detection is AST-based — the SDK finds `export default defineEntity(...)` calls regardless of where the file lives. Grouping files by type (e.g., `logic-functions/`, `roles/`) is just a convention, not a requirement. + **Die Dateiorganisation liegt bei Ihnen.** + Die Entitätserkennung ist AST-basiert — das SDK findet Aufrufe von `export default defineEntity(...)`, unabhängig davon, wo sich die Datei befindet. Das Gruppieren von Dateien nach Typ (z. B. `logic-functions/`, `roles/`) ist lediglich eine Konvention, keine Voraussetzung. -Roles encapsulate permissions on your workspace's objects and actions. +Rollen kapseln Berechtigungen für die Objekte und Aktionen Ihres Workspaces. ```ts restricted-company-role.ts import { @@ -69,12 +69,12 @@ export default defineRole({ -Every app must have exactly one `defineApplication` call that describes: +Jede App muss genau einen Aufruf von `defineApplication` haben, der Folgendes beschreibt: -* **Identity**: identifiers, display name, and description. -* **Permissions**: which role its functions and front components use. -* **(Optional) Variables**: key–value pairs exposed to your functions as environment variables. -* **(Optional) Pre-install / post-install functions**: logic functions that run before or after installation. +* **Identität**: Bezeichner, Anzeigename und Beschreibung. +* **Berechtigungen**: welche Rolle ihre Funktionen und Frontend-Komponenten verwenden. +* **(Optional) Variablen**: Schlüssel–Wert-Paare, die Ihren Funktionen als Umgebungsvariablen zur Verfügung gestellt werden. +* **(Optional) Pre-/Post-Installationsfunktionen**: Logikfunktionen, die vor oder nach der Installation ausgeführt werden. ```ts src/application-config.ts import { defineApplication } from 'twenty-sdk'; @@ -98,21 +98,21 @@ export default defineApplication({ ``` Notizen: -* `universalIdentifier` fields are deterministic IDs you own. Generate them once and keep them stable across syncs. -* `applicationVariables` become environment variables for your functions and front components (e.g., `DEFAULT_RECIPIENT_NAME` is available as `process.env.DEFAULT_RECIPIENT_NAME`). -* `defaultRoleUniversalIdentifier` must reference a role defined with `defineRole()` (see above). -* Pre-install and post-install functions are detected automatically during the manifest build — you do not need to reference them in `defineApplication()`. +* `universalIdentifier`-Felder sind deterministische IDs, die Ihnen gehören. Erzeugen Sie sie einmal und halten Sie sie über Synchronisierungen hinweg stabil. +* `applicationVariables` werden zu Umgebungsvariablen für Ihre Funktionen und Frontend-Komponenten (z. B. ist `DEFAULT_RECIPIENT_NAME` als `process.env.DEFAULT_RECIPIENT_NAME` verfügbar). +* `defaultRoleUniversalIdentifier` muss auf eine mit `defineRole()` definierte Rolle verweisen (siehe oben). +* Pre- und Post-Installationsfunktionen werden während des Manifest-Builds automatisch erkannt — Sie müssen sie in `defineApplication()` nicht referenzieren. #### Marktplatz-Metadaten -If you plan to [publish your app](/l/de/developers/extend/apps/publishing), these optional fields control how it appears in the marketplace: +Wenn Sie planen, [Ihre App zu veröffentlichen](/l/de/developers/extend/apps/publishing), steuern diese optionalen Felder, wie Ihre App im Marktplatz erscheint: | Feld | Beschreibung | | ------------------ | -------------------------------------------------------------------------------------------------------------------------------- | | `author` | Name des Autors oder des Unternehmens | | `category` | App-Kategorie für die Filterung im Marktplatz | -| `logoUrl` | Path to your app logo (e.g., `public/logo.png`) | -| `screenshots` | Array of screenshot paths (e.g., `public/screenshot-1.png`) | +| `logoUrl` | Pfad zu Ihrem App-Logo (z. B. `public/logo.png`) | +| `screenshots` | Array von Screenshot-Pfaden (z. B. `public/screenshot-1.png`) | | `aboutDescription` | Längere Markdown-Beschreibung für den Tab "Info". Wenn weggelassen, verwendet der Marketplace die `README.md` des Pakets von npm | | `websiteUrl` | Link zu Ihrer Website | | `termsUrl` | Link zu den Nutzungsbedingungen | @@ -121,15 +121,15 @@ If you plan to [publish your app](/l/de/developers/extend/apps/publishing), thes #### Rollen und Berechtigungen -The `defaultRoleUniversalIdentifier` in `application-config.ts` designates the default role used by your app's logic functions and front components. See `defineRole` above for details. +Das Feld `defaultRoleUniversalIdentifier` in `application-config.ts` legt die Standardrolle fest, die von den Logikfunktionen und Frontend-Komponenten Ihrer App verwendet wird. Details finden Sie oben unter `defineRole`. -* The runtime token injected as `TWENTY_APP_ACCESS_TOKEN` is derived from this role. -* The typed client is restricted to the permissions granted to that role. -* Follow least-privilege: create a dedicated role with only the permissions your functions need. +* Das zur Laufzeit als `TWENTY_APP_ACCESS_TOKEN` injizierte Token wird aus dieser Rolle abgeleitet. +* Der typisierte Client ist auf die dieser Rolle gewährten Berechtigungen beschränkt. +* Befolgen Sie das Least-Privilege-Prinzip: Erstellen Sie eine dedizierte Rolle nur mit den Berechtigungen, die Ihre Funktionen benötigen. -##### Default function role +##### Standard-Funktionsrolle -When you scaffold a new app, the CLI creates a default role file: +Wenn Sie eine neue App erzeugen, erstellt die CLI eine Standard-Rolldatei: ```ts src/roles/default-role.ts import { defineRole, PermissionFlag } from 'twenty-sdk'; @@ -155,16 +155,16 @@ export default defineRole({ }); ``` -This role's `universalIdentifier` is referenced in `application-config.ts` as `defaultRoleUniversalIdentifier`: +Der `universalIdentifier` dieser Rolle wird in `application-config.ts` als `defaultRoleUniversalIdentifier` referenziert: -* **\*.role.ts** defines what the role can do. +* **\*.role.ts** definiert, was die Rolle darf. * **application-config.ts** verweist auf diese Rolle, sodass Ihre Funktionen deren Berechtigungen erben. Notizen: * Beginnen Sie mit der vorab erstellten Rolle und schränken Sie sie schrittweise gemäß dem Least-Privilege-Prinzip ein. -* Replace `objectPermissions` and `fieldPermissions` with the objects and fields your functions actually need. -* `permissionFlags` steuern den Zugriff auf Funktionen auf Plattformebene. Keep them minimal. -* See a working example: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). +* Ersetzen Sie `objectPermissions` und `fieldPermissions` durch die Objekte und Felder, die Ihre Funktionen tatsächlich benötigen. +* `permissionFlags` steuern den Zugriff auf Funktionen auf Plattformebene. Halten Sie sie minimal. +* Ein funktionierendes Beispiel finden Sie unter: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). @@ -256,7 +256,7 @@ dies wird jedoch nicht empfohlen. - + Verwenden Sie `defineField()`, um Objekten, die Ihnen nicht gehören — etwa Standardobjekten von Twenty (Person, Company usw.) — Felder hinzuzufügen oder Objekten aus anderen Apps. Im Gegensatz zu Inline-Feldern in `defineObject()` benötigen eigenständige Felder einen `objectUniversalIdentifier`, um anzugeben, welches Objekt sie erweitern: @@ -284,7 +284,7 @@ Hauptpunkte: * `defineField()` ist die einzige Möglichkeit, Felder zu Objekten hinzuzufügen, die Sie nicht mit `defineObject()` erstellt haben. - + Relationen verbinden Objekte miteinander. In Twenty sind Relationen stets **bidirektional** — Sie definieren beide Seiten, und jede Seite referenziert die andere. @@ -443,7 +443,7 @@ export default defineObject({ }); ``` - + Jede Funktionsdatei verwendet `defineLogicFunction()`, um eine Konfiguration mit einem Handler und optionalen Triggern zu exportieren. @@ -487,15 +487,15 @@ export default defineLogicFunction({ }); ``` -Available trigger types: -* **httpRoute**: Exposes your function on an HTTP path and method **under the `/s/` endpoint**: -> e.g. `path: '/post-card/create'` is callable at `https://your-twenty-server.com/s/post-card/create` +Verfügbare Trigger-Typen: +* **httpRoute**: Stellt Ihre Funktion unter einem HTTP-Pfad und einer Methode **unter dem Endpunkt `/s/`** bereit: +> z. B. `path: '/post-card/create'` ist unter `https://your-twenty-server.com/s/post-card/create` aufrufbar * **cron**: Führt Ihre Funktion nach Zeitplan mithilfe eines CRON-Ausdrucks aus. * **databaseEvent**: Wird bei Lebenszyklusereignissen von Workspace-Objekten ausgeführt. Wenn die Ereignisoperation `updated` ist, können bestimmte zu überwachende Felder im Array `updatedFields` angegeben werden. Wenn das Array undefiniert oder leer ist, löst jede Aktualisierung die Funktion aus. -> e.g. `person.updated`, `*.created`, `company.*` +> z. B. `person.updated`, `*.created`, `company.*` -You can also manually execute a function using the CLI: +Sie können eine Funktion auch manuell über die CLI ausführen: ```bash filename="Terminal" yarn twenty exec -n create-new-post-card -p '{"key": "value"}' @@ -505,7 +505,7 @@ yarn twenty exec -n create-new-post-card -p '{"key": "value"}' yarn twenty exec -y e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf ``` -You can watch logs with: +Sie können Protokolle mit folgendem Befehl ansehen: ```bash filename="Terminal" yarn twenty logs @@ -514,9 +514,8 @@ yarn twenty logs #### Routen-Trigger-Payload -When a route trigger invokes your logic function, it receives a `RoutePayload` object that follows the -[AWS HTTP API v2 format](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html). -Import the `RoutePayload` type from `twenty-sdk`: +Wenn ein Route-Trigger Ihre Logikfunktion aufruft, erhält sie ein `RoutePayload`-Objekt, das dem [AWS-HTTP-API-v2-Format](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html) folgt. +Importieren Sie den Typ `RoutePayload` aus `twenty-sdk`: ```ts import { defineLogicFunction, type RoutePayload } from 'twenty-sdk'; @@ -533,9 +532,9 @@ Der Typ `RoutePayload` hat die folgende Struktur: | Eigenschaft | Typ | Beschreibung | Beispiel | | ---------------------------- | ------------------------------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------- | - | `headers` | `Record` | HTTP-Header (nur die in `forwardedRequestHeaders` aufgelisteten) | see section below | + | `headers` | `Record` | HTTP-Header (nur die in `forwardedRequestHeaders` aufgelisteten) | siehe Abschnitt unten | | `queryStringParameters` | `Record` | Query-String-Parameter (mehrere Werte mit Kommas verbunden) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` | - | `pathParameters` | `Record` | Path parameters extracted from the route pattern | `/users/:id`, `/users/123` -> `{ id: '123' }` | + | `pathParameters` | `Record` | Aus dem Routenmuster extrahierte Pfadparameter | `/users/:id`, `/users/123` -> `{ id: '123' }` | | `body` | `object \| null` | Geparster Request-Body (JSON) | `{ id: 1 }` -> `{ id: 1 }` | | `isBase64Encoded` | `boolean` | Gibt an, ob der Body Base64-codiert ist | | | `requestContext.http.method` | `string` | HTTP-Methode (GET, POST, PUT, PATCH, DELETE) | | @@ -545,7 +544,7 @@ Der Typ `RoutePayload` hat die folgende Struktur: #### forwardedRequestHeaders Standardmäßig werden HTTP-Header von eingehenden Anfragen aus Sicherheitsgründen nicht an Ihre Logikfunktion weitergegeben. -To access specific headers, list them in the `forwardedRequestHeaders` array: +Um auf bestimmte Header zuzugreifen, listen Sie diese im Array `forwardedRequestHeaders` auf: ```ts export default defineLogicFunction({ @@ -561,7 +560,7 @@ export default defineLogicFunction({ }); ``` -In your handler, access the forwarded headers like this: +Greifen Sie in Ihrem Handler wie folgt auf die weitergeleiteten Header zu: ```ts const handler = async (event: RoutePayload) => { @@ -574,14 +573,14 @@ const handler = async (event: RoutePayload) => { ``` -Header-Namen werden in Kleinbuchstaben normalisiert. Access them using lowercase keys (e.g., `event.headers['content-type']`). +Header-Namen werden in Kleinbuchstaben normalisiert. Greifen Sie mit Schlüsseln in Kleinbuchstaben darauf zu (z. B. `event.headers['content-type']`). -#### Exposing a function as a tool +#### Eine Funktion als Tool bereitstellen -Logikfunktionen können als **Tools** für KI-Agenten und Workflows verfügbar gemacht werden. When marked as a tool, a function becomes discoverable by Twenty's AI features and can be used in workflow automations. +Logikfunktionen können als **Tools** für KI-Agenten und Workflows verfügbar gemacht werden. Wenn eine Funktion als Tool markiert ist, wird sie von den KI-Funktionen von Twenty auffindbar und kann in Workflow-Automatisierungen verwendet werden. -To mark a logic function as a tool, set `isTool: true`: +Um eine Logikfunktion als Tool zu markieren, setzen Sie `isTool: true`: ```ts src/logic-functions/enrich-company.logic-function.ts import { defineLogicFunction } from 'twenty-sdk'; @@ -617,8 +616,8 @@ export default defineLogicFunction({ Hauptpunkte: -* You can combine `isTool` with triggers — a function can be both a tool (callable by AI agents) and triggered by events at the same time. -* **`toolInputSchema`** (optional): A JSON Schema object describing the parameters your function accepts. The schema is computed automatically from source code static analysis, but you can set it explicitly: +* Sie können `isTool` mit Triggern kombinieren — eine Funktion kann gleichzeitig sowohl ein Tool (von KI-Agenten aufrufbar) als auch durch Ereignisse ausgelöst werden. +* **`toolInputSchema`** (optional): Ein JSON-Schema-Objekt, das die Parameter beschreibt, die Ihre Funktion akzeptiert. Das Schema wird automatisch durch statische Analyse des Quellcodes ermittelt, Sie können es jedoch auch explizit festlegen: ```ts export default defineLogicFunction({ @@ -715,11 +714,11 @@ Hauptpunkte: -Front components are React components that render directly inside Twenty's UI. They run in an **isolated Web Worker** using Remote DOM — your code is sandboxed but renders natively in the page, not in an iframe. +Frontend-Komponenten sind React-Komponenten, die direkt innerhalb der Twenty-UI gerendert werden. Sie laufen in einem **isolierten Web Worker** unter Verwendung von Remote DOM — Ihr Code wird in einer Sandbox ausgeführt, rendert jedoch nativ auf der Seite, nicht in einem iframe. -#### Basic example +#### Einfaches Beispiel -The quickest way to see a front component in action is to register it as a **command**. Adding a `command` field with `isPinned: true` makes it appear as a quick-action button in the top-right corner of the page — no page layout needed: +Der schnellste Weg, eine Frontend-Komponente in Aktion zu sehen, ist, sie als Befehl zu registrieren. Das Hinzufügen eines `command`-Felds mit `isPinned: true` lässt sie als Schnellaktionsschaltfläche oben rechts auf der Seite erscheinen — kein Seitenlayout erforderlich: ```tsx src/front-components/hello-world.tsx import { defineFrontComponent } from 'twenty-sdk'; @@ -749,34 +748,34 @@ export default defineFrontComponent({ }); ``` -After syncing with `yarn twenty dev`, the quick action appears in the top-right corner of the page: +Nach dem Synchronisieren mit `yarn twenty dev` erscheint die Schnellaktion oben rechts auf der Seite:
- Quick action button in the top-right corner + Schnellaktionsschaltfläche oben rechts
-Click it to render the component inline. +Klicken Sie darauf, um die Komponente inline zu rendern. {/* TODO: add screenshot of the rendered front component */} -#### Configuration fields +#### Konfigurationsfelder -| Feld | Erforderlich | Beschreibung | -| --------------------- | ------------ | ----------------------------------------------------------------------------------- | -| `universalIdentifier` | Ja | Stable unique ID for this component | -| `component` | Ja | A React component function | -| `name` | Nein | Display name | -| `description` | Nein | Description of what the component does | -| `isHeadless` | Nein | Set to `true` if the component has no visible UI (see below) | -| `command` | Nein | Register the component as a command (see [command options](#command-options) below) | +| Feld | Erforderlich | Beschreibung | +| --------------------- | ------------ | ---------------------------------------------------------------------------------------- | +| `universalIdentifier` | Ja | Stabile eindeutige ID für diese Komponente | +| `component` | Ja | Eine React-Komponentenfunktion | +| `name` | Nein | Anzeigename | +| `description` | Nein | Beschreibung dessen, was die Komponente macht | +| `isHeadless` | Nein | Auf `true` setzen, wenn die Komponente keine sichtbare UI hat (siehe unten) | +| `command` | Nein | Die Komponente als Befehl registrieren (siehe unten [Befehlsoptionen](#command-options)) | -#### Placing a front component on a page +#### Eine Frontend-Komponente auf einer Seite platzieren -Beyond commands, you can embed a front component directly into a record page by adding it as a widget in a **page layout**. See the [definePageLayout](#definepagelayout) section for details. +Über Befehle hinaus können Sie eine Frontend-Komponente direkt in eine Datensatzseite einbetten, indem Sie sie als Widget in einem **Seitenlayout** hinzufügen. Details finden Sie im Abschnitt [definePageLayout](#definepagelayout). -#### Headless components (`isHeadless: true`) +#### Headless-Komponenten (`isHeadless: true`) -Headless components render no visible UI but still run React logic. This is useful for **effect components** — components that perform side effects when mounted, such as syncing data, starting a timer, listening to events, or triggering a notification. +Headless-Komponenten rendern keine sichtbare UI, führen aber dennoch React-Logik aus. Dies ist nützlich für **Effekt-Komponenten** — Komponenten, die beim Mounten Seiteneffekte ausführen, wie z. B. das Synchronisieren von Daten, Starten eines Timers, Lauschen auf Ereignisse oder Auslösen einer Benachrichtigung. ```tsx src/front-components/sync-tracker.tsx import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk'; @@ -801,11 +800,11 @@ export default defineFrontComponent({ }); ``` -Because the component returns `null`, Twenty skips rendering a container for it — no empty space appears in the layout. The component still has access to all hooks and the host communication API. +Da die Komponente `null` zurückgibt, überspringt Twenty das Rendern eines Containers dafür — im Layout entsteht kein Leerraum. Die Komponente hat dennoch Zugriff auf alle Hooks und die Host-Kommunikations-API. -#### Accessing runtime context +#### Zugriff auf den Laufzeitkontext -Inside your component, use SDK hooks to access the current user, record, and component instance: +Verwenden Sie innerhalb Ihrer Komponente SDK-Hooks, um auf den aktuellen Benutzer, den Datensatz und die Komponenteninstanz zuzugreifen: ```tsx src/front-components/record-info.tsx import { @@ -836,47 +835,47 @@ export default defineFrontComponent({ }); ``` -Available hooks: +Verfügbare Hooks: -| Hook | Returns | Beschreibung | -| --------------------------------------------- | ------------------ | ---------------------------------------------------------- | -| `useUserId()` | `string` or `null` | The current user's ID | -| `useRecordId()` | `string` or `null` | The current record's ID (when placed on a record page) | -| `useFrontComponentId()` | `string` | This component instance's ID | -| `useFrontComponentExecutionContext(selector)` | variiert | Access the full execution context with a selector function | +| Hook | Gibt zurück | Beschreibung | +| --------------------------------------------- | -------------------- | --------------------------------------------------------------------------- | +| `useUserId()` | `string` oder `null` | Die ID des aktuellen Benutzers | +| `useRecordId()` | `string` oder `null` | Die ID des aktuellen Datensatzes (wenn auf einer Datensatzseite platziert) | +| `useFrontComponentId()` | `string` | Die ID dieser Komponenteninstanz | +| `useFrontComponentExecutionContext(selector)` | variiert | Zugriff auf den vollständigen Ausführungskontext mit einer Selektorfunktion | -#### Host communication API +#### Host-Kommunikations-API -Front components can trigger navigation, modals, and notifications using functions from `twenty-sdk`: +Frontend-Komponenten können Navigation, Modals und Benachrichtigungen mittels Funktionen aus `twenty-sdk` auslösen: -| Funktion | Beschreibung | -| ----------------------------------------------- | ----------------------------- | -| `navigate(to, params?, queryParams?, options?)` | Navigate to a page in the app | -| `openSidePanelPage(params)` | Open a side panel | -| `closeSidePanel()` | Seitenpanel schließen | -| `openCommandConfirmationModal(params)` | Show a confirmation dialog | -| `enqueueSnackbar(params)` | Show a toast notification | -| `unmountFrontComponent()` | Unmount the component | -| `updateProgress(progress)` | Update a progress indicator | +| Funktion | Beschreibung | +| ----------------------------------------------- | ----------------------------------------- | +| `navigate(to, params?, queryParams?, options?)` | Zu einer Seite in der App navigieren | +| `openSidePanelPage(params)` | Ein Seitenpanel öffnen | +| `closeSidePanel()` | Seitenpanel schließen | +| `openCommandConfirmationModal(params)` | Einen Bestätigungsdialog anzeigen | +| `enqueueSnackbar(params)` | Eine Toast-Benachrichtigung anzeigen | +| `unmountFrontComponent()` | Die Komponente entfernen | +| `updateProgress(progress)` | Einen Fortschrittsindikator aktualisieren | -#### Command options +#### Befehlsoptionen -Adding a `command` field to `defineFrontComponent` registers the component in the command menu (Cmd+K). If `isPinned` is `true`, it also appears as a quick-action button in the top-right corner of the page. +Das Hinzufügen eines `command`-Felds zu `defineFrontComponent` registriert die Komponente im Befehlsmenü (Cmd+K). Wenn `isPinned` `true` ist, erscheint sie außerdem als Schnellaktionsschaltfläche oben rechts auf der Seite. -| Feld | Erforderlich | Beschreibung | -| --------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `universalIdentifier` | Ja | Stable unique ID for the command | -| `label` | Ja | Full label shown in the command menu (Cmd+K) | -| `shortLabel` | Nein | Shorter label displayed on the pinned quick-action button | -| `icon` | Nein | Icon name displayed next to the label (e.g. `'IconBolt'`, `'IconSend'`) | -| `isPinned` | Nein | When `true`, shows the command as a quick-action button in the top-right corner of the page | -| `availabilityType` | Nein | Controls where the command appears: `'GLOBAL'` (always available), `'RECORD_SELECTION'` (only when records are selected), or `'FALLBACK'` (shown when no other commands match) | -| `availabilityObjectUniversalIdentifier` | Nein | Restrict the command to pages of a specific object type (e.g. only on Company records) | -| `conditionalAvailabilityExpression` | Nein | A boolean expression to dynamically control whether the command is visible (see below) | +| Feld | Erforderlich | Beschreibung | +| --------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `universalIdentifier` | Ja | Stabile eindeutige ID für den Befehl | +| `label` | Ja | Vollständiges Label, das im Befehlsmenü (Cmd+K) angezeigt wird | +| `shortLabel` | Nein | Kürzeres Label, das auf der angehefteten Schnellaktionsschaltfläche angezeigt wird | +| `icon` | Nein | Neben dem Label angezeigter Icon-Name (z. B. 'IconBolt', 'IconSend') | +| `isPinned` | Nein | Bei `true` wird der Befehl als Schnellaktionsschaltfläche oben rechts auf der Seite angezeigt | +| `availabilityType` | Nein | Steuert, wo der Befehl erscheint: 'GLOBAL' (immer verfügbar), 'RECORD_SELECTION' (nur wenn Datensätze ausgewählt sind) oder 'FALLBACK' (wird angezeigt, wenn keine anderen Befehle passen) | +| `availabilityObjectUniversalIdentifier` | Nein | Beschränken Sie den Befehl auf Seiten eines bestimmten Objekttyps (z. B. nur bei Company-Datensätzen) | +| `conditionalAvailabilityExpression` | Nein | Ein boolescher Ausdruck, um dynamisch zu steuern, ob der Befehl sichtbar ist (siehe unten) | -#### Conditional availability expressions +#### Bedingte Verfügbarkeitsausdrücke -The `conditionalAvailabilityExpression` field lets you control when a command is visible based on the current page context. Import typed variables and operators from `twenty-sdk` to build expressions: +Mit dem Feld `conditionalAvailabilityExpression` können Sie basierend auf dem aktuellen Seitenkontext steuern, wann ein Befehl sichtbar ist. Importieren Sie typisierte Variablen und Operatoren aus `twenty-sdk`, um Ausdrücke zu erstellen: ```tsx import { @@ -905,45 +904,45 @@ export default defineFrontComponent({ }); ``` -**Context variables** — these represent the current state of the page: +**Kontextvariablen** — sie repräsentieren den aktuellen Zustand der Seite: -| Variable | Typ | Beschreibung | -| ------------------------------ | --------- | ---------------------------------------------------------------- | -| `pageType` | `string` | Current page type (e.g. `'RecordIndexPage'`, `'RecordShowPage'`) | -| `isInSidePanel` | `boolean` | Whether the component is rendered in a side panel | -| `numberOfSelectedRecords` | `number` | Number of currently selected records | -| `isSelectAll` | `boolean` | Whether "select all" is active | -| `selectedRecords` | `array` | The selected record objects | -| `favoriteRecordIds` | `array` | IDs of favorited records | -| `objectPermissions` | `object` | Permissions for the current object type | -| `targetObjectReadPermissions` | `object` | Read permissions for the target object | -| `targetObjectWritePermissions` | `object` | Write permissions for the target object | -| `featureFlags` | `object` | Active feature flags | -| `objectMetadataItem` | `object` | Metadata of the current object type | -| `hasAnySoftDeleteFilterOnView` | `boolean` | Whether the current view has a soft-delete filter | +| Variable | Typ | Beschreibung | +| ------------------------------ | --------- | --------------------------------------------------------------- | +| `pageType` | `string` | Aktueller Seitentyp (z. B. 'RecordIndexPage', 'RecordShowPage') | +| `isInSidePanel` | `boolean` | Ob die Komponente in einem Seitenpanel gerendert wird | +| `numberOfSelectedRecords` | `number` | Anzahl der aktuell ausgewählten Datensätze | +| `isSelectAll` | `boolean` | Ob „Alle auswählen“ aktiv ist | +| `selectedRecords` | `array` | Die ausgewählten Datensatzobjekte | +| `favoriteRecordIds` | `array` | IDs der favorisierten Datensätze | +| `objectPermissions` | `object` | Berechtigungen für den aktuellen Objekttyp | +| `targetObjectReadPermissions` | `object` | Leseberechtigungen für das Zielobjekt | +| `targetObjectWritePermissions` | `object` | Schreibberechtigungen für das Zielobjekt | +| `featureFlags` | `object` | Aktive Feature-Flags | +| `objectMetadataItem` | `object` | Metadaten des aktuellen Objekttyps | +| `hasAnySoftDeleteFilterOnView` | `boolean` | Ob die aktuelle Ansicht einen Soft-Delete-Filter hat | -**Operators** — combine variables into boolean expressions: +**Operatoren** — Variablen zu booleschen Ausdrücken kombinieren: -| Operator | Beschreibung | -| ----------------------------------- | ----------------------------------------------------------------- | -| `isDefined(value)` | `true` if the value is not null/undefined | -| `isNonEmptyString(value)` | `true` if the value is a non-empty string | -| `includes(array, value)` | `true` if the array contains the value | -| `includesEvery(array, prop, value)` | `true` if every item's property includes the value | -| `every(array, prop)` | `true` if the property is truthy on every item | -| `everyDefined(array, prop)` | `true` if the property is defined on every item | -| `everyEquals(array, prop, value)` | `true` if the property equals the value on every item | -| `some(array, prop)` | `true` if the property is truthy on at least one item | -| `someDefined(array, prop)` | `true` if the property is defined on at least one item | -| `someEquals(array, prop, value)` | `true` if the property equals the value on at least one item | -| `someNonEmptyString(array, prop)` | `true` if the property is a non-empty string on at least one item | -| `none(array, prop)` | `true` if the property is falsy on every item | -| `noneDefined(array, prop)` | `true` if the property is undefined on every item | -| `noneEquals(array, prop, value)` | `true` if the property does not equal the value on any item | +| Operator | Beschreibung | +| ----------------------------------- | ------------------------------------------------------------------------------------------- | +| `isDefined(value)` | `true`, wenn der Wert nicht null/undefined ist | +| `isNonEmptyString(value)` | `true`, wenn der Wert eine nicht leere Zeichenfolge ist | +| `includes(array, value)` | `true`, wenn das Array den Wert enthält | +| `includesEvery(array, prop, value)` | `true`, wenn die Eigenschaft jedes Elements den Wert enthält | +| `every(array, prop)` | `true`, wenn die Eigenschaft bei jedem Element truthy ist | +| `everyDefined(array, prop)` | `true`, wenn die Eigenschaft bei jedem Element definiert ist | +| `everyEquals(array, prop, value)` | `true`, wenn die Eigenschaft bei jedem Element dem Wert entspricht | +| `some(array, prop)` | `true`, wenn die Eigenschaft bei mindestens einem Element truthy ist | +| `someDefined(array, prop)` | `true`, wenn die Eigenschaft bei mindestens einem Element definiert ist | +| `someEquals(array, prop, value)` | `true`, wenn die Eigenschaft bei mindestens einem Element dem Wert entspricht | +| `someNonEmptyString(array, prop)` | `true`, wenn die Eigenschaft bei mindestens einem Element eine nicht leere Zeichenfolge ist | +| `none(array, prop)` | `true`, wenn die Eigenschaft bei jedem Element falsy ist | +| `noneDefined(array, prop)` | `true`, wenn die Eigenschaft bei jedem Element undefined ist | +| `noneEquals(array, prop, value)` | `true`, wenn die Eigenschaft bei keinem Element dem Wert entspricht | -#### Public assets +#### Öffentliche Assets -Front components can access files from the app's `public/` directory using `getPublicAssetUrl`: +Frontend-Komponenten können mit `getPublicAssetUrl` auf Dateien aus dem `public/`-Verzeichnis der App zugreifen: ```tsx import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk'; @@ -957,18 +956,18 @@ export default defineFrontComponent({ }); ``` -See the [public assets section](#accessing-public-assets-with-getpublicasseturl) for details. +Details finden Sie im Abschnitt [Öffentliche Assets](#accessing-public-assets-with-getpublicasseturl). #### Styling -Front components support multiple styling approaches. You can use: +Frontend-Komponenten unterstützen mehrere Styling-Ansätze. Sie können verwenden: -* **Inline styles** — `style={{ color: 'red' }}` -* **Twenty UI components** — import from `twenty-sdk/ui` (Button, Tag, Status, Chip, Avatar, and more) -* **Emotion** — CSS-in-JS with `@emotion/react` -* **Styled-components** — `styled.div` patterns -* **Tailwind CSS** — utility classes -* **Any CSS-in-JS library** compatible with React +* **Inline-Styles** — `style={{ color: 'red' }}` +* **Twenty-UI-Komponenten** — Import aus `twenty-sdk/ui` (Button, Tag, Status, Chip, Avatar und mehr) +* **Emotion** — CSS-in-JS mit `@emotion/react` +* **Styled-components** — `styled.div`-Muster +* **Tailwind CSS** — Utility-Klassen +* **Beliebige CSS-in-JS-Bibliothek**, die mit React kompatibel ist ```tsx import { defineFrontComponent } from 'twenty-sdk'; @@ -1022,9 +1021,9 @@ Hauptpunkte: * `description` (optional) liefert zusätzlichen Kontext zum Zweck des Skills.
- + -Agents are AI assistants that live inside your workspace. Use `defineAgent()` to create agents with a custom system prompt: +Agenten sind KI-Assistenten, die innerhalb Ihres Workspaces leben. Verwenden Sie `defineAgent()`, um Agenten mit einem benutzerdefinierten System-Prompt zu erstellen: ```ts src/agents/example-agent.ts import { defineAgent } from 'twenty-sdk'; @@ -1040,17 +1039,17 @@ export default defineAgent({ ``` Hauptpunkte: -* `name` is the unique identifier string for the agent (kebab-case recommended). -* `label` is the display name shown in the UI. -* `prompt` is the system prompt that defines the agent's behavior. -* `description` (optional) provides context about what the agent does. +* `name` ist die eindeutige Kennzeichnungs-Zeichenfolge für den Agenten (kebab-case empfohlen). +* `label` ist der in der UI angezeigte Anzeigename. +* `prompt` ist der System-Prompt, der das Verhalten des Agenten definiert. +* `description` (optional) liefert Kontext dazu, was der Agent tut. * `icon` (optional) legt das in der UI angezeigte Symbol fest. -* `modelId` (optional) overrides the default AI model used by the agent. +* `modelId` (optional) überschreibt das vom Agenten verwendete Standard-KI-Modell. -Views are saved configurations for how records of an object are displayed — including which fields are visible, their order, and any filters or groups applied. Use `defineView()` to ship pre-configured views with your app: +Ansichten sind gespeicherte Konfigurationen dafür, wie Datensätze eines Objekts angezeigt werden — einschließlich sichtbarer Felder, deren Reihenfolge sowie angewendeter Filter oder Gruppen. Verwenden Sie `defineView()`, um vorkonfigurierte Ansichten mit Ihrer App auszuliefern: ```ts src/views/example-view.ts import { defineView, ViewKey } from 'twenty-sdk'; @@ -1077,16 +1076,16 @@ export default defineView({ ``` Hauptpunkte: -* `objectUniversalIdentifier` specifies which object this view applies to. -* `key` determines the view type (e.g., `ViewKey.INDEX` for the main list view). -* `fields` controls which columns appear and their order. Each field references a `fieldMetadataUniversalIdentifier`. -* You can also define `filters`, `filterGroups`, `groups`, and `fieldGroups` for more advanced configurations. -* `position` controls the ordering when multiple views exist for the same object. +* `objectUniversalIdentifier` gibt an, auf welches Objekt diese Ansicht angewendet wird. +* `key` bestimmt den Ansichtstyp (z. B. `ViewKey.INDEX` für die Hauptlistenansicht). +* `fields` steuert, welche Spalten erscheinen und in welcher Reihenfolge. Jedes Feld referenziert einen `fieldMetadataUniversalIdentifier`. +* Für erweiterte Konfigurationen können Sie außerdem `filters`, `filterGroups`, `groups` und `fieldGroups` definieren. +* `position` steuert die Reihenfolge, wenn mehrere Ansichten für dasselbe Objekt existieren. -Navigation menu items add custom entries to the workspace sidebar. Use `defineNavigationMenuItem()` to link to views, external URLs, or objects: +Navigationsmenüeinträge fügen der Workspace-Seitenleiste benutzerdefinierte Einträge hinzu. Verwenden Sie `defineNavigationMenuItem()`, um auf Ansichten, externe URLs oder Objekte zu verlinken: ```ts src/navigation-menu-items/example-navigation-menu-item.ts import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk'; @@ -1104,15 +1103,15 @@ export default defineNavigationMenuItem({ ``` Hauptpunkte: -* `type` determines what the menu item links to: `NavigationMenuItemType.VIEW` for a saved view, or `NavigationMenuItemType.LINK` for an external URL. -* For view links, set `viewUniversalIdentifier`. For external links, set `link`. -* `position` controls the ordering in the sidebar. -* `icon` and `color` (optional) customize the appearance. +* `type` bestimmt, worauf der Menüeintrag verweist: `NavigationMenuItemType.VIEW` für eine gespeicherte Ansicht oder `NavigationMenuItemType.LINK` für eine externe URL. +* Für Ansichtslinks setzen Sie `viewUniversalIdentifier`. Für externe Links setzen Sie `link`. +* `position` steuert die Reihenfolge in der Seitenleiste. +* `icon` und `color` (optional) passen das Erscheinungsbild an. - + -Page layouts let you customize how a record detail page looks — which tabs appear, what widgets are inside each tab, and how they are arranged. Use `definePageLayout()` to ship custom layouts with your app: +Seitenlayouts ermöglichen es Ihnen, das Aussehen einer Datensatzdetailseite anzupassen — welche Tabs erscheinen, welche Widgets sich in jedem Tab befinden und wie sie angeordnet sind. Verwenden Sie `definePageLayout()`, um benutzerdefinierte Layouts mit Ihrer App auszuliefern: ```ts src/page-layouts/example-record-page-layout.ts import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk'; @@ -1149,33 +1148,33 @@ export default definePageLayout({ ``` Hauptpunkte: -* `type` is typically `'RECORD_PAGE'` to customize the detail view of a specific object. -* `objectUniversalIdentifier` specifies which object this layout applies to. -* Each `tab` defines a section of the page with a `title`, `position`, and `layoutMode` (`CANVAS` for free-form layout). -* Each `widget` inside a tab can render a front component, a relation list, or other built-in widget types. -* `position` on tabs controls their order. Use higher values (e.g., 50) to place custom tabs after built-in ones. +* `type` ist typischerweise `'RECORD_PAGE'`, um die Detailansicht eines bestimmten Objekts anzupassen. +* `objectUniversalIdentifier` gibt an, auf welches Objekt dieses Layout angewendet wird. +* Jeder `tab` definiert einen Abschnitt der Seite mit `title`, `position` und `layoutMode` (`CANVAS` für ein freies Layout). +* Jedes `widget` innerhalb eines Tabs kann eine Frontend-Komponente, eine Relationenliste oder andere eingebaute Widget-Typen rendern. +* `position` auf Tabs steuert deren Reihenfolge. Verwenden Sie höhere Werte (z. B. 50), um benutzerdefinierte Tabs hinter den integrierten zu platzieren.
-## Public assets (`public/` folder) +## Öffentliche Assets (Ordner `public/`) -The `public/` folder at the root of your app holds static files — images, icons, fonts, or any other assets your app needs at runtime. These files are automatically included in builds, synced during dev mode, and uploaded to the server. +Der Ordner `public/` im Stammverzeichnis Ihrer App enthält statische Dateien — Bilder, Icons, Schriftarten oder sonstige Assets, die Ihre App zur Laufzeit benötigt. Diese Dateien werden automatisch in Builds aufgenommen, während des Dev-Modus synchronisiert und auf den Server hochgeladen. -Files placed in `public/` are: +Für Dateien im Verzeichnis `public/` gilt: -* **Publicly accessible** — once synced to the server, assets are served at a public URL. No authentication is needed to access them. -* **Available in front components** — use asset URLs to display images, icons, or any media inside your React components. -* **Available in logic functions** — reference asset URLs in emails, API responses, or any server-side logic. -* **Used for marketplace metadata** — the `logoUrl` and `screenshots` fields in `defineApplication()` reference files from this folder (e.g., `public/logo.png`). These are displayed in the marketplace when your app is published. -* **Auto-synced in dev mode** — when you add, update, or delete a file in `public/`, it is synced to the server automatically. No restart needed. -* **Included in builds** — `yarn twenty build` bundles all public assets into the distribution output. +* **Öffentlich zugänglich** — nach der Synchronisierung mit dem Server werden Assets unter einer öffentlichen URL bereitgestellt. Zum Zugriff ist keine Authentifizierung erforderlich. +* **In Frontend-Komponenten verfügbar** — verwenden Sie Asset-URLs, um Bilder, Icons oder andere Medien in Ihren React-Komponenten anzuzeigen. +* **In Logikfunktionen verfügbar** — referenzieren Sie Asset-URLs in E-Mails, API-Antworten oder in beliebiger serverseitiger Logik. +* **Für Marketplace-Metadaten verwendet** — die Felder `logoUrl` und `screenshots` in `defineApplication()` referenzieren Dateien aus diesem Ordner (z. B. `public/logo.png`). Diese werden im Marketplace angezeigt, wenn Ihre App veröffentlicht wird. +* **Im Dev-Modus automatisch synchronisiert** — wenn Sie in `public/` eine Datei hinzufügen, aktualisieren oder löschen, wird sie automatisch mit dem Server synchronisiert. Kein Neustart erforderlich. +* **In Builds enthalten** — `yarn twenty build` bündelt alle öffentlichen Assets in der Distributionsausgabe. -### Accessing public assets with `getPublicAssetUrl` +### Zugriff auf öffentliche Assets mit `getPublicAssetUrl` -Use the `getPublicAssetUrl` helper from `twenty-sdk` to get the full URL of a file in your `public/` directory. It works in both **logic functions** and **front components**. +Verwenden Sie den Helper `getPublicAssetUrl` aus `twenty-sdk`, um die vollständige URL einer Datei in Ihrem `public/`-Verzeichnis zu erhalten. Dies funktioniert sowohl in Logikfunktionen als auch in Frontend-Komponenten. -**In a logic function:** +**In einer Logikfunktion:** ```ts src/logic-functions/send-invoice.ts import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk'; @@ -1200,7 +1199,7 @@ export default defineLogicFunction({ }); ``` -**In a front component:** +**In einer Frontend-Komponente:** ```tsx src/front-components/company-card.tsx import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk'; @@ -1212,19 +1211,19 @@ export default defineFrontComponent(() => { }); ``` -The `path` argument is relative to your app's `public/` folder. Both `getPublicAssetUrl('logo.png')` and `getPublicAssetUrl('public/logo.png')` resolve to the same URL — the `public/` prefix is stripped automatically if present. +Das Argument `path` ist relativ zum `public/`-Ordner Ihrer App. Sowohl `getPublicAssetUrl('logo.png')` als auch `getPublicAssetUrl('public/logo.png')` ergeben dieselbe URL — das Präfix `public/` wird, falls vorhanden, automatisch entfernt. -## Using npm packages +## Verwendung von npm-Paketen -You can install and use any npm package in your app. Both logic functions and front components are bundled with [esbuild](https://esbuild.github.io/), which inlines all dependencies into the output — no `node_modules` are needed at runtime. +Sie können in Ihrer App beliebige npm-Pakete installieren und verwenden. Sowohl Logikfunktionen als auch Frontend-Komponenten werden mit [esbuild](https://esbuild.github.io/) gebündelt, das alle Abhängigkeiten in die Ausgabe einbettet — zur Laufzeit sind keine `node_modules` erforderlich. -### Installing a package +### Ein Paket installieren ```bash filename="Terminal" yarn add axios ``` -Then import it in your code: +Importieren Sie es anschließend in Ihrem Code: ```ts src/logic-functions/fetch-data.ts import { defineLogicFunction } from 'twenty-sdk'; @@ -1245,7 +1244,7 @@ export default defineLogicFunction({ }); ``` -The same works for front components: +Dasselbe funktioniert für Frontend-Komponenten: ```tsx src/front-components/chart.tsx import { defineFrontComponent } from 'twenty-sdk'; @@ -1262,27 +1261,27 @@ export default defineFrontComponent({ }); ``` -### How bundling works +### Wie das Bundling funktioniert -The build step (`yarn twenty dev` or `yarn twenty build`) uses esbuild to produce a single self-contained file per logic function and per front component. All imported packages are inlined into the bundle. +Der Build-Schritt (`yarn twenty dev` oder `yarn twenty build`) verwendet esbuild, um pro Logikfunktion und pro Frontend-Komponente eine einzelne, in sich geschlossene Datei zu erzeugen. Alle importierten Pakete werden in das Bundle eingebettet. -**Logic functions** run in a Node.js environment. Node built-in modules (`fs`, `path`, `crypto`, `http`, etc.) are available and do not need to be installed. +**Logikfunktionen** laufen in einer Node.js-Umgebung. Eingebaute Node.js-Module (`fs`, `path`, `crypto`, `http` usw.) stehen zur Verfügung und müssen nicht installiert werden. -**Front components** run in a Web Worker. Node built-in modules are **not** available — only browser APIs and npm packages that work in a browser environment. +**Frontend-Komponenten** laufen in einem Web Worker. Eingebaute Node.js-Module sind **nicht** verfügbar — nur Browser-APIs und npm-Pakete, die in einer Browserumgebung funktionieren. -Both environments have `twenty-client-sdk/core` and `twenty-client-sdk/metadata` available as pre-provided modules — these are not bundled but resolved at runtime by the server. +In beiden Umgebungen stehen `twenty-client-sdk/core` und `twenty-client-sdk/metadata` als vorab bereitgestellte Module zur Verfügung — sie werden nicht gebündelt, sondern zur Laufzeit vom Server aufgelöst. -## Scaffolding entities with `yarn twenty add` +## Entitäten mit `yarn twenty add` erstellen -Instead of creating entity files by hand, you can use the interactive scaffolder: +Anstatt Entitätsdateien manuell zu erstellen, können Sie den interaktiven Scaffolder verwenden: ```bash filename="Terminal" yarn twenty add ``` -This prompts you to pick an entity type and walks you through the required fields. It generates a ready-to-use file with a stable `universalIdentifier` and the correct `defineEntity()` call. +Dies fordert Sie auf, einen Entitätstyp auszuwählen, und führt Sie durch die erforderlichen Felder. Er erzeugt eine einsatzbereite Datei mit einem stabilen `universalIdentifier` und dem korrekten `defineEntity()`-Aufruf. -You can also pass the entity type directly to skip the first prompt: +Sie können den Entitätstyp auch direkt übergeben, um die erste Eingabeaufforderung zu überspringen: ```bash filename="Terminal" yarn twenty add object @@ -1290,44 +1289,44 @@ yarn twenty add logicFunction yarn twenty add frontComponent ``` -### Available entity types +### Verfügbare Entitätstypen -| Entitätstyp | Befehl | Generated file | -| -------------------- | ------------------------------------ | ------------------------------------- | -| Objekt | `yarn twenty add object` | `src/objects/.ts` | -| Feld | `yarn twenty add field` | `src/fields/.ts` | -| Logic function | `yarn twenty add logicFunction` | `src/logic-functions/.ts` | -| Front component | `yarn twenty add frontComponent` | `src/front-components/.tsx` | -| Rolle | `yarn twenty add role` | `src/roles/.ts` | -| Skill | `yarn twenty add skill` | `src/skills/.ts` | -| Agent | `yarn twenty add agent` | `src/agents/.ts` | -| Ansicht | `yarn twenty add view` | `src/views/.ts` | -| Navigation menu item | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/.ts` | -| Page layout | `yarn twenty add pageLayout` | `src/page-layouts/.ts` | +| Entitätstyp | Befehl | Generierte Datei | +| ---------------------- | ------------------------------------ | ------------------------------------- | +| Objekt | `yarn twenty add object` | `src/objects/.ts` | +| Feld | `yarn twenty add field` | `src/fields/.ts` | +| Logikfunktion | `yarn twenty add logicFunction` | `src/logic-functions/.ts` | +| Frontend-Komponente | `yarn twenty add frontComponent` | `src/front-components/.tsx` | +| Rolle | `yarn twenty add role` | `src/roles/.ts` | +| Skill | `yarn twenty add skill` | `src/skills/.ts` | +| Agent | `yarn twenty add agent` | `src/agents/.ts` | +| Ansicht | `yarn twenty add view` | `src/views/.ts` | +| Navigationsmenüeintrag | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/.ts` | +| Seitenlayout | `yarn twenty add pageLayout` | `src/page-layouts/.ts` | -### What the scaffolder generates +### Was der Scaffolder generiert -Each entity type has its own template. For example, `yarn twenty add object` asks for: +Jeder Entitätstyp hat seine eigene Vorlage. Zum Beispiel fragt `yarn twenty add object` nach: -1. **Name (singular)** — e.g., `invoice` -2. **Name (plural)** — e.g., `invoices` -3. **Label (singular)** — auto-populated from the name (e.g., `Invoice`) -4. **Label (plural)** — auto-populated (e.g., `Invoices`) -5. **Create a view and navigation item?** — if you answer yes, the scaffolder also generates a matching view and sidebar link for the new object. +1. **Name (Singular)** — z. B. `invoice` +2. **Name (Plural)** — z. B. `invoices` +3. **Label (Singular)** — automatisch aus dem Namen befüllt (z. B. `Invoice`) +4. **Label (Plural)** — automatisch befüllt (z. B. `Invoices`) +5. **Ansicht und Navigationseintrag erstellen?** — wenn Sie mit Ja antworten, erzeugt der Scaffolder außerdem eine passende Ansicht und einen Sidebar-Link für das neue Objekt. -Other entity types have simpler prompts — most only ask for a name. +Andere Entitätstypen haben einfachere Eingabeaufforderungen — die meisten fragen nur nach einem Namen. -The `field` entity type is more detailed: it asks for the field name, label, type (from a list of all available field types like `TEXT`, `NUMBER`, `SELECT`, `RELATION`, etc.), and the target object's `universalIdentifier`. +Der Entitätstyp `field` ist detaillierter: Er fragt nach Feldname, Label, Typ (aus einer Liste aller verfügbaren Feldtypen wie `TEXT`, `NUMBER`, `SELECT`, `RELATION` usw.) sowie dem `universalIdentifier` des Zielobjekts. -### Custom output path +### Benutzerdefinierter Ausgabepfad -Use the `--path` flag to place the generated file in a custom location: +Verwenden Sie den Schalter `--path`, um die generierte Datei an einem benutzerdefinierten Ort abzulegen: ```bash filename="Terminal" yarn twenty add logicFunction --path src/custom-folder ``` -## Typed API clients (twenty-client-sdk) +## Typisierte API-Clients (twenty-client-sdk) Das Paket `twenty-client-sdk` stellt zwei typisierte GraphQL-Clients bereit, um aus Ihren Logikfunktionen und Frontend-Komponenten mit der Twenty-API zu interagieren. @@ -1337,9 +1336,9 @@ Das Paket `twenty-client-sdk` stellt zwei typisierte GraphQL-Clients bereit, um | `MetadataApiClient` | `twenty-client-sdk/metadata` | `/metadata` — Arbeitsbereichskonfiguration, Datei-Uploads | Nein, wird vorgefertigt ausgeliefert | - + -Der `CoreApiClient` ist der Haupt-Client zum Abfragen und Ändern von Arbeitsbereichsdaten. It is **generated from your workspace schema** during `yarn twenty dev` or `yarn twenty build`, so it is fully typed to match your objects and fields. +Der `CoreApiClient` ist der Haupt-Client zum Abfragen und Ändern von Arbeitsbereichsdaten. Er wird während `yarn twenty dev` oder `yarn twenty build` **aus Ihrem Arbeitsbereichsschema generiert** und ist daher vollständig typisiert, passend zu Ihren Objekten und Feldern. ```ts import { CoreApiClient } from 'twenty-client-sdk/core'; @@ -1379,12 +1378,12 @@ const { createCompany } = await client.mutation({ Der Client verwendet eine Selection-Set-Syntax: Übergeben Sie `true`, um ein Feld einzuschließen, verwenden Sie `__args` für Argumente, und verschachteln Sie Objekte für Relationen. Sie erhalten vollständige Autovervollständigung und Typprüfung basierend auf Ihrem Arbeitsbereichsschema. -**CoreApiClient is generated at dev/build time.** If you use it without running `yarn twenty dev` or `yarn twenty build` first, it throws an error. The generation happens automatically — the CLI introspects your workspace's GraphQL schema and generates a typed client using `@genql/cli`. +**Der CoreApiClient wird zur Entwicklungs-/Build-Zeit generiert.** Wenn Sie ihn verwenden, ohne zuvor `yarn twenty dev` oder `yarn twenty build` ausgeführt zu haben, wird ein Fehler ausgelöst. Die Generierung erfolgt automatisch — die CLI inspiziert das GraphQL-Schema Ihres Arbeitsbereichs und erzeugt mit `@genql/cli` einen typisierten Client. #### Verwendung von CoreSchema für Typannotationen -`CoreSchema` provides TypeScript types matching your workspace objects — useful for typing component state or function parameters: +`CoreSchema` stellt TypeScript-Typen bereit, die Ihren Arbeitsbereichsobjekten entsprechen — nützlich zum Typisieren von Komponentenzustand oder Funktionsparametern: ```ts import { CoreApiClient, CoreSchema } from 'twenty-client-sdk/core'; @@ -1406,7 +1405,7 @@ setCompany(result.company); ``` - + `MetadataApiClient` ist im SDK bereits vorgefertigt enthalten (keine Generierung erforderlich). Er fragt den Endpunkt `/metadata` nach Arbeitsbereichskonfiguration, Anwendungen und Datei-Uploads ab. @@ -1437,7 +1436,7 @@ const { objects } = await metadataClient.query({ #### Dateien hochladen -`MetadataApiClient` includes an `uploadFile` method for attaching files to file-type fields: +Der `MetadataApiClient` enthält eine Methode `uploadFile`, um Dateien an Felder des Typs Datei anzuhängen: ```ts import { MetadataApiClient } from 'twenty-client-sdk/metadata'; @@ -1458,12 +1457,12 @@ console.log(uploadedFile); // { id: '...', path: '...', size: 12345, createdAt: '...', url: 'https://...' } ``` -| Parameter | Typ | Beschreibung | -| ---------------------------------- | -------- | --------------------------------------------------------------- | -| `fileBuffer` | `Buffer` | Der Rohinhalt der Datei | -| `filename` | `string` | Der Name der Datei (wird für Speicherung und Anzeige verwendet) | -| `contentType` | `string` | MIME type (defaults to `application/octet-stream` if omitted) | -| `fieldMetadataUniversalIdentifier` | `string` | Der `universalIdentifier` des Dateityp-Felds in Ihrem Objekt | +| Parameter | Typ | Beschreibung | +| ---------------------------------- | -------- | --------------------------------------------------------------------- | +| `fileBuffer` | `Buffer` | Der Rohinhalt der Datei | +| `filename` | `string` | Der Name der Datei (wird für Speicherung und Anzeige verwendet) | +| `contentType` | `string` | MIME-Typ (standardmäßig `application/octet-stream`, wenn weggelassen) | +| `fieldMetadataUniversalIdentifier` | `string` | Der `universalIdentifier` des Dateityp-Felds in Ihrem Objekt | Hauptpunkte: * Sie verwendet den `universalIdentifier` des Feldes (nicht dessen arbeitsbereichsspezifische ID), sodass Ihr Upload-Code in jedem Arbeitsbereich funktioniert, in dem Ihre App installiert ist. @@ -1476,24 +1475,24 @@ Hauptpunkte: Wenn Ihr Code auf Twenty ausgeführt wird (Logikfunktionen oder Frontend-Komponenten), injiziert die Plattform Anmeldedaten als Umgebungsvariablen: * `TWENTY_API_URL` — Basis-URL der Twenty-API - * `TWENTY_APP_ACCESS_TOKEN` — Short-lived key scoped to your application's default function role + * `TWENTY_APP_ACCESS_TOKEN` — Kurzlebiger Schlüssel, der auf die Standard-Funktionsrolle Ihrer Anwendung begrenzt ist Sie müssen diese **nicht** an die Clients übergeben — sie lesen automatisch aus `process.env`. Die Berechtigungen des API-Schlüssels werden durch die Rolle bestimmt, auf die in `defaultRoleUniversalIdentifier` in Ihrer `application-config.ts` verwiesen wird. -## Testing your app +## Ihre App testen -The SDK provides programmatic APIs that let you build, deploy, install, and uninstall your app from test code. Combined with [Vitest](https://vitest.dev/) and the typed API clients, you can write integration tests that verify your app works end-to-end against a real Twenty server. +Das SDK stellt programmgesteuerte APIs bereit, mit denen Sie Ihre App aus Testcode heraus bauen, bereitstellen, installieren und deinstallieren können. In Kombination mit [Vitest](https://vitest.dev/) und den typisierten API-Clients können Sie Integrationstests schreiben, die prüfen, dass Ihre App End-to-End gegen einen echten Twenty-Server funktioniert. ### Einrichtung -The scaffolded app already includes Vitest. If you set it up manually, install the dependencies: +Die erzeugte App enthält bereits Vitest. Wenn Sie es manuell einrichten, installieren Sie die Abhängigkeiten: ```bash filename="Terminal" yarn add -D vitest vite-tsconfig-paths ``` -Create a `vitest.config.ts` at the root of your app: +Erstellen Sie eine `vitest.config.ts` im Stammverzeichnis Ihrer App: ```ts vitest.config.ts import tsconfigPaths from 'vite-tsconfig-paths'; @@ -1519,7 +1518,7 @@ export default defineConfig({ }); ``` -Create a setup file that verifies the server is reachable before tests run: +Erstellen Sie eine Setup-Datei, die vor dem Testlauf überprüft, dass der Server erreichbar ist: ```ts src/__tests__/setup-test.ts import * as fs from 'fs'; @@ -1559,22 +1558,22 @@ beforeAll(async () => { }); ``` -### Programmatic SDK APIs +### Programmgesteuerte SDK-APIs -The `twenty-sdk/cli` subpath exports functions you can call directly from test code: +Der Subpfad `twenty-sdk/cli` exportiert Funktionen, die Sie direkt aus Testcode aufrufen können: -| Funktion | Beschreibung | -| -------------- | ------------------------------------------- | -| `appBuild` | Build the app and optionally pack a tarball | -| `appDeploy` | Upload a tarball to the server | -| `appInstall` | Install the app on the active workspace | -| `appUninstall` | Uninstall the app from the active workspace | +| Funktion | Beschreibung | +| -------------- | ----------------------------------------------------- | +| `appBuild` | Die App bauen und optional ein Tarball packen | +| `appDeploy` | Ein Tarball auf den Server hochladen | +| `appInstall` | Die App im aktiven Arbeitsbereich installieren | +| `appUninstall` | Die App aus dem aktiven Arbeitsbereich deinstallieren | -Each function returns a result object with `success: boolean` and either `data` or `error`. +Jede Funktion gibt ein Ergebnisobjekt mit `success: boolean` und entweder `data` oder `error` zurück. -### Writing an integration test +### Einen Integrationstest schreiben -Here is a full example that builds, deploys, and installs the app, then verifies it appears in the workspace: +Hier ist ein vollständiges Beispiel, das die App baut, bereitstellt und installiert und anschließend prüft, dass sie im Arbeitsbereich erscheint: ```ts src/__tests__/app-install.integration-test.ts import { APPLICATION_UNIVERSAL_IDENTIFIER } from 'src/application-config'; @@ -1637,37 +1636,37 @@ describe('App installation', () => { }); ``` -### Running tests +### Tests ausführen -Make sure your local Twenty server is running, then: +Stellen Sie sicher, dass Ihr lokaler Twenty-Server läuft, und führen Sie dann Folgendes aus: ```bash filename="Terminal" yarn test ``` -Or in watch mode during development: +Oder im Watch-Modus während der Entwicklung: ```bash filename="Terminal" yarn test:watch ``` -### Type checking +### Typprüfung -You can also run type checking on your app without running tests: +Sie können die Typprüfung Ihrer App auch ohne Tests ausführen: ```bash filename="Terminal" yarn twenty typecheck ``` -This runs `tsc --noEmit` and reports any type errors. +Dies führt `tsc --noEmit` aus und meldet etwaige Typfehler. ## CLI-Referenz -Beyond `dev`, `build`, `add`, and `typecheck`, the CLI provides commands for executing functions, viewing logs, and managing app installations. +Zusätzlich zu `dev`, `build`, `add` und `typecheck` bietet die CLI Befehle zum Ausführen von Funktionen, Anzeigen von Logs und Verwalten von App-Installationen. -### Executing functions (`yarn twenty exec`) +### Funktionen ausführen (`yarn twenty exec`) -Run a logic function manually without triggering it via HTTP, cron, or database event: +Eine Logikfunktion manuell ausführen, ohne sie über HTTP, Cron oder ein Datenbankereignis auszulösen: ```bash filename="Terminal" # Execute by function name @@ -1684,9 +1683,9 @@ yarn twenty exec --preInstall yarn twenty exec --postInstall ``` -### Viewing function logs (`yarn twenty logs`) +### Funktionsprotokolle ansehen (`yarn twenty logs`) -Stream execution logs for your app's logic functions: +Ausführungsprotokolle für die Logikfunktionen Ihrer App streamen: ```bash filename="Terminal" # Stream all function logs @@ -1700,12 +1699,12 @@ yarn twenty logs -u e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf ``` -This is different from `yarn twenty server logs`, which shows the Docker container logs. `yarn twenty logs` shows your app's function execution logs from the Twenty server. +Dies unterscheidet sich von `yarn twenty server logs`, das die Docker-Container-Logs anzeigt. `yarn twenty logs` zeigt die Funktionsausführungsprotokolle Ihrer App vom Twenty-Server. -### Uninstalling an app (`yarn twenty uninstall`) +### Eine App deinstallieren (`yarn twenty uninstall`) -Remove your app from the active workspace: +Entfernen Sie Ihre App aus dem aktiven Arbeitsbereich: ```bash filename="Terminal" yarn twenty uninstall diff --git a/packages/twenty-docs/l/it/developers/extend/apps/building.mdx b/packages/twenty-docs/l/it/developers/extend/apps/building.mdx index 4bf6b4f513..b33a4264f3 100644 --- a/packages/twenty-docs/l/it/developers/extend/apps/building.mdx +++ b/packages/twenty-docs/l/it/developers/extend/apps/building.mdx @@ -4,24 +4,24 @@ description: Definisci oggetti, funzioni logiche, componenti front-end e molto a --- - Apps are currently in alpha. The feature works but is still evolving. + Le app sono attualmente in fase alfa. La funzionalità funziona ma è ancora in evoluzione. -The `twenty-sdk` package provides typed building blocks to create your app. This page covers every entity type and API client available in the SDK. +Il pacchetto `twenty-sdk` fornisce blocchi costruttivi tipizzati per creare la tua app. Questa pagina copre tutti i tipi di entità e i client API disponibili nell'SDK. -## DefineEntity functions +## Funzioni DefineEntity -The SDK provides functions to define your app entities. You must use `export default defineEntity({...})` for the SDK to detect your entities. Queste funzioni convalidano la configurazione in fase di build e offrono il completamento automatico nell'IDE e la sicurezza dei tipi. +L'SDK fornisce funzioni per definire le entità della tua app. Devi usare `export default defineEntity({...})` affinché l'SDK rilevi le tue entità. Queste funzioni convalidano la configurazione in fase di build e offrono il completamento automatico nell'IDE e la sicurezza dei tipi. - **File organization is up to you.** - Entity detection is AST-based — the SDK finds `export default defineEntity(...)` calls regardless of where the file lives. Grouping files by type (e.g., `logic-functions/`, `roles/`) is just a convention, not a requirement. + **L'organizzazione dei file dipende da te.** + Il rilevamento delle entità è basato sull'AST — l'SDK trova le chiamate a `export default defineEntity(...)` indipendentemente da dove si trova il file. Raggruppare i file per tipo (ad es., `logic-functions/`, `roles/`) è solo una convenzione, non un requisito. -Roles encapsulate permissions on your workspace's objects and actions. +I ruoli incapsulano i permessi sugli oggetti e sulle azioni del tuo spazio di lavoro. ```ts restricted-company-role.ts import { @@ -69,12 +69,12 @@ export default defineRole({ -Every app must have exactly one `defineApplication` call that describes: +Ogni app deve avere esattamente una chiamata a `defineApplication` che descrive: -* **Identity**: identifiers, display name, and description. -* **Permissions**: which role its functions and front components use. -* **(Optional) Variables**: key–value pairs exposed to your functions as environment variables. -* **(Optional) Pre-install / post-install functions**: logic functions that run before or after installation. +* **Identità**: identificatori, nome visualizzato e descrizione. +* **Autorizzazioni**: quale ruolo usano le sue funzioni e i componenti front-end. +* **Variabili (opzionali)**: coppie chiave–valore esposte alle funzioni come variabili d'ambiente. +* **(Opzionali) Funzioni di pre-installazione/post-installazione**: funzioni logiche che vengono eseguite prima o dopo l'installazione. ```ts src/application-config.ts import { defineApplication } from 'twenty-sdk'; @@ -98,21 +98,21 @@ export default defineApplication({ ``` Note: -* `universalIdentifier` fields are deterministic IDs you own. Generate them once and keep them stable across syncs. -* `applicationVariables` become environment variables for your functions and front components (e.g., `DEFAULT_RECIPIENT_NAME` is available as `process.env.DEFAULT_RECIPIENT_NAME`). -* `defaultRoleUniversalIdentifier` must reference a role defined with `defineRole()` (see above). -* Pre-install and post-install functions are detected automatically during the manifest build — you do not need to reference them in `defineApplication()`. +* I campi `universalIdentifier` sono ID deterministici che possiedi. Generali una volta e mantienili stabili tra una sincronizzazione e l'altra. +* `applicationVariables` diventano variabili d'ambiente per le tue funzioni e i componenti front-end (ad esempio, `DEFAULT_RECIPIENT_NAME` è disponibile come `process.env.DEFAULT_RECIPIENT_NAME`). +* `defaultRoleUniversalIdentifier` deve fare riferimento a un ruolo definito con `defineRole()` (vedi sopra). +* Le funzioni di pre-installazione e post-installazione vengono rilevate automaticamente durante il build del manifesto — non è necessario farvi riferimento in `defineApplication()`. #### Metadati del marketplace -If you plan to [publish your app](/l/it/developers/extend/apps/publishing), these optional fields control how it appears in the marketplace: +Se prevedi di [pubblicare la tua app](/l/it/developers/extend/apps/publishing), questi campi opzionali controllano come appare nel marketplace: | Campo | Descrizione | | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | | `autore` | Nome dell'autore o dell'azienda | | `categoria` | Categoria dell'app per il filtraggio nel marketplace | -| `logoUrl` | Path to your app logo (e.g., `public/logo.png`) | -| `screenshots` | Array of screenshot paths (e.g., `public/screenshot-1.png`) | +| `logoUrl` | Percorso al logo della tua app (ad es., `public/logo.png`) | +| `screenshots` | Array di percorsi degli screenshot (ad es., `public/screenshot-1.png`) | | `aboutDescription` | Descrizione markdown più lunga per la scheda "Informazioni". Se omesso, il marketplace utilizza il `README.md` del pacchetto da npm | | `websiteUrl` | Link al tuo sito web | | `termsUrl` | Link ai Termini di servizio | @@ -121,15 +121,15 @@ If you plan to [publish your app](/l/it/developers/extend/apps/publishing), thes #### Ruoli e permessi -The `defaultRoleUniversalIdentifier` in `application-config.ts` designates the default role used by your app's logic functions and front components. See `defineRole` above for details. +Il `defaultRoleUniversalIdentifier` in `application-config.ts` indica il ruolo predefinito utilizzato dalle funzioni logiche e dai componenti front-end della tua app. Vedi `defineRole` sopra per i dettagli. -* The runtime token injected as `TWENTY_APP_ACCESS_TOKEN` is derived from this role. -* The typed client is restricted to the permissions granted to that role. -* Follow least-privilege: create a dedicated role with only the permissions your functions need. +* Il token di runtime iniettato come `TWENTY_APP_ACCESS_TOKEN` è derivato da questo ruolo. +* Il client tipizzato è limitato ai permessi concessi a quel ruolo. +* Segui il principio del privilegio minimo: crea un ruolo dedicato con solo i permessi necessari alle tue funzioni. -##### Default function role +##### Ruolo funzione predefinito -When you scaffold a new app, the CLI creates a default role file: +Quando esegui lo scaffolding di una nuova app, la CLI crea un file di ruolo predefinito: ```ts src/roles/default-role.ts import { defineRole, PermissionFlag } from 'twenty-sdk'; @@ -155,16 +155,16 @@ export default defineRole({ }); ``` -This role's `universalIdentifier` is referenced in `application-config.ts` as `defaultRoleUniversalIdentifier`: +L'`universalIdentifier` di questo ruolo viene referenziato in `application-config.ts` come `defaultRoleUniversalIdentifier`: -* **\*.role.ts** defines what the role can do. +* **\*.role.ts** definisce ciò che il ruolo può fare. * **application-config.ts** punta a quel ruolo in modo che le tue funzioni ne ereditino i permessi. Note: * Parti dal ruolo generato dallo scaffolder, quindi restringilo progressivamente seguendo il principio del privilegio minimo. -* Replace `objectPermissions` and `fieldPermissions` with the objects and fields your functions actually need. -* `permissionFlags` controllano l'accesso alle funzionalità a livello di piattaforma. Keep them minimal. -* See a working example: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). +* Sostituisci `objectPermissions` e `fieldPermissions` con gli oggetti e i campi di cui le tue funzioni hanno realmente bisogno. +* `permissionFlags` controllano l'accesso alle funzionalità a livello di piattaforma. Mantienili al minimo. +* Vedi un esempio funzionante: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). @@ -256,7 +256,7 @@ ma non è consigliato. - + Usa `defineField()` per aggiungere campi a oggetti che non possiedi — come gli oggetti standard di Twenty (Person, Company, ecc.) o oggetti di altre app. A differenza dei campi inline in `defineObject()`, i campi autonomi richiedono un `objectUniversalIdentifier` per specificare quale oggetto estendono: @@ -284,7 +284,7 @@ Punti chiave: * `defineField()` è l'unico modo per aggiungere campi a oggetti che non hai creato con `defineObject()`. - + Le relazioni collegano gli oggetti tra loro. In Twenty, le relazioni sono sempre **bidirezionali** — definisci entrambi i lati e ciascun lato fa riferimento all'altro. @@ -443,7 +443,7 @@ export default defineObject({ }); ``` - + Ogni file di funzione usa `defineLogicFunction()` per esportare una configurazione con un handler e trigger opzionali. @@ -487,15 +487,15 @@ export default defineLogicFunction({ }); ``` -Available trigger types: -* **httpRoute**: Exposes your function on an HTTP path and method **under the `/s/` endpoint**: -> e.g. `path: '/post-card/create'` is callable at `https://your-twenty-server.com/s/post-card/create` +Tipi di trigger disponibili: +* **httpRoute**: Espone la tua funzione su un percorso e metodo HTTP **sotto l'endpoint `/s/`**: +> ad es. `path: '/post-card/create'` è invocabile su `https://your-twenty-server.com/s/post-card/create` * **cron**: Esegue la tua funzione secondo una pianificazione utilizzando un'espressione CRON. * **databaseEvent**: Viene eseguito sugli eventi del ciclo di vita degli oggetti dello spazio di lavoro. Quando l'operazione dell'evento è `updated`, è possibile specificare campi specifici da monitorare nell'array `updatedFields`. Se lasciato non definito o vuoto, qualsiasi aggiornamento attiverà la funzione. -> e.g. `person.updated`, `*.created`, `company.*` +> ad es. `person.updated`, `*.created`, `company.*` -You can also manually execute a function using the CLI: +Puoi anche eseguire manualmente una funzione utilizzando la CLI: ```bash filename="Terminal" yarn twenty exec -n create-new-post-card -p '{"key": "value"}' @@ -505,7 +505,7 @@ yarn twenty exec -n create-new-post-card -p '{"key": "value"}' yarn twenty exec -y e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf ``` -You can watch logs with: +Puoi osservare i log con: ```bash filename="Terminal" yarn twenty logs @@ -514,9 +514,8 @@ yarn twenty logs #### Payload del trigger di route -When a route trigger invokes your logic function, it receives a `RoutePayload` object that follows the -[AWS HTTP API v2 format](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html). -Import the `RoutePayload` type from `twenty-sdk`: +Quando un trigger di tipo route invoca la tua funzione logica, questa riceve un oggetto `RoutePayload` che segue il [formato AWS HTTP API v2](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html). +Importa il tipo `RoutePayload` da `twenty-sdk`: ```ts import { defineLogicFunction, type RoutePayload } from 'twenty-sdk'; @@ -533,9 +532,9 @@ Il tipo `RoutePayload` ha la seguente struttura: | Proprietà | Tipo | Descrizione | Esempio | | ---------------------------- | ------------------------------------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------- | - | `headers` | `Record` | Intestazioni HTTP (solo quelle elencate in `forwardedRequestHeaders`) | see section below | + | `headers` | `Record` | Intestazioni HTTP (solo quelle elencate in `forwardedRequestHeaders`) | vedi la sezione sotto | | `queryStringParameters` | `Record` | Parametri della query string (valori multipli uniti da virgole) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` | - | `pathParameters` | `Record` | Path parameters extracted from the route pattern | `/users/:id`, `/users/123` -> `{ id: '123' }` | + | `pathParameters` | `Record` | Parametri di percorso estratti dal pattern della route | `/users/:id`, `/users/123` -> `{ id: '123' }` | | `body` | `object \| null` | Corpo della richiesta analizzato (JSON) | `{ id: 1 }` -> `{ id: 1 }` | | `isBase64Encoded` | `boolean` | Indica se il corpo è codificato in base64 | | | `requestContext.http.method` | `string` | Metodo HTTP (GET, POST, PUT, PATCH, DELETE) | | @@ -545,7 +544,7 @@ Il tipo `RoutePayload` ha la seguente struttura: #### forwardedRequestHeaders Per impostazione predefinita, le intestazioni HTTP delle richieste in ingresso **non** vengono passate alla tua funzione logica per motivi di sicurezza. -To access specific headers, list them in the `forwardedRequestHeaders` array: +Per accedere a intestazioni specifiche, elencale nell'array `forwardedRequestHeaders`: ```ts export default defineLogicFunction({ @@ -561,7 +560,7 @@ export default defineLogicFunction({ }); ``` -In your handler, access the forwarded headers like this: +Nel tuo handler, accedi alle intestazioni inoltrate in questo modo: ```ts const handler = async (event: RoutePayload) => { @@ -574,14 +573,14 @@ const handler = async (event: RoutePayload) => { ``` -I nomi delle intestazioni vengono normalizzati in minuscolo. Access them using lowercase keys (e.g., `event.headers['content-type']`). +I nomi delle intestazioni vengono normalizzati in minuscolo. Accedile usando chiavi in minuscolo (ad es., `event.headers['content-type']`). -#### Exposing a function as a tool +#### Esporre una funzione come strumento -Le funzioni logiche possono essere esposte come **strumenti** per gli agenti di IA e i flussi di lavoro. When marked as a tool, a function becomes discoverable by Twenty's AI features and can be used in workflow automations. +Le funzioni logiche possono essere esposte come **strumenti** per gli agenti di IA e i flussi di lavoro. Quando una funzione è contrassegnata come strumento, diventa individuabile dalle funzionalità di IA di Twenty e può essere utilizzata nelle automazioni dei flussi di lavoro. -To mark a logic function as a tool, set `isTool: true`: +Per contrassegnare una funzione logica come strumento, imposta `isTool: true`: ```ts src/logic-functions/enrich-company.logic-function.ts import { defineLogicFunction } from 'twenty-sdk'; @@ -617,8 +616,8 @@ export default defineLogicFunction({ Punti chiave: -* You can combine `isTool` with triggers — a function can be both a tool (callable by AI agents) and triggered by events at the same time. -* **`toolInputSchema`** (optional): A JSON Schema object describing the parameters your function accepts. The schema is computed automatically from source code static analysis, but you can set it explicitly: +* Puoi combinare `isTool` con i trigger — una funzione può essere sia uno strumento (invocabile dagli agenti IA) sia attivata da eventi allo stesso tempo. +* **`toolInputSchema`** (opzionale): un oggetto JSON Schema che descrive i parametri accettati dalla funzione. Lo schema viene calcolato automaticamente dall'analisi statica del codice sorgente, ma puoi impostarlo esplicitamente: ```ts export default defineLogicFunction({ @@ -715,11 +714,11 @@ Punti chiave: -Front components are React components that render directly inside Twenty's UI. They run in an **isolated Web Worker** using Remote DOM — your code is sandboxed but renders natively in the page, not in an iframe. +I componenti front-end sono componenti React che vengono renderizzati direttamente all'interno della UI di Twenty. Vengono eseguiti in un **Web Worker** isolato utilizzando Remote DOM — il tuo codice è in sandbox ma viene renderizzato in modo nativo nella pagina, non in un iframe. -#### Basic example +#### Esempio di base -The quickest way to see a front component in action is to register it as a **command**. Adding a `command` field with `isPinned: true` makes it appear as a quick-action button in the top-right corner of the page — no page layout needed: +Il modo più rapido per vedere in azione un componente front-end è registrarlo come **comando**. Aggiungere un campo `command` con `isPinned: true` lo fa apparire come pulsante di azione rapida nell'angolo in alto a destra della pagina — nessun layout di pagina necessario: ```tsx src/front-components/hello-world.tsx import { defineFrontComponent } from 'twenty-sdk'; @@ -749,34 +748,34 @@ export default defineFrontComponent({ }); ``` -After syncing with `yarn twenty dev`, the quick action appears in the top-right corner of the page: +Dopo la sincronizzazione con `yarn twenty dev`, l'azione rapida appare nell'angolo in alto a destra della pagina:
- Quick action button in the top-right corner + Pulsante di azione rapida nell'angolo in alto a destra
-Click it to render the component inline. +Fai clic per renderizzare il componente in linea. {/* TODO: add screenshot of the rendered front component */} -#### Configuration fields +#### Campi di configurazione -| Campo | Obbligatorio | Descrizione | -| --------------------- | ------------ | ----------------------------------------------------------------------------------- | -| `universalIdentifier` | Sì | Stable unique ID for this component | -| `component` | Sì | A React component function | -| `name` | No | Display name | -| `descrizione` | No | Description of what the component does | -| `isHeadless` | No | Set to `true` if the component has no visible UI (see below) | -| `comando` | No | Register the component as a command (see [command options](#command-options) below) | +| Campo | Obbligatorio | Descrizione | +| --------------------- | ------------ | ---------------------------------------------------------------------------------------- | +| `universalIdentifier` | Sì | ID univoco stabile per questo componente | +| `component` | Sì | Una funzione di componente React | +| `name` | No | Nome visualizzato | +| `descrizione` | No | Descrizione di ciò che fa il componente | +| `isHeadless` | No | Imposta su `true` se il componente non ha una UI visibile (vedi sotto) | +| `comando` | No | Registra il componente come comando (vedi [opzioni del comando](#command-options) sotto) | -#### Placing a front component on a page +#### Posizionare un componente front-end su una pagina -Beyond commands, you can embed a front component directly into a record page by adding it as a widget in a **page layout**. See the [definePageLayout](#definepagelayout) section for details. +Oltre ai comandi, puoi incorporare un componente front-end direttamente in una pagina di record aggiungendolo come widget in un **layout di pagina**. Vedi la sezione [definePageLayout](#definepagelayout) per i dettagli. -#### Headless components (`isHeadless: true`) +#### Componenti headless (`isHeadless: true`) -Headless components render no visible UI but still run React logic. This is useful for **effect components** — components that perform side effects when mounted, such as syncing data, starting a timer, listening to events, or triggering a notification. +I componenti headless non renderizzano alcuna UI visibile ma eseguono comunque la logica React. Questo è utile per i componenti di effetto — componenti che eseguono effetti collaterali quando vengono montati, come sincronizzare dati, avviare un timer, ascoltare eventi o attivare una notifica. ```tsx src/front-components/sync-tracker.tsx import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk'; @@ -801,11 +800,11 @@ export default defineFrontComponent({ }); ``` -Because the component returns `null`, Twenty skips rendering a container for it — no empty space appears in the layout. The component still has access to all hooks and the host communication API. +Poiché il componente restituisce `null`, Twenty evita di renderizzare un contenitore per esso — non appare alcuno spazio vuoto nel layout. Il componente ha comunque accesso a tutti gli hook e all'API di comunicazione con l'host. -#### Accessing runtime context +#### Accesso al contesto di runtime -Inside your component, use SDK hooks to access the current user, record, and component instance: +All'interno del tuo componente, usa gli hook dell'SDK per accedere all'utente corrente, al record e all'istanza del componente: ```tsx src/front-components/record-info.tsx import { @@ -836,47 +835,47 @@ export default defineFrontComponent({ }); ``` -Available hooks: +Hook disponibili: -| Hook | Returns | Descrizione | -| --------------------------------------------- | ------------------ | ---------------------------------------------------------- | -| `useUserId()` | `string` or `null` | The current user's ID | -| `useRecordId()` | `string` or `null` | The current record's ID (when placed on a record page) | -| `useFrontComponentId()` | `string` | This component instance's ID | -| `useFrontComponentExecutionContext(selector)` | varia | Access the full execution context with a selector function | +| Hook | Restituisce | Descrizione | +| --------------------------------------------- | ----------------- | --------------------------------------------------------------------- | +| `useUserId()` | `string` o `null` | L'ID dell'utente corrente | +| `useRecordId()` | `string` o `null` | L'ID del record corrente (quando posizionato su una pagina di record) | +| `useFrontComponentId()` | `string` | L'ID di questa istanza di componente | +| `useFrontComponentExecutionContext(selector)` | varia | Accedi all'intero contesto di esecuzione con una funzione selettore | -#### Host communication API +#### API di comunicazione con l'host -Front components can trigger navigation, modals, and notifications using functions from `twenty-sdk`: +I componenti front-end possono attivare navigazione, modali e notifiche utilizzando funzioni da `twenty-sdk`: -| Funzione | Descrizione | -| ----------------------------------------------- | ----------------------------- | -| `navigate(to, params?, queryParams?, options?)` | Navigate to a page in the app | -| `openSidePanelPage(params)` | Open a side panel | -| `closeSidePanel()` | Chiudi il pannello laterale | -| `openCommandConfirmationModal(params)` | Show a confirmation dialog | -| `enqueueSnackbar(params)` | Show a toast notification | -| `unmountFrontComponent()` | Unmount the component | -| `updateProgress(progress)` | Update a progress indicator | +| Funzione | Descrizione | +| ----------------------------------------------- | ------------------------------------- | +| `navigate(to, params?, queryParams?, options?)` | Naviga a una pagina dell'app | +| `openSidePanelPage(params)` | Apri un pannello laterale | +| `closeSidePanel()` | Chiudi il pannello laterale | +| `openCommandConfirmationModal(params)` | Mostra una finestra di conferma | +| `enqueueSnackbar(params)` | Mostra una notifica toast | +| `unmountFrontComponent()` | Smonta il componente | +| `updateProgress(progress)` | Aggiorna un indicatore di avanzamento | -#### Command options +#### Opzioni del comando -Adding a `command` field to `defineFrontComponent` registers the component in the command menu (Cmd+K). If `isPinned` is `true`, it also appears as a quick-action button in the top-right corner of the page. +Aggiungere un campo `command` a `defineFrontComponent` registra il componente nel menu comandi (Cmd+K). Se `isPinned` è `true`, compare anche come pulsante di azione rapida nell'angolo in alto a destra della pagina. -| Campo | Obbligatorio | Descrizione | -| --------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `universalIdentifier` | Sì | Stable unique ID for the command | -| `etichetta` | Sì | Full label shown in the command menu (Cmd+K) | -| `shortLabel` | No | Shorter label displayed on the pinned quick-action button | -| `icona` | No | Icon name displayed next to the label (e.g. `'IconBolt'`, `'IconSend'`) | -| `isPinned` | No | When `true`, shows the command as a quick-action button in the top-right corner of the page | -| `availabilityType` | No | Controls where the command appears: `'GLOBAL'` (always available), `'RECORD_SELECTION'` (only when records are selected), or `'FALLBACK'` (shown when no other commands match) | -| `availabilityObjectUniversalIdentifier` | No | Restrict the command to pages of a specific object type (e.g. only on Company records) | -| `conditionalAvailabilityExpression` | No | A boolean expression to dynamically control whether the command is visible (see below) | +| Campo | Obbligatorio | Descrizione | +| --------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `universalIdentifier` | Sì | ID univoco stabile per il comando | +| `etichetta` | Sì | Etichetta completa mostrata nel menu comandi (Cmd+K) | +| `shortLabel` | No | Etichetta breve visualizzata sul pulsante di azione rapida fissato | +| `icona` | No | Nome dell'icona visualizzato accanto all'etichetta (ad es. `'IconBolt'`, `'IconSend'`) | +| `isPinned` | No | Quando `true`, mostra il comando come pulsante di azione rapida nell'angolo in alto a destra della pagina | +| `availabilityType` | No | Controlla dove compare il comando: `'GLOBAL'` (sempre disponibile), `'RECORD_SELECTION'` (solo quando sono selezionati dei record) o `'FALLBACK'` (mostrato quando nessun altro comando corrisponde) | +| `availabilityObjectUniversalIdentifier` | No | Limita il comando alle pagine di uno specifico tipo di oggetto (ad es. solo sui record Company) | +| `conditionalAvailabilityExpression` | No | Un'espressione booleana per controllare dinamicamente se il comando è visibile (vedi sotto) | -#### Conditional availability expressions +#### Espressioni di disponibilità condizionale -The `conditionalAvailabilityExpression` field lets you control when a command is visible based on the current page context. Import typed variables and operators from `twenty-sdk` to build expressions: +Il campo `conditionalAvailabilityExpression` consente di controllare quando un comando è visibile in base al contesto della pagina corrente. Importa variabili tipizzate e operatori da `twenty-sdk` per costruire espressioni: ```tsx import { @@ -905,45 +904,45 @@ export default defineFrontComponent({ }); ``` -**Context variables** — these represent the current state of the page: +**Variabili di contesto** — rappresentano lo stato corrente della pagina: -| Variabile | Tipo | Descrizione | -| ------------------------------ | --------- | ---------------------------------------------------------------- | -| `pageType` | `string` | Current page type (e.g. `'RecordIndexPage'`, `'RecordShowPage'`) | -| `isInSidePanel` | `boolean` | Whether the component is rendered in a side panel | -| `numberOfSelectedRecords` | `numero` | Number of currently selected records | -| `isSelectAll` | `boolean` | Whether "select all" is active | -| `selectedRecords` | `array` | The selected record objects | -| `favoriteRecordIds` | `array` | IDs of favorited records | -| `objectPermissions` | `oggetto` | Permissions for the current object type | -| `targetObjectReadPermissions` | `oggetto` | Read permissions for the target object | -| `targetObjectWritePermissions` | `oggetto` | Write permissions for the target object | -| `featureFlags` | `oggetto` | Active feature flags | -| `objectMetadataItem` | `oggetto` | Metadata of the current object type | -| `hasAnySoftDeleteFilterOnView` | `boolean` | Whether the current view has a soft-delete filter | +| Variabile | Tipo | Descrizione | +| ------------------------------ | --------- | ------------------------------------------------------------------------ | +| `pageType` | `string` | Tipo di pagina corrente (ad es. `'RecordIndexPage'`, `'RecordShowPage'`) | +| `isInSidePanel` | `boolean` | Indica se il componente è renderizzato in un pannello laterale | +| `numberOfSelectedRecords` | `numero` | Numero di record attualmente selezionati | +| `isSelectAll` | `boolean` | Indica se "seleziona tutto" è attivo | +| `selectedRecords` | `array` | Gli oggetti dei record selezionati | +| `favoriteRecordIds` | `array` | ID dei record aggiunti ai preferiti | +| `objectPermissions` | `oggetto` | Autorizzazioni per il tipo di oggetto corrente | +| `targetObjectReadPermissions` | `oggetto` | Autorizzazioni di lettura per l'oggetto di destinazione | +| `targetObjectWritePermissions` | `oggetto` | Autorizzazioni di scrittura per l'oggetto di destinazione | +| `featureFlags` | `oggetto` | Flag delle funzionalità attivi | +| `objectMetadataItem` | `oggetto` | Metadati del tipo di oggetto corrente | +| `hasAnySoftDeleteFilterOnView` | `boolean` | Indica se la vista corrente ha un filtro di soft-delete | -**Operators** — combine variables into boolean expressions: +**Operatori** — combinano variabili in espressioni booleane: -| Operator | Descrizione | -| ----------------------------------- | ----------------------------------------------------------------- | -| `isDefined(value)` | `true` if the value is not null/undefined | -| `isNonEmptyString(value)` | `true` if the value is a non-empty string | -| `includes(array, value)` | `true` if the array contains the value | -| `includesEvery(array, prop, value)` | `true` if every item's property includes the value | -| `every(array, prop)` | `true` if the property is truthy on every item | -| `everyDefined(array, prop)` | `true` if the property is defined on every item | -| `everyEquals(array, prop, value)` | `true` if the property equals the value on every item | -| `some(array, prop)` | `true` if the property is truthy on at least one item | -| `someDefined(array, prop)` | `true` if the property is defined on at least one item | -| `someEquals(array, prop, value)` | `true` if the property equals the value on at least one item | -| `someNonEmptyString(array, prop)` | `true` if the property is a non-empty string on at least one item | -| `none(array, prop)` | `true` if the property is falsy on every item | -| `noneDefined(array, prop)` | `true` if the property is undefined on every item | -| `noneEquals(array, prop, value)` | `true` if the property does not equal the value on any item | +| Operatore | Descrizione | +| ----------------------------------- | -------------------------------------------------------------------- | +| `isDefined(value)` | `true` se il valore non è null/undefined | +| `isNonEmptyString(value)` | `true` se il valore è una stringa non vuota | +| `includes(array, value)` | `true` se l'array contiene il valore | +| `includesEvery(array, prop, value)` | `true` se la proprietà di ogni elemento include il valore | +| `every(array, prop)` | `true` se la proprietà è truthy su ogni elemento | +| `everyDefined(array, prop)` | `true` se la proprietà è definita su ogni elemento | +| `everyEquals(array, prop, value)` | `true` se la proprietà è uguale al valore su ogni elemento | +| `some(array, prop)` | `true` se la proprietà è truthy su almeno un elemento | +| `someDefined(array, prop)` | `true` se la proprietà è definita su almeno un elemento | +| `someEquals(array, prop, value)` | `true` se la proprietà è uguale al valore su almeno un elemento | +| `someNonEmptyString(array, prop)` | `true` se la proprietà è una stringa non vuota su almeno un elemento | +| `none(array, prop)` | `true` se la proprietà è falsy su ogni elemento | +| `noneDefined(array, prop)` | `true` se la proprietà è undefined su ogni elemento | +| `noneEquals(array, prop, value)` | `true` se la proprietà non è uguale al valore su alcun elemento | -#### Public assets +#### Asset pubblici -Front components can access files from the app's `public/` directory using `getPublicAssetUrl`: +I componenti front-end possono accedere ai file dalla directory `public/` dell'app utilizzando `getPublicAssetUrl`: ```tsx import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk'; @@ -957,18 +956,18 @@ export default defineFrontComponent({ }); ``` -See the [public assets section](#accessing-public-assets-with-getpublicasseturl) for details. +Vedi la [sezione sugli asset pubblici](#accessing-public-assets-with-getpublicasseturl) per i dettagli. #### Stile -Front components support multiple styling approaches. You can use: +I componenti front-end supportano diversi approcci di styling. Puoi usare: -* **Inline styles** — `style={{ color: 'red' }}` -* **Twenty UI components** — import from `twenty-sdk/ui` (Button, Tag, Status, Chip, Avatar, and more) -* **Emotion** — CSS-in-JS with `@emotion/react` -* **Styled-components** — `styled.div` patterns -* **Tailwind CSS** — utility classes -* **Any CSS-in-JS library** compatible with React +* **Stili inline** — `style={{ color: 'red' }}` +* **Componenti Twenty UI** — importali da `twenty-sdk/ui` (Button, Tag, Status, Chip, Avatar e altro) +* **Emotion** — CSS-in-JS con `@emotion/react` +* **Styled-components** — pattern `styled.div` +* **Tailwind CSS** — classi di utilità +* **Qualsiasi libreria CSS-in-JS** compatibile con React ```tsx import { defineFrontComponent } from 'twenty-sdk'; @@ -1022,9 +1021,9 @@ Punti chiave: * `description` (opzionale) fornisce contesto aggiuntivo sullo scopo della skill.
- + -Agents are AI assistants that live inside your workspace. Use `defineAgent()` to create agents with a custom system prompt: +Gli agenti sono assistenti IA che vivono all'interno del tuo spazio di lavoro. Usa `defineAgent()` per creare agenti con un prompt di sistema personalizzato: ```ts src/agents/example-agent.ts import { defineAgent } from 'twenty-sdk'; @@ -1040,17 +1039,17 @@ export default defineAgent({ ``` Punti chiave: -* `name` is the unique identifier string for the agent (kebab-case recommended). -* `label` is the display name shown in the UI. -* `prompt` is the system prompt that defines the agent's behavior. -* `description` (optional) provides context about what the agent does. +* `name` è la stringa identificativa univoca dell'agente (kebab-case consigliato). +* `label` è il nome visualizzato nell'UI. +* `prompt` è il prompt di sistema che definisce il comportamento dell'agente. +* `description` (opzionale) fornisce contesto su ciò che fa l'agente. * `icon` (opzionale) imposta l'icona visualizzata nell'UI. -* `modelId` (optional) overrides the default AI model used by the agent. +* `modelId` (opzionale) sostituisce il modello di IA predefinito utilizzato dall'agente. -Views are saved configurations for how records of an object are displayed — including which fields are visible, their order, and any filters or groups applied. Use `defineView()` to ship pre-configured views with your app: +Le viste sono configurazioni salvate di come vengono visualizzati i record di un oggetto — inclusi quali campi sono visibili, il loro ordine e gli eventuali filtri o raggruppamenti applicati. Usa `defineView()` per fornire viste preconfigurate con la tua app: ```ts src/views/example-view.ts import { defineView, ViewKey } from 'twenty-sdk'; @@ -1077,16 +1076,16 @@ export default defineView({ ``` Punti chiave: -* `objectUniversalIdentifier` specifies which object this view applies to. -* `key` determines the view type (e.g., `ViewKey.INDEX` for the main list view). -* `fields` controls which columns appear and their order. Each field references a `fieldMetadataUniversalIdentifier`. -* You can also define `filters`, `filterGroups`, `groups`, and `fieldGroups` for more advanced configurations. -* `position` controls the ordering when multiple views exist for the same object. +* `objectUniversalIdentifier` specifica a quale oggetto si applica questa vista. +* `key` determina il tipo di vista (ad es., `ViewKey.INDEX` per la vista elenco principale). +* `fields` controlla quali colonne compaiono e il loro ordine. Ogni campo fa riferimento a un `fieldMetadataUniversalIdentifier`. +* Puoi anche definire `filters`, `filterGroups`, `groups` e `fieldGroups` per configurazioni più avanzate. +* `position` controlla l'ordinamento quando esistono più viste per lo stesso oggetto. -Navigation menu items add custom entries to the workspace sidebar. Use `defineNavigationMenuItem()` to link to views, external URLs, or objects: +Le voci del menu di navigazione aggiungono elementi personalizzati alla barra laterale dello spazio di lavoro. Usa `defineNavigationMenuItem()` per collegarti a viste, URL esterni o oggetti: ```ts src/navigation-menu-items/example-navigation-menu-item.ts import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk'; @@ -1104,15 +1103,15 @@ export default defineNavigationMenuItem({ ``` Punti chiave: -* `type` determines what the menu item links to: `NavigationMenuItemType.VIEW` for a saved view, or `NavigationMenuItemType.LINK` for an external URL. -* For view links, set `viewUniversalIdentifier`. For external links, set `link`. -* `position` controls the ordering in the sidebar. -* `icon` and `color` (optional) customize the appearance. +* `type` determina a cosa rimanda la voce di menu: `NavigationMenuItemType.VIEW` per una vista salvata o `NavigationMenuItemType.LINK` per un URL esterno. +* Per i link a viste, imposta `viewUniversalIdentifier`. Per i link esterni, imposta `link`. +* `position` controlla l'ordinamento nella barra laterale. +* `icon` e `color` (opzionali) personalizzano l'aspetto. - + -Page layouts let you customize how a record detail page looks — which tabs appear, what widgets are inside each tab, and how they are arranged. Use `definePageLayout()` to ship custom layouts with your app: +I layout di pagina ti consentono di personalizzare l'aspetto di una pagina dei dettagli di un record — quali schede compaiono, quali widget sono all'interno di ciascuna scheda e come sono disposti. Usa `definePageLayout()` per fornire layout personalizzati con la tua app: ```ts src/page-layouts/example-record-page-layout.ts import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk'; @@ -1149,33 +1148,33 @@ export default definePageLayout({ ``` Punti chiave: -* `type` is typically `'RECORD_PAGE'` to customize the detail view of a specific object. -* `objectUniversalIdentifier` specifies which object this layout applies to. -* Each `tab` defines a section of the page with a `title`, `position`, and `layoutMode` (`CANVAS` for free-form layout). -* Each `widget` inside a tab can render a front component, a relation list, or other built-in widget types. -* `position` on tabs controls their order. Use higher values (e.g., 50) to place custom tabs after built-in ones. +* `type` è in genere `'RECORD_PAGE'` per personalizzare la vista dei dettagli di un oggetto specifico. +* `objectUniversalIdentifier` specifica a quale oggetto si applica questo layout. +* Ogni `tab` definisce una sezione della pagina con un `title`, `position` e `layoutMode` (`CANVAS` per il layout libero). +* Ogni `widget` all'interno di una scheda può renderizzare un componente front-end, un elenco di relazioni o altri tipi di widget integrati. +* `position` sulle schede controlla il loro ordine. Usa valori più alti (ad es., 50) per posizionare le schede personalizzate dopo quelle integrate.
-## Public assets (`public/` folder) +## Asset pubblici (cartella `public/`) -The `public/` folder at the root of your app holds static files — images, icons, fonts, or any other assets your app needs at runtime. These files are automatically included in builds, synced during dev mode, and uploaded to the server. +La cartella `public/` alla radice della tua app contiene file statici — immagini, icone, font o qualsiasi altro asset di cui la tua app ha bisogno a runtime. Questi file sono inclusi automaticamente nelle build, sincronizzati durante la modalità di sviluppo e caricati sul server. -Files placed in `public/` are: +I file posizionati in `public/` sono: -* **Publicly accessible** — once synced to the server, assets are served at a public URL. No authentication is needed to access them. -* **Available in front components** — use asset URLs to display images, icons, or any media inside your React components. -* **Available in logic functions** — reference asset URLs in emails, API responses, or any server-side logic. -* **Used for marketplace metadata** — the `logoUrl` and `screenshots` fields in `defineApplication()` reference files from this folder (e.g., `public/logo.png`). These are displayed in the marketplace when your app is published. -* **Auto-synced in dev mode** — when you add, update, or delete a file in `public/`, it is synced to the server automatically. No restart needed. -* **Included in builds** — `yarn twenty build` bundles all public assets into the distribution output. +* **Pubblicamente accessibili** — una volta sincronizzati sul server, gli asset sono serviti a un URL pubblico. Non è necessaria alcuna autenticazione per accedervi. +* **Disponibili nei componenti front-end** — usa gli URL degli asset per visualizzare immagini, icone o qualsiasi media all'interno dei tuoi componenti React. +* **Disponibili nelle funzioni logiche** — fai riferimento agli URL degli asset nelle email, nelle risposte API o in qualsiasi logica lato server. +* **Usati per i metadati del marketplace** — i campi `logoUrl` e `screenshots` in `defineApplication()` fanno riferimento a file di questa cartella (ad es., `public/logo.png`). Questi vengono visualizzati nel marketplace quando la tua app viene pubblicata. +* **Sincronizzati automaticamente in modalità dev** — quando aggiungi, aggiorni o elimini un file in `public/`, viene sincronizzato automaticamente con il server. Nessun riavvio necessario. +* **Inclusi nelle build** — `yarn twenty build` raggruppa tutti gli asset pubblici nell'output di distribuzione. -### Accessing public assets with `getPublicAssetUrl` +### Accedere agli asset pubblici con `getPublicAssetUrl` -Use the `getPublicAssetUrl` helper from `twenty-sdk` to get the full URL of a file in your `public/` directory. It works in both **logic functions** and **front components**. +Usa l'helper `getPublicAssetUrl` da `twenty-sdk` per ottenere l'URL completo di un file nella tua directory `public/`. Funziona sia nelle funzioni logiche che nei componenti front-end. -**In a logic function:** +**In una funzione logica:** ```ts src/logic-functions/send-invoice.ts import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk'; @@ -1200,7 +1199,7 @@ export default defineLogicFunction({ }); ``` -**In a front component:** +**In un componente front-end:** ```tsx src/front-components/company-card.tsx import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk'; @@ -1212,19 +1211,19 @@ export default defineFrontComponent(() => { }); ``` -The `path` argument is relative to your app's `public/` folder. Both `getPublicAssetUrl('logo.png')` and `getPublicAssetUrl('public/logo.png')` resolve to the same URL — the `public/` prefix is stripped automatically if present. +L'argomento `path` è relativo alla cartella `public/` della tua app. Sia `getPublicAssetUrl('logo.png')` sia `getPublicAssetUrl('public/logo.png')` risolvono allo stesso URL — il prefisso `public/` viene rimosso automaticamente se presente. -## Using npm packages +## Uso dei pacchetti npm -You can install and use any npm package in your app. Both logic functions and front components are bundled with [esbuild](https://esbuild.github.io/), which inlines all dependencies into the output — no `node_modules` are needed at runtime. +Puoi installare e usare qualsiasi pacchetto npm nella tua app. Sia le funzioni logiche sia i componenti front-end vengono impacchettati con [esbuild](https://esbuild.github.io/), che incorpora tutte le dipendenze nell'output — non sono necessari i `node_modules` a runtime. -### Installing a package +### Installazione di un pacchetto ```bash filename="Terminal" yarn add axios ``` -Then import it in your code: +Quindi importalo nel tuo codice: ```ts src/logic-functions/fetch-data.ts import { defineLogicFunction } from 'twenty-sdk'; @@ -1245,7 +1244,7 @@ export default defineLogicFunction({ }); ``` -The same works for front components: +Lo stesso vale per i componenti front-end: ```tsx src/front-components/chart.tsx import { defineFrontComponent } from 'twenty-sdk'; @@ -1262,27 +1261,27 @@ export default defineFrontComponent({ }); ``` -### How bundling works +### Come funziona il bundling -The build step (`yarn twenty dev` or `yarn twenty build`) uses esbuild to produce a single self-contained file per logic function and per front component. All imported packages are inlined into the bundle. +La fase di build (`yarn twenty dev` o `yarn twenty build`) usa esbuild per produrre un singolo file autonomo per ogni funzione logica e per ogni componente front-end. Tutti i pacchetti importati sono incorporati nel bundle. -**Logic functions** run in a Node.js environment. Node built-in modules (`fs`, `path`, `crypto`, `http`, etc.) are available and do not need to be installed. +**Le funzioni logiche** vengono eseguite in un ambiente Node.js. I moduli integrati di Node (`fs`, `path`, `crypto`, `http`, ecc.) sono disponibili e non necessitano di essere installati. -**Front components** run in a Web Worker. Node built-in modules are **not** available — only browser APIs and npm packages that work in a browser environment. +**I componenti front-end** vengono eseguiti in un Web Worker. I moduli integrati di Node non sono disponibili — solo le API del browser e i pacchetti npm che funzionano in un ambiente browser. -Both environments have `twenty-client-sdk/core` and `twenty-client-sdk/metadata` available as pre-provided modules — these are not bundled but resolved at runtime by the server. +Entrambi gli ambienti hanno `twenty-client-sdk/core` e `twenty-client-sdk/metadata` disponibili come moduli preforniti — questi non vengono inclusi nel bundle ma vengono risolti a runtime dal server. -## Scaffolding entities with `yarn twenty add` +## Creazione di entità con lo scaffolding tramite `yarn twenty add` -Instead of creating entity files by hand, you can use the interactive scaffolder: +Invece di creare manualmente i file delle entità, puoi usare lo scaffolder interattivo: ```bash filename="Terminal" yarn twenty add ``` -This prompts you to pick an entity type and walks you through the required fields. It generates a ready-to-use file with a stable `universalIdentifier` and the correct `defineEntity()` call. +Questo ti chiede di scegliere un tipo di entità e ti guida attraverso i campi richiesti. Genera un file pronto all'uso con un `universalIdentifier` stabile e la corretta chiamata a `defineEntity()`. -You can also pass the entity type directly to skip the first prompt: +Puoi anche passare direttamente il tipo di entità per saltare il primo prompt: ```bash filename="Terminal" yarn twenty add object @@ -1290,44 +1289,44 @@ yarn twenty add logicFunction yarn twenty add frontComponent ``` -### Available entity types +### Tipi di entità disponibili -| Tipo di entità | Comando | Generated file | -| -------------------- | ------------------------------------ | ------------------------------------- | -| Oggetto | `yarn twenty add object` | `src/objects/.ts` | -| Campo | `yarn twenty add field` | `src/fields/.ts` | -| Logic function | `yarn twenty add logicFunction` | `src/logic-functions/.ts` | -| Front component | `yarn twenty add frontComponent` | `src/front-components/.tsx` | -| Ruolo | `yarn twenty add role` | `src/roles/.ts` | -| Abilità | `yarn twenty add skill` | `src/skills/.ts` | -| Agente | `yarn twenty add agent` | `src/agents/.ts` | -| Vista | `yarn twenty add view` | `src/views/.ts` | -| Navigation menu item | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/.ts` | -| Page layout | `yarn twenty add pageLayout` | `src/page-layouts/.ts` | +| Tipo di entità | Comando | File generato | +| ---------------------------- | ------------------------------------ | ------------------------------------- | +| Oggetto | `yarn twenty add object` | `src/objects/.ts` | +| Campo | `yarn twenty add field` | `src/fields/.ts` | +| Funzione logica | `yarn twenty add logicFunction` | `src/logic-functions/.ts` | +| Componente front-end | `yarn twenty add frontComponent` | `src/front-components/.tsx` | +| Ruolo | `yarn twenty add role` | `src/roles/.ts` | +| Abilità | `yarn twenty add skill` | `src/skills/.ts` | +| Agente | `yarn twenty add agent` | `src/agents/.ts` | +| Vista | `yarn twenty add view` | `src/views/.ts` | +| Voce del menu di navigazione | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/.ts` | +| Layout di pagina | `yarn twenty add pageLayout` | `src/page-layouts/.ts` | -### What the scaffolder generates +### Cosa genera lo scaffolder -Each entity type has its own template. For example, `yarn twenty add object` asks for: +Ogni tipo di entità ha il proprio template. Ad esempio, `yarn twenty add object` richiede: -1. **Name (singular)** — e.g., `invoice` -2. **Name (plural)** — e.g., `invoices` -3. **Label (singular)** — auto-populated from the name (e.g., `Invoice`) -4. **Label (plural)** — auto-populated (e.g., `Invoices`) -5. **Create a view and navigation item?** — if you answer yes, the scaffolder also generates a matching view and sidebar link for the new object. +1. **Nome (singolare)** — ad es., `invoice` +2. **Nome (plurale)** — ad es., `invoices` +3. **Etichetta (singolare)** — compilata automaticamente dal nome (ad es., `Invoice`) +4. **Etichetta (plurale)** — compilata automaticamente (ad es., `Invoices`) +5. **Creare una vista e una voce di navigazione?** — se rispondi sì, lo scaffolder genera anche una vista corrispondente e un link nella barra laterale per il nuovo oggetto. -Other entity types have simpler prompts — most only ask for a name. +Gli altri tipi di entità hanno prompt più semplici — la maggior parte chiede solo un nome. -The `field` entity type is more detailed: it asks for the field name, label, type (from a list of all available field types like `TEXT`, `NUMBER`, `SELECT`, `RELATION`, etc.), and the target object's `universalIdentifier`. +Il tipo di entità `field` è più dettagliato: chiede il nome del campo, l'etichetta, il tipo (da un elenco di tutti i tipi di campo disponibili come `TEXT`, `NUMBER`, `SELECT`, `RELATION`, ecc.) e l'`universalIdentifier` dell'oggetto di destinazione. -### Custom output path +### Percorso di output personalizzato -Use the `--path` flag to place the generated file in a custom location: +Usa il flag `--path` per posizionare il file generato in una posizione personalizzata: ```bash filename="Terminal" yarn twenty add logicFunction --path src/custom-folder ``` -## Typed API clients (twenty-client-sdk) +## Client API tipizzati (twenty-client-sdk) Il pacchetto `twenty-client-sdk` fornisce due client GraphQL tipizzati per interagire con l'API di Twenty dalle tue funzioni logiche e dai componenti front-end. @@ -1337,9 +1336,9 @@ Il pacchetto `twenty-client-sdk` fornisce due client GraphQL tipizzati per inter | `MetadataApiClient` | `twenty-client-sdk/metadata` | `/metadata` — configurazione dello spazio di lavoro, caricamenti di file | No, fornito pronto all'uso | - + -`CoreApiClient` è il client principale per interrogare e modificare i dati dello spazio di lavoro. It is **generated from your workspace schema** during `yarn twenty dev` or `yarn twenty build`, so it is fully typed to match your objects and fields. +`CoreApiClient` è il client principale per interrogare e modificare i dati dello spazio di lavoro. Viene **generato dallo schema del tuo spazio di lavoro** durante `yarn twenty dev` o `yarn twenty build`, quindi è completamente tipizzato per corrispondere ai tuoi oggetti e campi. ```ts import { CoreApiClient } from 'twenty-client-sdk/core'; @@ -1379,12 +1378,12 @@ const { createCompany } = await client.mutation({ Il client utilizza una sintassi a selection-set: passa `true` per includere un campo, usa `__args` per gli argomenti e annida oggetti per le relazioni. Ottieni completamento automatico e controllo dei tipi completi basati sullo schema del tuo spazio di lavoro. -**CoreApiClient is generated at dev/build time.** If you use it without running `yarn twenty dev` or `yarn twenty build` first, it throws an error. The generation happens automatically — the CLI introspects your workspace's GraphQL schema and generates a typed client using `@genql/cli`. +**CoreApiClient viene generato in fase di dev/build.** Se lo usi senza eseguire prima `yarn twenty dev` o `yarn twenty build`, genera un errore. La generazione avviene automaticamente — la CLI esegue l'introspezione dello schema GraphQL del tuo spazio di lavoro e genera un client tipizzato usando `@genql/cli`. #### Utilizzo di CoreSchema per le annotazioni di tipo -`CoreSchema` provides TypeScript types matching your workspace objects — useful for typing component state or function parameters: +`CoreSchema` fornisce tipi TypeScript corrispondenti agli oggetti del tuo spazio di lavoro — utile per tipizzare lo stato dei componenti o i parametri delle funzioni: ```ts import { CoreApiClient, CoreSchema } from 'twenty-client-sdk/core'; @@ -1406,7 +1405,7 @@ setCompany(result.company); ``` - + `MetadataApiClient` è fornito pronto all'uso con l'SDK (nessuna generazione richiesta). Interroga l'endpoint `/metadata` per la configurazione dello spazio di lavoro, le applicazioni e i caricamenti di file. @@ -1462,7 +1461,7 @@ console.log(uploadedFile); | ---------------------------------- | -------- | ---------------------------------------------------------------------- | | `fileBuffer` | `Buffer` | Il contenuto grezzo del file | | `filename` | `string` | Il nome del file (utilizzato per l'archiviazione e la visualizzazione) | -| `contentType` | `string` | MIME type (defaults to `application/octet-stream` if omitted) | +| `contentType` | `string` | Tipo MIME (predefinito su `application/octet-stream` se omesso) | | `fieldMetadataUniversalIdentifier` | `string` | L'`universalIdentifier` del campo di tipo file nel tuo oggetto | Punti chiave: @@ -1476,24 +1475,24 @@ Punti chiave: Quando il tuo codice viene eseguito su Twenty (funzioni logiche o componenti front-end), la piattaforma inietta le credenziali come variabili d'ambiente: * `TWENTY_API_URL` — URL di base dell'API di Twenty - * `TWENTY_APP_ACCESS_TOKEN` — Short-lived key scoped to your application's default function role + * `TWENTY_APP_ACCESS_TOKEN` — Chiave a breve durata con ambito al ruolo funzione predefinito della tua applicazione Non è **necessario** passarle ai client — vengono lette automaticamente da `process.env`. I permessi della chiave API sono determinati dal ruolo referenziato in `defaultRoleUniversalIdentifier` nel tuo `application-config.ts`. -## Testing your app +## Testare la tua app -The SDK provides programmatic APIs that let you build, deploy, install, and uninstall your app from test code. Combined with [Vitest](https://vitest.dev/) and the typed API clients, you can write integration tests that verify your app works end-to-end against a real Twenty server. +L'SDK fornisce API programmatiche che ti consentono di compilare, distribuire, installare e disinstallare la tua app dal codice di test. In combinazione con [Vitest](https://vitest.dev/) e i client API tipizzati, puoi scrivere test di integrazione che verificano che la tua app funzioni end-to-end contro un server Twenty reale. ### Impostazione -The scaffolded app already includes Vitest. If you set it up manually, install the dependencies: +L'app generata tramite scaffolding include già Vitest. Se la configuri manualmente, installa le dipendenze: ```bash filename="Terminal" yarn add -D vitest vite-tsconfig-paths ``` -Create a `vitest.config.ts` at the root of your app: +Crea un `vitest.config.ts` alla radice della tua app: ```ts vitest.config.ts import tsconfigPaths from 'vite-tsconfig-paths'; @@ -1519,7 +1518,7 @@ export default defineConfig({ }); ``` -Create a setup file that verifies the server is reachable before tests run: +Crea un file di setup che verifichi che il server sia raggiungibile prima dell'esecuzione dei test: ```ts src/__tests__/setup-test.ts import * as fs from 'fs'; @@ -1559,22 +1558,22 @@ beforeAll(async () => { }); ``` -### Programmatic SDK APIs +### API programmatiche dell'SDK -The `twenty-sdk/cli` subpath exports functions you can call directly from test code: +Il sottopercorso `twenty-sdk/cli` esporta funzioni che puoi chiamare direttamente dal codice di test: -| Funzione | Descrizione | -| -------------- | ------------------------------------------- | -| `appBuild` | Build the app and optionally pack a tarball | -| `appDeploy` | Upload a tarball to the server | -| `appInstall` | Install the app on the active workspace | -| `appUninstall` | Uninstall the app from the active workspace | +| Funzione | Descrizione | +| -------------- | ----------------------------------------------- | +| `appBuild` | Compila l'app e, opzionalmente, crea un tarball | +| `appDeploy` | Carica un tarball sul server | +| `appInstall` | Installa l'app nello spazio di lavoro attivo | +| `appUninstall` | Disinstalla l'app dallo spazio di lavoro attivo | -Each function returns a result object with `success: boolean` and either `data` or `error`. +Ogni funzione restituisce un oggetto risultato con `success: boolean` e `data` oppure `error`. -### Writing an integration test +### Scrivere un test di integrazione -Here is a full example that builds, deploys, and installs the app, then verifies it appears in the workspace: +Ecco un esempio completo che compila, distribuisce e installa l'app, quindi verifica che compaia nello spazio di lavoro: ```ts src/__tests__/app-install.integration-test.ts import { APPLICATION_UNIVERSAL_IDENTIFIER } from 'src/application-config'; @@ -1637,37 +1636,37 @@ describe('App installation', () => { }); ``` -### Running tests +### Esecuzione dei test -Make sure your local Twenty server is running, then: +Assicurati che il tuo server Twenty locale sia in esecuzione, quindi: ```bash filename="Terminal" yarn test ``` -Or in watch mode during development: +Oppure in modalità watch durante lo sviluppo: ```bash filename="Terminal" yarn test:watch ``` -### Type checking +### Controllo dei tipi -You can also run type checking on your app without running tests: +Puoi anche eseguire il controllo dei tipi sulla tua app senza eseguire i test: ```bash filename="Terminal" yarn twenty typecheck ``` -This runs `tsc --noEmit` and reports any type errors. +Questo esegue `tsc --noEmit` e riporta eventuali errori di tipo. ## Riferimento CLI -Beyond `dev`, `build`, `add`, and `typecheck`, the CLI provides commands for executing functions, viewing logs, and managing app installations. +Oltre a `dev`, `build`, `add` e `typecheck`, la CLI fornisce comandi per eseguire funzioni, visualizzare i log e gestire le installazioni delle app. -### Executing functions (`yarn twenty exec`) +### Esecuzione delle funzioni (`yarn twenty exec`) -Run a logic function manually without triggering it via HTTP, cron, or database event: +Esegui manualmente una funzione logica senza attivarla tramite HTTP, cron o evento del database: ```bash filename="Terminal" # Execute by function name @@ -1684,9 +1683,9 @@ yarn twenty exec --preInstall yarn twenty exec --postInstall ``` -### Viewing function logs (`yarn twenty logs`) +### Visualizzazione dei log delle funzioni (`yarn twenty logs`) -Stream execution logs for your app's logic functions: +Esegui lo streaming dei log di esecuzione per le funzioni logiche della tua app: ```bash filename="Terminal" # Stream all function logs @@ -1700,12 +1699,12 @@ yarn twenty logs -u e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf ``` -This is different from `yarn twenty server logs`, which shows the Docker container logs. `yarn twenty logs` shows your app's function execution logs from the Twenty server. +Questo è diverso da `yarn twenty server logs`, che mostra i log del container Docker. `yarn twenty logs` mostra i log di esecuzione delle funzioni della tua app dal server Twenty. -### Uninstalling an app (`yarn twenty uninstall`) +### Disinstallazione di un'app (`yarn twenty uninstall`) -Remove your app from the active workspace: +Rimuovi la tua app dallo spazio di lavoro attivo: ```bash filename="Terminal" yarn twenty uninstall diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/building.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/building.mdx index 334932bb4a..b90ac47556 100644 --- a/packages/twenty-docs/l/ro/developers/extend/apps/building.mdx +++ b/packages/twenty-docs/l/ro/developers/extend/apps/building.mdx @@ -4,24 +4,24 @@ description: Definiți obiecte, funcții logice, componente front-end și multe --- - Apps are currently in alpha. The feature works but is still evolving. + Aplicațiile sunt în prezent în testare alfa. Caracteristica funcționează, dar este încă în dezvoltare. -The `twenty-sdk` package provides typed building blocks to create your app. This page covers every entity type and API client available in the SDK. +Pachetul `twenty-sdk` oferă blocuri de construcție tipizate pentru a crea aplicația. Această pagină acoperă toate tipurile de entități și clienții API disponibili în SDK. -## DefineEntity functions +## Funcții DefineEntity -The SDK provides functions to define your app entities. You must use `export default defineEntity({...})` for the SDK to detect your entities. Aceste funcții validează configurația în timpul build-ului și oferă completare automată în IDE și siguranța tipurilor. +SDK-ul oferă funcții pentru definirea entităților aplicației. Trebuie să folosiți `export default defineEntity({...})` pentru ca SDK-ul să detecteze entitățile. Aceste funcții validează configurația în timpul build-ului și oferă completare automată în IDE și siguranța tipurilor. - **File organization is up to you.** - Entity detection is AST-based — the SDK finds `export default defineEntity(...)` calls regardless of where the file lives. Grouping files by type (e.g., `logic-functions/`, `roles/`) is just a convention, not a requirement. + **Organizarea fișierelor ține de dvs.** + Detectarea entităților este bazată pe AST — SDK-ul găsește apelurile `export default defineEntity(...)` indiferent unde se află fișierul. Gruparea fișierelor după tip (de exemplu, `logic-functions/`, `roles/`) este doar o convenție pentru organizarea codului, nu o cerință. -Roles encapsulate permissions on your workspace's objects and actions. +Rolurile încapsulează permisiuni asupra obiectelor și acțiunilor din spațiul dvs. de lucru. ```ts restricted-company-role.ts import { @@ -69,12 +69,12 @@ export default defineRole({ -Every app must have exactly one `defineApplication` call that describes: +Fiecare aplicație trebuie să aibă exact un apel `defineApplication` care descrie: -* **Identity**: identifiers, display name, and description. -* **Permissions**: which role its functions and front components use. -* **(Optional) Variables**: key–value pairs exposed to your functions as environment variables. -* **(Optional) Pre-install / post-install functions**: logic functions that run before or after installation. +* **Identitate**: identificatori, nume de afișare și descriere. +* **Permisiuni**: ce rol folosesc funcțiile și componentele front-end ale acesteia. +* **(Opțional) Variabile**: perechi cheie–valoare expuse funcțiilor ca variabile de mediu. +* **(Opțional) funcții de pre-instalare / post-instalare**: funcții logice care rulează înainte sau după instalare. ```ts src/application-config.ts import { defineApplication } from 'twenty-sdk'; @@ -98,21 +98,21 @@ export default defineApplication({ ``` Notițe: -* `universalIdentifier` fields are deterministic IDs you own. Generate them once and keep them stable across syncs. -* `applicationVariables` become environment variables for your functions and front components (e.g., `DEFAULT_RECIPIENT_NAME` is available as `process.env.DEFAULT_RECIPIENT_NAME`). -* `defaultRoleUniversalIdentifier` must reference a role defined with `defineRole()` (see above). -* Pre-install and post-install functions are detected automatically during the manifest build — you do not need to reference them in `defineApplication()`. +* Câmpurile `universalIdentifier` sunt ID-uri deterministe pe care le dețineți. Generați-le o singură dată și mențineți-le stabile între sincronizări. +* `applicationVariables` devin variabile de mediu pentru funcțiile și componentele front-end (de exemplu, `DEFAULT_RECIPIENT_NAME` este disponibil ca `process.env.DEFAULT_RECIPIENT_NAME`). +* `defaultRoleUniversalIdentifier` trebuie să facă referire la un rol definit cu `defineRole()` (vezi mai sus). +* Funcțiile de pre-instalare și post-instalare sunt detectate automat în timpul construirii manifestului — nu trebuie să le referiți în `defineApplication()`. #### Metadate pentru marketplace -If you plan to [publish your app](/l/ro/developers/extend/apps/publishing), these optional fields control how it appears in the marketplace: +Dacă intenționați să [publicați aplicația](/l/ro/developers/extend/apps/publishing), aceste câmpuri opționale controlează modul în care apare în marketplace: | Câmp | Descriere | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------ | | `autor` | Numele autorului sau al companiei | | `categorie` | Categoria aplicației pentru filtrarea în marketplace | -| `logoUrl` | Path to your app logo (e.g., `public/logo.png`) | -| `screenshots` | Array of screenshot paths (e.g., `public/screenshot-1.png`) | +| `logoUrl` | Calea către logo-ul aplicației (de ex., `public/logo.png`) | +| `screenshots` | Array de căi către capturi de ecran (de ex., `public/screenshot-1.png`) | | `aboutDescription` | Descriere markdown mai lungă pentru fila "About". Dacă este omis, marketplace-ul folosește `README.md` al pachetului de pe npm | | `websiteUrl` | Link către site-ul dvs. | | `termsUrl` | Link către termenii de serviciu | @@ -121,15 +121,15 @@ If you plan to [publish your app](/l/ro/developers/extend/apps/publishing), thes #### Roluri și permisiuni -The `defaultRoleUniversalIdentifier` in `application-config.ts` designates the default role used by your app's logic functions and front components. See `defineRole` above for details. +Câmpul `defaultRoleUniversalIdentifier` din `application-config.ts` desemnează rolul implicit utilizat de funcțiile logice și componentele front-end ale aplicației. Consultați `defineRole` mai sus pentru detalii. -* The runtime token injected as `TWENTY_APP_ACCESS_TOKEN` is derived from this role. -* The typed client is restricted to the permissions granted to that role. -* Follow least-privilege: create a dedicated role with only the permissions your functions need. +* Tokenul de runtime injectat ca `TWENTY_APP_ACCESS_TOKEN` este derivat din acest rol. +* Clientul tipizat este restricționat la permisiunile acordate acelui rol. +* Respectați principiul celui mai mic privilegiu: creați un rol dedicat doar cu permisiunile de care au nevoie funcțiile. -##### Default function role +##### Rol implicit pentru funcții -When you scaffold a new app, the CLI creates a default role file: +Când generați o aplicație nouă, CLI creează un fișier de rol implicit: ```ts src/roles/default-role.ts import { defineRole, PermissionFlag } from 'twenty-sdk'; @@ -155,16 +155,16 @@ export default defineRole({ }); ``` -This role's `universalIdentifier` is referenced in `application-config.ts` as `defaultRoleUniversalIdentifier`: +`universalIdentifier` al acestui rol este apoi referențiat în `application-config.ts` ca `defaultRoleUniversalIdentifier`. -* **\*.role.ts** defines what the role can do. +* **\*.role.ts** definește ce poate face rolul. * **application-config.ts** indică acel rol, astfel încât funcțiile moștenesc permisiunile lui. Notițe: * Porniți de la rolul generat, apoi restrângeți-l progresiv urmând principiul celui mai mic privilegiu. -* Replace `objectPermissions` and `fieldPermissions` with the objects and fields your functions actually need. -* `permissionFlags` controlează accesul la capabilități la nivelul platformei. Keep them minimal. -* See a working example: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). +* Înlocuiți `objectPermissions` și `fieldPermissions` cu obiectele și câmpurile de care au nevoie efectiv funcțiile. +* `permissionFlags` controlează accesul la capabilități la nivelul platformei. Mențineți-le la minimum. +* Vedeți un exemplu funcțional: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). @@ -256,7 +256,7 @@ dar acest lucru nu este recomandat. - + Utilizați `defineField()` pentru a adăuga câmpuri la obiecte pe care nu le dețineți — cum ar fi obiectele standard Twenty (Person, Company etc.). sau obiecte din alte aplicații. Spre deosebire de câmpurile inline din `defineObject()`, câmpurile independente necesită un `objectUniversalIdentifier` pentru a specifica obiectul pe care îl extind: @@ -284,7 +284,7 @@ Puncte cheie: * `defineField()` este singura modalitate de a adăuga câmpuri la obiecte pe care nu le-ați creat cu `defineObject()`. - + Relațiile conectează obiectele între ele. În Twenty, relațiile sunt întotdeauna bidirecționale — definiți ambele părți, iar fiecare parte o referențiază pe cealaltă. @@ -443,7 +443,7 @@ export default defineObject({ }); ``` - + Fiecare fișier de funcție folosește `defineLogicFunction()` pentru a exporta o configurație cu un handler și declanșatoare opționale. @@ -487,15 +487,15 @@ export default defineLogicFunction({ }); ``` -Available trigger types: -* **httpRoute**: Exposes your function on an HTTP path and method **under the `/s/` endpoint**: -> e.g. `path: '/post-card/create'` is callable at `https://your-twenty-server.com/s/post-card/create` +Tipuri de declanșatoare disponibile: +* **httpRoute**: Expune funcția pe o cale și metodă HTTP **sub endpoint-ul `/s/`**: +> de ex. `path: '/post-card/create'` este apelabil la `https://your-twenty-server.com/s/post-card/create` * **cron**: Rulează funcția pe un program folosind o expresie CRON. * **databaseEvent**: Rulează la evenimentele ciclului de viață ale obiectelor din spațiul de lucru. Când operațiunea evenimentului este `updated`, câmpurile specifice de urmărit pot fi specificate în array-ul `updatedFields`. Dacă este lăsat nedefinit sau gol, orice actualizare va declanșa funcția. -> e.g. `person.updated`, `*.created`, `company.*` +> de ex. `person.updated`, `*.created`, `company.*` -You can also manually execute a function using the CLI: +Puteți, de asemenea, să executați manual o funcție folosind CLI: ```bash filename="Terminal" yarn twenty exec -n create-new-post-card -p '{"key": "value"}' @@ -505,7 +505,7 @@ yarn twenty exec -n create-new-post-card -p '{"key": "value"}' yarn twenty exec -y e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf ``` -You can watch logs with: +Puteți urmări jurnalele cu: ```bash filename="Terminal" yarn twenty logs @@ -514,9 +514,9 @@ yarn twenty logs #### Payload-ul declanșatorului de rută -When a route trigger invokes your logic function, it receives a `RoutePayload` object that follows the +Când un declanșator de rută invocă funcția logică, aceasta primește un obiect `RoutePayload` care urmează [AWS HTTP API v2 format](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html). -Import the `RoutePayload` type from `twenty-sdk`: +Importați tipul `RoutePayload` din `twenty-sdk`: ```ts import { defineLogicFunction, type RoutePayload } from 'twenty-sdk'; @@ -533,9 +533,9 @@ Tipul `RoutePayload` are următoarea structură: | Proprietate | Tip | Descriere | Exemplu | | ---------------------------- | ------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------------------- | - | `headers` | `Record` | Anteturi HTTP (doar cele listate în `forwardedRequestHeaders`) | see section below | + | `headers` | `Record` | Anteturi HTTP (doar cele listate în `forwardedRequestHeaders`) | consultați secțiunea de mai jos | | `queryStringParameters` | `Record` | Parametri query string (valorile multiple unite cu virgule) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` | - | `pathParameters` | `Record` | Path parameters extracted from the route pattern | `/users/:id`, `/users/123` -> `{ id: '123' }` | + | `pathParameters` | `Record` | Parametri de cale extrași din modelul rutei | `/users/:id`, `/users/123` -> `{ id: '123' }` | | `body` | `object \| null` | Corpul cererii analizat (JSON) | `{ id: 1 }` -> `{ id: 1 }` | | `isBase64Encoded` | `boolean` | Indică dacă corpul este codificat în base64 | | | `requestContext.http.method` | `string` | Metoda HTTP (GET, POST, PUT, PATCH, DELETE) | | @@ -545,7 +545,7 @@ Tipul `RoutePayload` are următoarea structură: #### forwardedRequestHeaders În mod implicit, anteturile HTTP din cererile de intrare **nu** sunt transmise funcției dvs. de logică din motive de securitate. -To access specific headers, list them in the `forwardedRequestHeaders` array: +Pentru a accesa anumite anteturi, listează-le explicit în array-ul `forwardedRequestHeaders`: ```ts export default defineLogicFunction({ @@ -561,7 +561,7 @@ export default defineLogicFunction({ }); ``` -In your handler, access the forwarded headers like this: +În handler, accesați anteturile transmise mai departe astfel: ```ts const handler = async (event: RoutePayload) => { @@ -574,14 +574,14 @@ const handler = async (event: RoutePayload) => { ``` -Numele anteturilor sunt normalizate la litere mici. Access them using lowercase keys (e.g., `event.headers['content-type']`). +Numele anteturilor sunt normalizate la litere mici. Accesați-le folosind chei cu litere mici (de exemplu, `event.headers['content-type']`). -#### Exposing a function as a tool +#### Expunerea unei funcții ca instrument -Funcțiile logice pot fi expuse ca **instrumente** pentru agenți de IA și fluxuri de lucru. When marked as a tool, a function becomes discoverable by Twenty's AI features and can be used in workflow automations. +Funcțiile logice pot fi expuse ca **instrumente** pentru agenți de IA și fluxuri de lucru. Când este marcată ca instrument, o funcție poate fi descoperită de funcționalitățile de IA ale Twenty și poate fi utilizată în automatizări ale fluxurilor de lucru. -To mark a logic function as a tool, set `isTool: true`: +Pentru a marca o funcție logică drept instrument, setați `isTool: true`: ```ts src/logic-functions/enrich-company.logic-function.ts import { defineLogicFunction } from 'twenty-sdk'; @@ -617,8 +617,8 @@ export default defineLogicFunction({ Puncte cheie: -* You can combine `isTool` with triggers — a function can be both a tool (callable by AI agents) and triggered by events at the same time. -* **`toolInputSchema`** (optional): A JSON Schema object describing the parameters your function accepts. The schema is computed automatically from source code static analysis, but you can set it explicitly: +* Puteți combina `isTool` cu declanșatoare — o funcție poate fi atât un instrument (apelabilă de agenții AI), cât și declanșată de evenimente în același timp. +* **`toolInputSchema`** (opțional): Un obiect JSON Schema care descrie parametrii pe care îi acceptă funcția dvs. Schema este calculată automat prin analiză statică a codului sursă, dar o puteți seta explicit: ```ts export default defineLogicFunction({ @@ -715,11 +715,11 @@ Puncte cheie: -Front components are React components that render directly inside Twenty's UI. They run in an **isolated Web Worker** using Remote DOM — your code is sandboxed but renders natively in the page, not in an iframe. +Componentele front-end sunt componente React care se afișează direct în interfața Twenty. Rulează într-un **Web Worker** izolat folosind Remote DOM — codul este izolat (sandboxed), dar se redă nativ în pagină, nu într-un iframe. -#### Basic example +#### Exemplu de bază -The quickest way to see a front component in action is to register it as a **command**. Adding a `command` field with `isPinned: true` makes it appear as a quick-action button in the top-right corner of the page — no page layout needed: +Cel mai rapid mod de a vedea o componentă front-end în acțiune este să o înregistrați ca o **comandă**. Adăugarea unui câmp `command` cu `isPinned: true` o face să apară ca un buton de acțiune rapidă în colțul din dreapta sus al paginii — nu este nevoie de layout de pagină: ```tsx src/front-components/hello-world.tsx import { defineFrontComponent } from 'twenty-sdk'; @@ -749,34 +749,34 @@ export default defineFrontComponent({ }); ``` -After syncing with `yarn twenty dev`, the quick action appears in the top-right corner of the page: +După sincronizarea cu `yarn twenty dev`, acțiunea rapidă apare în colțul din dreapta sus al paginii:
- Quick action button in the top-right corner + Buton de acțiune rapidă în colțul din dreapta sus
-Click it to render the component inline. +Faceți clic pe el pentru a afișa componenta inline. {/* TODO: add screenshot of the rendered front component */} -#### Configuration fields +#### Câmpuri de configurare -| Câmp | Obligatoriu | Descriere | -| --------------------- | ----------- | ----------------------------------------------------------------------------------- | -| `universalIdentifier` | Da | Stable unique ID for this component | -| `component` | Da | A React component function | -| `name` | Nu | Display name | -| `description` | Nu | Description of what the component does | -| `isHeadless` | Nu | Set to `true` if the component has no visible UI (see below) | -| `command` | Nu | Register the component as a command (see [command options](#command-options) below) | +| Câmp | Obligatoriu | Descriere | +| --------------------- | ----------- | ------------------------------------------------------------------------------------------------ | +| `universalIdentifier` | Da | ID unic stabil pentru această componentă | +| `component` | Da | O funcție de componentă React | +| `name` | Nu | Nume afișat | +| `description` | Nu | Descriere a ceea ce face componenta | +| `isHeadless` | Nu | Setați la `true` dacă componenta nu are UI vizibilă (vezi mai jos) | +| `command` | Nu | Înregistrați componenta ca o comandă (consultați [opțiunile comenzii](#command-options) mai jos) | -#### Placing a front component on a page +#### Plasarea unei componente front-end pe o pagină -Beyond commands, you can embed a front component directly into a record page by adding it as a widget in a **page layout**. See the [definePageLayout](#definepagelayout) section for details. +Dincolo de comenzi, puteți încorpora o componentă front-end direct într-o pagină de înregistrare adăugând-o ca widget într-un **layout de pagină**. Consultați secțiunea [definePageLayout](#definepagelayout) pentru detalii. -#### Headless components (`isHeadless: true`) +#### Componente headless (`isHeadless: true`) -Headless components render no visible UI but still run React logic. This is useful for **effect components** — components that perform side effects when mounted, such as syncing data, starting a timer, listening to events, or triggering a notification. +Componentele headless nu redau nicio interfață vizibilă, dar rulează în continuare logica React. Acest lucru este util pentru **componente de efect** — componente care execută efecte secundare la montare, cum ar fi sincronizarea datelor, pornirea unui cronometru, ascultarea evenimentelor sau declanșarea unei notificări. ```tsx src/front-components/sync-tracker.tsx import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk'; @@ -801,11 +801,11 @@ export default defineFrontComponent({ }); ``` -Because the component returns `null`, Twenty skips rendering a container for it — no empty space appears in the layout. The component still has access to all hooks and the host communication API. +Deoarece componenta returnează `null`, Twenty omite redarea unui container pentru ea — nu apare spațiu gol în layout. Componenta are în continuare acces la toate hook-urile și la API-ul de comunicare cu gazda. -#### Accessing runtime context +#### Accesarea contextului de rulare -Inside your component, use SDK hooks to access the current user, record, and component instance: +În interiorul componentei, folosiți hook-urile SDK pentru a accesa utilizatorul curent, înregistrarea curentă și instanța componentei: ```tsx src/front-components/record-info.tsx import { @@ -836,47 +836,47 @@ export default defineFrontComponent({ }); ``` -Available hooks: +Hook-uri disponibile: -| Hook | Returns | Descriere | -| --------------------------------------------- | ------------------ | ---------------------------------------------------------- | -| `useUserId()` | `string` or `null` | The current user's ID | -| `useRecordId()` | `string` or `null` | The current record's ID (when placed on a record page) | -| `useFrontComponentId()` | `string` | This component instance's ID | -| `useFrontComponentExecutionContext(selector)` | variază | Access the full execution context with a selector function | +| Hook | Returnează | Descriere | +| --------------------------------------------- | ------------------- | --------------------------------------------------------------------------- | +| `useUserId()` | `string` sau `null` | ID-ul utilizatorului curent | +| `useRecordId()` | `string` sau `null` | ID-ul înregistrării curente (când este plasată pe o pagină de înregistrare) | +| `useFrontComponentId()` | `string` | ID-ul acestei instanțe de componentă | +| `useFrontComponentExecutionContext(selector)` | variază | Accesați întregul context de execuție cu o funcție selector | -#### Host communication API +#### API-ul de comunicare cu gazda -Front components can trigger navigation, modals, and notifications using functions from `twenty-sdk`: +Componentele front-end pot declanșa navigare, ferestre modale și notificări folosind funcții din `twenty-sdk`: -| Funcție | Descriere | -| ----------------------------------------------- | ----------------------------- | -| `navigate(to, params?, queryParams?, options?)` | Navigate to a page in the app | -| `openSidePanelPage(params)` | Open a side panel | -| `closeSidePanel()` | Close the side panel | -| `openCommandConfirmationModal(params)` | Show a confirmation dialog | -| `enqueueSnackbar(params)` | Show a toast notification | -| `unmountFrontComponent()` | Unmount the component | -| `updateProgress(progress)` | Update a progress indicator | +| Funcție | Descriere | +| ----------------------------------------------- | ----------------------------------- | +| `navigate(to, params?, queryParams?, options?)` | Navigați la o pagină din aplicație | +| `openSidePanelPage(params)` | Deschideți un panou lateral | +| `closeSidePanel()` | Închideți panoul lateral | +| `openCommandConfirmationModal(params)` | Afișați un dialog de confirmare | +| `enqueueSnackbar(params)` | Afișați o notificare tip toast | +| `unmountFrontComponent()` | Demontați componenta | +| `updateProgress(progress)` | Actualizați un indicator de progres | -#### Command options +#### Opțiuni pentru comandă -Adding a `command` field to `defineFrontComponent` registers the component in the command menu (Cmd+K). If `isPinned` is `true`, it also appears as a quick-action button in the top-right corner of the page. +Adăugarea unui câmp `command` la `defineFrontComponent` înregistrează componenta în meniul de comenzi (Cmd+K). Dacă `isPinned` este `true`, apare și ca buton de acțiune rapidă în colțul din dreapta sus al paginii. -| Câmp | Obligatoriu | Descriere | -| --------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `universalIdentifier` | Da | Stable unique ID for the command | -| `label` | Da | Full label shown in the command menu (Cmd+K) | -| `shortLabel` | Nu | Shorter label displayed on the pinned quick-action button | -| `icon` | Nu | Icon name displayed next to the label (e.g. `'IconBolt'`, `'IconSend'`) | -| `isPinned` | Nu | When `true`, shows the command as a quick-action button in the top-right corner of the page | -| `availabilityType` | Nu | Controls where the command appears: `'GLOBAL'` (always available), `'RECORD_SELECTION'` (only when records are selected), or `'FALLBACK'` (shown when no other commands match) | -| `availabilityObjectUniversalIdentifier` | Nu | Restrict the command to pages of a specific object type (e.g. only on Company records) | -| `conditionalAvailabilityExpression` | Nu | A boolean expression to dynamically control whether the command is visible (see below) | +| Câmp | Obligatoriu | Descriere | +| --------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `universalIdentifier` | Da | ID unic stabil pentru comandă | +| `label` | Da | Etichetă completă afișată în meniul de comenzi (Cmd+K) | +| `shortLabel` | Nu | Etichetă mai scurtă afișată pe butonul de acțiune rapidă fixat | +| `icon` | Nu | Numele pictogramei afișat lângă etichetă (de ex. `'IconBolt'`, `'IconSend'`) | +| `isPinned` | Nu | Când este `true`, afișează comanda ca buton de acțiune rapidă în colțul din dreapta sus al paginii | +| `availabilityType` | Nu | Controlează unde apare comanda: `'GLOBAL'` (mereu disponibilă), `'RECORD_SELECTION'` (doar când sunt selectate înregistrări) sau `'FALLBACK'` (afișată când nicio altă comandă nu se potrivește) | +| `availabilityObjectUniversalIdentifier` | Nu | Restricționați comanda la paginile unui anumit tip de obiect (de ex., doar pe înregistrările Company) | +| `conditionalAvailabilityExpression` | Nu | O expresie booleană pentru a controla dinamic dacă comanda este vizibilă (vezi mai jos) | -#### Conditional availability expressions +#### Expresii de disponibilitate condițională -The `conditionalAvailabilityExpression` field lets you control when a command is visible based on the current page context. Import typed variables and operators from `twenty-sdk` to build expressions: +Câmpul `conditionalAvailabilityExpression` vă permite să controlați când este vizibilă o comandă în funcție de contextul paginii curente. Importați variabile tipizate și operatori din `twenty-sdk` pentru a construi expresii: ```tsx import { @@ -905,45 +905,45 @@ export default defineFrontComponent({ }); ``` -**Context variables** — these represent the current state of the page: +**Variabile de context** — acestea reprezintă starea curentă a paginii: -| Variabilă | Tip | Descriere | -| ------------------------------ | --------- | ---------------------------------------------------------------- | -| `pageType` | `string` | Current page type (e.g. `'RecordIndexPage'`, `'RecordShowPage'`) | -| `isInSidePanel` | `boolean` | Whether the component is rendered in a side panel | -| `numberOfSelectedRecords` | `number` | Number of currently selected records | -| `isSelectAll` | `boolean` | Whether "select all" is active | -| `selectedRecords` | `array` | The selected record objects | -| `favoriteRecordIds` | `array` | IDs of favorited records | -| `objectPermissions` | `object` | Permissions for the current object type | -| `targetObjectReadPermissions` | `object` | Read permissions for the target object | -| `targetObjectWritePermissions` | `object` | Write permissions for the target object | -| `featureFlags` | `object` | Active feature flags | -| `objectMetadataItem` | `object` | Metadata of the current object type | -| `hasAnySoftDeleteFilterOnView` | `boolean` | Whether the current view has a soft-delete filter | +| Variabilă | Tip | Descriere | +| ------------------------------ | --------- | ---------------------------------------------------------------------- | +| `pageType` | `string` | Tipul paginii curente (de ex. `'RecordIndexPage'`, `'RecordShowPage'`) | +| `isInSidePanel` | `boolean` | Dacă componenta este redată într-un panou lateral | +| `numberOfSelectedRecords` | `number` | Numărul de înregistrări selectate în prezent | +| `isSelectAll` | `boolean` | Dacă "select all" este activ | +| `selectedRecords` | `array` | Obiectele înregistrărilor selectate | +| `favoriteRecordIds` | `array` | ID-urile înregistrărilor marcate ca favorite | +| `objectPermissions` | `object` | Permisiuni pentru tipul de obiect curent | +| `targetObjectReadPermissions` | `object` | Permisiuni de citire pentru obiectul țintă | +| `targetObjectWritePermissions` | `object` | Permisiuni de scriere pentru obiectul țintă | +| `featureFlags` | `object` | Steaguri de caracteristici active | +| `objectMetadataItem` | `object` | Metadatele tipului de obiect curent | +| `hasAnySoftDeleteFilterOnView` | `boolean` | Dacă vizualizarea curentă are un filtru soft-delete | -**Operators** — combine variables into boolean expressions: +**Operatori** — combinați variabilele în expresii booleene: -| Operator | Descriere | -| ----------------------------------- | ----------------------------------------------------------------- | -| `isDefined(value)` | `true` if the value is not null/undefined | -| `isNonEmptyString(value)` | `true` if the value is a non-empty string | -| `includes(array, value)` | `true` if the array contains the value | -| `includesEvery(array, prop, value)` | `true` if every item's property includes the value | -| `every(array, prop)` | `true` if the property is truthy on every item | -| `everyDefined(array, prop)` | `true` if the property is defined on every item | -| `everyEquals(array, prop, value)` | `true` if the property equals the value on every item | -| `some(array, prop)` | `true` if the property is truthy on at least one item | -| `someDefined(array, prop)` | `true` if the property is defined on at least one item | -| `someEquals(array, prop, value)` | `true` if the property equals the value on at least one item | -| `someNonEmptyString(array, prop)` | `true` if the property is a non-empty string on at least one item | -| `none(array, prop)` | `true` if the property is falsy on every item | -| `noneDefined(array, prop)` | `true` if the property is undefined on every item | -| `noneEquals(array, prop, value)` | `true` if the property does not equal the value on any item | +| Operator | Descriere | +| ----------------------------------- | ----------------------------------------------------------------------- | +| `isDefined(value)` | `true` dacă valoarea nu este null/undefined | +| `isNonEmptyString(value)` | `true` dacă valoarea este un șir nevid | +| `includes(array, value)` | `true` dacă array-ul conține valoarea | +| `includesEvery(array, prop, value)` | `true` dacă proprietatea fiecărui element include valoarea | +| `every(array, prop)` | `true` dacă proprietatea este truthy pentru fiecare element | +| `everyDefined(array, prop)` | `true` dacă proprietatea este definită pentru fiecare element | +| `everyEquals(array, prop, value)` | `true` dacă proprietatea este egală cu valoarea pentru fiecare element | +| `some(array, prop)` | `true` dacă proprietatea este truthy pe cel puțin un element | +| `someDefined(array, prop)` | `true` dacă proprietatea este definită pe cel puțin un element | +| `someEquals(array, prop, value)` | `true` dacă proprietatea este egală cu valoarea pe cel puțin un element | +| `someNonEmptyString(array, prop)` | `true` dacă proprietatea este un șir nevid pe cel puțin un element | +| `none(array, prop)` | `true` dacă proprietatea este falsy pentru fiecare element | +| `noneDefined(array, prop)` | `true` dacă proprietatea este nedefinită pentru fiecare element | +| `noneEquals(array, prop, value)` | `true` dacă proprietatea nu este egală cu valoarea pe niciun element | -#### Public assets +#### Resurse publice -Front components can access files from the app's `public/` directory using `getPublicAssetUrl`: +Componentele front-end pot accesa fișiere din directorul `public/` al aplicației folosind `getPublicAssetUrl`: ```tsx import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk'; @@ -957,18 +957,18 @@ export default defineFrontComponent({ }); ``` -See the [public assets section](#accessing-public-assets-with-getpublicasseturl) for details. +Consultați [secțiunea despre resurse publice](#accessing-public-assets-with-getpublicasseturl) pentru detalii. #### Stilizare -Front components support multiple styling approaches. You can use: +Componentele front-end acceptă mai multe abordări de stilizare. Puteți folosi: -* **Inline styles** — `style={{ color: 'red' }}` -* **Twenty UI components** — import from `twenty-sdk/ui` (Button, Tag, Status, Chip, Avatar, and more) -* **Emotion** — CSS-in-JS with `@emotion/react` -* **Styled-components** — `styled.div` patterns -* **Tailwind CSS** — utility classes -* **Any CSS-in-JS library** compatible with React +* **Stiluri inline** — `style={{ color: 'red' }}` +* **Componente Twenty UI** — import din `twenty-sdk/ui` (Button, Tag, Status, Chip, Avatar și altele) +* **Emotion** — CSS-in-JS cu `@emotion/react` +* **Styled-components** — pattern-uri `styled.div` +* **Tailwind CSS** — clase utilitare +* **Orice bibliotecă CSS-in-JS** compatibilă cu React ```tsx import { defineFrontComponent } from 'twenty-sdk'; @@ -1022,9 +1022,9 @@ Puncte cheie: * `description` (opțional) oferă context suplimentar despre scopul abilității.
- + -Agents are AI assistants that live inside your workspace. Use `defineAgent()` to create agents with a custom system prompt: +Agenții sunt asistenți AI care există în interiorul spațiului dvs. de lucru. Utilizați `defineAgent()` pentru a crea agenți cu un prompt de sistem personalizat: ```ts src/agents/example-agent.ts import { defineAgent } from 'twenty-sdk'; @@ -1040,17 +1040,17 @@ export default defineAgent({ ``` Puncte cheie: -* `name` is the unique identifier string for the agent (kebab-case recommended). -* `label` is the display name shown in the UI. -* `prompt` is the system prompt that defines the agent's behavior. -* `description` (optional) provides context about what the agent does. +* `name` este un șir identificator unic pentru agent (se recomandă kebab-case). +* `label` este numele de afișare din interfața cu utilizatorul (UI). +* `prompt` conține promptul de sistem — acesta este textul de instrucțiuni care definește comportamentul agentului. +* `description` (opțional) oferă context suplimentar despre scopul agentului. * `icon` (opțional) setează pictograma afișată în UI. -* `modelId` (optional) overrides the default AI model used by the agent. +* `modelId` (opțional) suprascrie modelul AI implicit utilizat de agent. -Views are saved configurations for how records of an object are displayed — including which fields are visible, their order, and any filters or groups applied. Use `defineView()` to ship pre-configured views with your app: +Vizualizările sunt configurații salvate despre cum sunt afișate înregistrările unui obiect — inclusiv ce câmpuri sunt vizibile, ordinea lor și orice filtre sau grupuri aplicate. Utilizați `defineView()` pentru a livra vizualizări preconfigurate împreună cu aplicația: ```ts src/views/example-view.ts import { defineView, ViewKey } from 'twenty-sdk'; @@ -1077,16 +1077,16 @@ export default defineView({ ``` Puncte cheie: -* `objectUniversalIdentifier` specifies which object this view applies to. -* `key` determines the view type (e.g., `ViewKey.INDEX` for the main list view). -* `fields` controls which columns appear and their order. Each field references a `fieldMetadataUniversalIdentifier`. -* You can also define `filters`, `filterGroups`, `groups`, and `fieldGroups` for more advanced configurations. -* `position` controls the ordering when multiple views exist for the same object. +* `objectUniversalIdentifier` specifică la ce obiect se aplică această vizualizare. +* `key` determină tipul vizualizării (de ex., `ViewKey.INDEX` pentru vizualizarea principală de listă). +* `fields` controlează ce coloane apar și ordinea acestora. Fiecare câmp face referire la un `fieldMetadataUniversalIdentifier`. +* Puteți defini, de asemenea, `filters`, `filterGroups`, `groups` și `fieldGroups` pentru configurații mai avansate. +* `position` controlează ordonarea atunci când există mai multe vizualizări pentru același obiect. -Navigation menu items add custom entries to the workspace sidebar. Use `defineNavigationMenuItem()` to link to views, external URLs, or objects: +Elementele de meniu de navigare adaugă intrări personalizate în bara laterală a spațiului de lucru. Utilizați `defineNavigationMenuItem()` pentru a lega la vizualizări, URL-uri externe sau obiecte: ```ts src/navigation-menu-items/example-navigation-menu-item.ts import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk'; @@ -1104,15 +1104,15 @@ export default defineNavigationMenuItem({ ``` Puncte cheie: -* `type` determines what the menu item links to: `NavigationMenuItemType.VIEW` for a saved view, or `NavigationMenuItemType.LINK` for an external URL. -* For view links, set `viewUniversalIdentifier`. For external links, set `link`. -* `position` controls the ordering in the sidebar. -* `icon` and `color` (optional) customize the appearance. +* `type` determină la ce face trimitere elementul de meniu: `NavigationMenuItemType.VIEW` pentru o vizualizare salvată sau `NavigationMenuItemType.LINK` pentru un URL extern. +* Pentru link-uri către vizualizări, setați `viewUniversalIdentifier`. Pentru link-uri externe, setați `link`. +* `position` controlează ordonarea în bara laterală. +* `icon` și `color` (opțional) personalizează aspectul. - + -Page layouts let you customize how a record detail page looks — which tabs appear, what widgets are inside each tab, and how they are arranged. Use `definePageLayout()` to ship custom layouts with your app: +Machetele de pagină vă permit să personalizați aspectul unei pagini de detalii a unei înregistrări — ce file apar, ce widgeturi sunt în fiecare filă și cum sunt aranjate. Utilizați `definePageLayout()` pentru a livra machete personalizate împreună cu aplicația: ```ts src/page-layouts/example-record-page-layout.ts import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk'; @@ -1149,33 +1149,33 @@ export default definePageLayout({ ``` Puncte cheie: -* `type` is typically `'RECORD_PAGE'` to customize the detail view of a specific object. -* `objectUniversalIdentifier` specifies which object this layout applies to. -* Each `tab` defines a section of the page with a `title`, `position`, and `layoutMode` (`CANVAS` for free-form layout). -* Each `widget` inside a tab can render a front component, a relation list, or other built-in widget types. -* `position` on tabs controls their order. Use higher values (e.g., 50) to place custom tabs after built-in ones. +* `type` este de obicei `'RECORD_PAGE'` pentru a personaliza vizualizarea de detaliu a unui obiect specific. +* `objectUniversalIdentifier` specifică la ce obiect se aplică această machetă. +* Fiecare `tab` definește o secțiune a paginii cu un `title`, `position` și `layoutMode` (`CANVAS` pentru layout liber). +* Fiecare `widget` dintr-o filă poate reda o componentă frontend, o listă de relații sau alte tipuri de widgeturi integrate. +* `position` pe file le controlează ordinea. Folosiți valori mai mari (de ex., 50) pentru a plasa filele personalizate după cele integrate.
-## Public assets (`public/` folder) +## Resurse publice (folderul `public/`) -The `public/` folder at the root of your app holds static files — images, icons, fonts, or any other assets your app needs at runtime. These files are automatically included in builds, synced during dev mode, and uploaded to the server. +Folderul `public/` din rădăcina aplicației conține fișiere statice — imagini, pictograme, fonturi sau orice alte resurse de care are nevoie aplicația la rulare. Aceste fișiere sunt incluse automat în build-uri, sincronizate în timpul modului de dezvoltare și încărcate pe server. -Files placed in `public/` are: +Fișierele plasate în `public/` sunt: -* **Publicly accessible** — once synced to the server, assets are served at a public URL. No authentication is needed to access them. -* **Available in front components** — use asset URLs to display images, icons, or any media inside your React components. -* **Available in logic functions** — reference asset URLs in emails, API responses, or any server-side logic. -* **Used for marketplace metadata** — the `logoUrl` and `screenshots` fields in `defineApplication()` reference files from this folder (e.g., `public/logo.png`). These are displayed in the marketplace when your app is published. -* **Auto-synced in dev mode** — when you add, update, or delete a file in `public/`, it is synced to the server automatically. No restart needed. -* **Included in builds** — `yarn twenty build` bundles all public assets into the distribution output. +* **Accesibile public** — odată sincronizate pe server, resursele sunt servite la un URL public. Nu este necesară autentificarea pentru a le accesa. +* **Disponibile în componentele frontend** — folosiți URL-urile resurselor pentru a afișa imagini, pictograme sau orice media în componentele React. +* **Disponibile în funcțiile logice** — referiți URL-urile resurselor în e-mailuri, răspunsuri API sau orice logică pe server. +* **Utilizate pentru metadatele marketplace-ului** — câmpurile `logoUrl` și `screenshots` din `defineApplication()` fac referire la fișiere din acest folder (de ex., `public/logo.png`). Acestea sunt afișate în marketplace când aplicația este publicată. +* **Sincronizate automat în modul de dezvoltare** — când adăugați, actualizați sau ștergeți un fișier în `public/`, acesta este sincronizat automat cu serverul. Nu este nevoie de repornire. +* **Incluse în build-uri** — `yarn twenty build` împachetează toate resursele publice în outputul de distribuție. -### Accessing public assets with `getPublicAssetUrl` +### Accesarea resurselor publice cu `getPublicAssetUrl` -Use the `getPublicAssetUrl` helper from `twenty-sdk` to get the full URL of a file in your `public/` directory. It works in both **logic functions** and **front components**. +Utilizați helperul `getPublicAssetUrl` din `twenty-sdk` pentru a obține URL-ul complet al unui fișier din directorul `public/`. Funcționează atât în funcții logice, cât și în componente frontend. -**In a logic function:** +**Într-o funcție logică:** ```ts src/logic-functions/send-invoice.ts import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk'; @@ -1200,7 +1200,7 @@ export default defineLogicFunction({ }); ``` -**In a front component:** +**Într-o componentă frontend:** ```tsx src/front-components/company-card.tsx import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk'; @@ -1212,19 +1212,19 @@ export default defineFrontComponent(() => { }); ``` -The `path` argument is relative to your app's `public/` folder. Both `getPublicAssetUrl('logo.png')` and `getPublicAssetUrl('public/logo.png')` resolve to the same URL — the `public/` prefix is stripped automatically if present. +Argumentul `path` este relativ la folderul `public/` al aplicației. Atât `getPublicAssetUrl('logo.png')`, cât și `getPublicAssetUrl('public/logo.png')` se rezolvă la același URL — prefixul `public/` este eliminat automat dacă este prezent. -## Using npm packages +## Utilizarea pachetelor npm -You can install and use any npm package in your app. Both logic functions and front components are bundled with [esbuild](https://esbuild.github.io/), which inlines all dependencies into the output — no `node_modules` are needed at runtime. +Puteți instala și utiliza orice pachet npm în aplicația dvs. Atât funcțiile logice, cât și componentele frontend sunt împachetate cu [esbuild](https://esbuild.github.io/), care integrează toate dependențele în output — nu sunt necesare `node_modules` la rulare. -### Installing a package +### Instalarea unui pachet ```bash filename="Terminal" yarn add axios ``` -Then import it in your code: +Apoi importați-l în codul dvs.: ```ts src/logic-functions/fetch-data.ts import { defineLogicFunction } from 'twenty-sdk'; @@ -1245,7 +1245,7 @@ export default defineLogicFunction({ }); ``` -The same works for front components: +Același lucru funcționează și pentru componentele frontend: ```tsx src/front-components/chart.tsx import { defineFrontComponent } from 'twenty-sdk'; @@ -1262,27 +1262,27 @@ export default defineFrontComponent({ }); ``` -### How bundling works +### Cum funcționează împachetarea -The build step (`yarn twenty dev` or `yarn twenty build`) uses esbuild to produce a single self-contained file per logic function and per front component. All imported packages are inlined into the bundle. +Pasul de build (`yarn twenty dev` sau `yarn twenty build`) folosește esbuild pentru a produce un singur fișier autonom per funcție logică și per componentă frontend. Toate pachetele importate sunt integrate în bundle. -**Logic functions** run in a Node.js environment. Node built-in modules (`fs`, `path`, `crypto`, `http`, etc.) are available and do not need to be installed. +**Funcțiile logice** rulează într-un mediu Node.js. Modulele built-in Node (`fs`, `path`, `crypto`, `http` etc.) sunt disponibile și nu trebuie instalate. -**Front components** run in a Web Worker. Node built-in modules are **not** available — only browser APIs and npm packages that work in a browser environment. +**Componentele frontend** rulează într-un Web Worker. Modulele built-in Node nu sunt disponibile — doar API-urile de browser și pachetele npm care funcționează într-un mediu de browser. -Both environments have `twenty-client-sdk/core` and `twenty-client-sdk/metadata` available as pre-provided modules — these are not bundled but resolved at runtime by the server. +Ambele medii au `twenty-client-sdk/core` și `twenty-client-sdk/metadata` disponibile ca module pre-furnizate — acestea nu sunt incluse în bundle, ci sunt rezolvate la rulare de către server. -## Scaffolding entities with `yarn twenty add` +## Generarea scheletului entităților cu `yarn twenty add` -Instead of creating entity files by hand, you can use the interactive scaffolder: +În loc să creați manual fișiere de entități, puteți folosi generatorul interactiv (scaffolder): ```bash filename="Terminal" yarn twenty add ``` -This prompts you to pick an entity type and walks you through the required fields. It generates a ready-to-use file with a stable `universalIdentifier` and the correct `defineEntity()` call. +Acesta vă solicită să alegeți un tip de entitate și vă ghidează prin câmpurile necesare. Generează un fișier gata de utilizare, cu un `universalIdentifier` stabil și apelul corect `defineEntity()`. -You can also pass the entity type directly to skip the first prompt: +Puteți de asemenea să transmiteți direct tipul de entitate pentru a sări peste primul prompt: ```bash filename="Terminal" yarn twenty add object @@ -1290,44 +1290,44 @@ yarn twenty add logicFunction yarn twenty add frontComponent ``` -### Available entity types +### Tipuri de entități disponibile -| Tipul entității | Comandă | Generated file | -| -------------------- | ------------------------------------ | ------------------------------------- | -| Obiect | `yarn twenty add object` | `src/objects/.ts` | -| Câmp | `yarn twenty add field` | `src/fields/.ts` | -| Logic function | `yarn twenty add logicFunction` | `src/logic-functions/.ts` | -| Front component | `yarn twenty add frontComponent` | `src/front-components/.tsx` | -| Rol | `yarn twenty add role` | `src/roles/.ts` | -| Abilitate | `yarn twenty add skill` | `src/skills/.ts` | -| Agent | `yarn twenty add agent` | `src/agents/.ts` | -| Vizualizare | `yarn twenty add view` | `src/views/.ts` | -| Navigation menu item | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/.ts` | -| Page layout | `yarn twenty add pageLayout` | `src/page-layouts/.ts` | +| Tipul entității | Comandă | Fișier generat | +| ---------------------------- | ------------------------------------ | ------------------------------------- | +| Obiect | `yarn twenty add object` | `src/objects/.ts` | +| Câmp | `yarn twenty add field` | `src/fields/.ts` | +| Funcție logică | `yarn twenty add logicFunction` | `src/logic-functions/.ts` | +| Componentă frontend | `yarn twenty add frontComponent` | `src/front-components/.tsx` | +| Rol | `yarn twenty add role` | `src/roles/.ts` | +| Abilitate | `yarn twenty add skill` | `src/skills/.ts` | +| Agent | `yarn twenty add agent` | `src/agents/.ts` | +| Vizualizare | `yarn twenty add view` | `src/views/.ts` | +| Element de meniu de navigare | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/.ts` | +| Machetă de pagină | `yarn twenty add pageLayout` | `src/page-layouts/.ts` | -### What the scaffolder generates +### Ce generează scaffolder-ul -Each entity type has its own template. For example, `yarn twenty add object` asks for: +Fiecare tip de entitate are propriul său șablon. De exemplu, `yarn twenty add object` solicită: -1. **Name (singular)** — e.g., `invoice` -2. **Name (plural)** — e.g., `invoices` -3. **Label (singular)** — auto-populated from the name (e.g., `Invoice`) -4. **Label (plural)** — auto-populated (e.g., `Invoices`) -5. **Create a view and navigation item?** — if you answer yes, the scaffolder also generates a matching view and sidebar link for the new object. +1. **Nume (singular)** — de ex., `invoice` +2. **Nume (plural)** — de ex., `invoices` +3. **Etichetă (singular)** — completată automat din nume (de ex., `Invoice`) +4. **Etichetă (plural)** — completată automat (de ex., `Invoices`) +5. **Creați o vizualizare și un element de navigare?** — dacă răspundeți afirmativ, scaffolder-ul generează, de asemenea, o vizualizare corespunzătoare și un link în bara laterală pentru noul obiect. -Other entity types have simpler prompts — most only ask for a name. +Alte tipuri de entități au prompturi mai simple — majoritatea cer doar un nume. -The `field` entity type is more detailed: it asks for the field name, label, type (from a list of all available field types like `TEXT`, `NUMBER`, `SELECT`, `RELATION`, etc.), and the target object's `universalIdentifier`. +Tipul de entitate `field` este mai detaliat: solicită numele câmpului, eticheta, tipul (dintr-o listă cu toate tipurile de câmp disponibile precum `TEXT`, `NUMBER`, `SELECT`, `RELATION` etc.) și `universalIdentifier` al obiectului țintă. -### Custom output path +### Cale de output personalizată -Use the `--path` flag to place the generated file in a custom location: +Utilizați opțiunea `--path` pentru a plasa fișierul generat într-o locație personalizată: ```bash filename="Terminal" yarn twenty add logicFunction --path src/custom-folder ``` -## Typed API clients (twenty-client-sdk) +## Clienți API tipizați (twenty-client-sdk) Pachetul `twenty-client-sdk` oferă doi clienți GraphQL tipați pentru a interacționa cu API-ul Twenty din funcțiile de logică și componentele Front. @@ -1337,9 +1337,9 @@ Pachetul `twenty-client-sdk` oferă doi clienți GraphQL tipați pentru a intera | `MetadataApiClient` | `twenty-client-sdk/metadata` | `/metadata` — configurarea spațiului de lucru, încărcări de fișiere | Nu, este livrat preconstruit | - + -`CoreApiClient` este clientul principal pentru interogarea și modificarea datelor din spațiul de lucru. It is **generated from your workspace schema** during `yarn twenty dev` or `yarn twenty build`, so it is fully typed to match your objects and fields. +`CoreApiClient` este clientul principal pentru interogarea și modificarea datelor din spațiul de lucru. Este generat din schema spațiului de lucru în timpul `yarn twenty dev` sau `yarn twenty build`, astfel încât este complet tipizat pentru a corespunde obiectelor și câmpurilor dvs. ```ts import { CoreApiClient } from 'twenty-client-sdk/core'; @@ -1379,12 +1379,12 @@ const { createCompany } = await client.mutation({ Clientul folosește o sintaxă de tip selection-set: transmiteți `true` pentru a include un câmp, folosiți `__args` pentru argumente și imbricați obiecte pentru relații. Obțineți autocompletare și verificare a tipurilor complete, pe baza schemei spațiului dvs. de lucru. -**CoreApiClient is generated at dev/build time.** If you use it without running `yarn twenty dev` or `yarn twenty build` first, it throws an error. The generation happens automatically — the CLI introspects your workspace's GraphQL schema and generates a typed client using `@genql/cli`. +**CoreApiClient este generat în timpul dev/build.** Dacă îl utilizați fără a rula mai întâi `yarn twenty dev` sau `yarn twenty build`, va arunca o eroare. Generarea are loc automat — CLI inspectează schema GraphQL a spațiului dvs. de lucru și generează un client tipizat folosind `@genql/cli`. #### Folosirea CoreSchema pentru adnotări de tip -`CoreSchema` provides TypeScript types matching your workspace objects — useful for typing component state or function parameters: +`CoreSchema` oferă tipuri TypeScript care corespund obiectelor din spațiul dvs. de lucru — utile pentru tiparea stării componentelor sau a parametrilor funcțiilor: ```ts import { CoreApiClient, CoreSchema } from 'twenty-client-sdk/core'; @@ -1406,7 +1406,7 @@ setCompany(result.company); ``` - + `MetadataApiClient` este livrat preconstruit împreună cu SDK-ul (nu este necesară generarea). Interoghează endpointul `/metadata` pentru configurarea spațiului de lucru, aplicații și încărcări de fișiere. @@ -1462,7 +1462,7 @@ console.log(uploadedFile); | ---------------------------------- | -------- | ------------------------------------------------------------------ | | `fileBuffer` | `Buffer` | Conținutul brut al fișierului | | `filename` | `string` | Numele fișierului (folosit pentru stocare și afișare) | -| `contentType` | `string` | MIME type (defaults to `application/octet-stream` if omitted) | +| `contentType` | `string` | Tipul MIME (implicit `application/octet-stream` dacă este omis) | | `fieldMetadataUniversalIdentifier` | `string` | `universalIdentifier` al câmpului de tip fișier de pe obiectul tău | Puncte cheie: @@ -1476,24 +1476,24 @@ Puncte cheie: Când codul dvs. rulează pe Twenty (funcții de logică sau componente Front), platforma injectează acreditările ca variabile de mediu: * `TWENTY_API_URL` — URL-ul de bază al API-ului Twenty - * `TWENTY_APP_ACCESS_TOKEN` — Short-lived key scoped to your application's default function role + * `TWENTY_APP_ACCESS_TOKEN` — Cheie cu durată scurtă, limitată la rolul implicit de funcție al aplicației Nu trebuie să le transmiteți clienților — aceștia citesc automat din `process.env`. Permisiunile cheii API sunt determinate de rolul referențiat în `defaultRoleUniversalIdentifier` din `application-config.ts`. -## Testing your app +## Testarea aplicației -The SDK provides programmatic APIs that let you build, deploy, install, and uninstall your app from test code. Combined with [Vitest](https://vitest.dev/) and the typed API clients, you can write integration tests that verify your app works end-to-end against a real Twenty server. +SDK-ul oferă API-uri programatice care vă permit să construiți, să distribuiți, să instalați și să dezinstalați aplicația din codul de test. Combinat cu [Vitest](https://vitest.dev/) și clienții API tipizați, puteți scrie teste de integrare care verifică faptul că aplicația funcționează cap-coadă împotriva unui server Twenty real. ### Configurare -The scaffolded app already includes Vitest. If you set it up manually, install the dependencies: +Aplicația generată (scaffolded) include deja Vitest. Dacă o configurați manual, instalați dependențele: ```bash filename="Terminal" yarn add -D vitest vite-tsconfig-paths ``` -Create a `vitest.config.ts` at the root of your app: +Creați un `vitest.config.ts` în rădăcina aplicației: ```ts vitest.config.ts import tsconfigPaths from 'vite-tsconfig-paths'; @@ -1519,7 +1519,7 @@ export default defineConfig({ }); ``` -Create a setup file that verifies the server is reachable before tests run: +Creați un fișier de configurare care verifică faptul că serverul este accesibil înainte de rularea testelor: ```ts src/__tests__/setup-test.ts import * as fs from 'fs'; @@ -1559,22 +1559,22 @@ beforeAll(async () => { }); ``` -### Programmatic SDK APIs +### API-uri SDK programatice -The `twenty-sdk/cli` subpath exports functions you can call directly from test code: +Subruta `twenty-sdk/cli` exportă funcții pe care le puteți apela direct din codul de test: -| Funcție | Descriere | -| -------------- | ------------------------------------------- | -| `appBuild` | Build the app and optionally pack a tarball | -| `appDeploy` | Upload a tarball to the server | -| `appInstall` | Install the app on the active workspace | -| `appUninstall` | Uninstall the app from the active workspace | +| Funcție | Descriere | +| -------------- | --------------------------------------------------------- | +| `appBuild` | Construiți aplicația și, opțional, împachetați un tarball | +| `appDeploy` | Încărcați un tarball pe server | +| `appInstall` | Instalați aplicația în spațiul de lucru activ | +| `appUninstall` | Dezinstalați aplicația din spațiul de lucru activ | -Each function returns a result object with `success: boolean` and either `data` or `error`. +Fiecare funcție returnează un obiect rezultat cu `success: boolean` și fie `data`, fie `error`. -### Writing an integration test +### Scrierea unui test de integrare -Here is a full example that builds, deploys, and installs the app, then verifies it appears in the workspace: +Iată un exemplu complet care construiește, distribuie și instalează aplicația, apoi verifică faptul că aceasta apare în spațiul de lucru: ```ts src/__tests__/app-install.integration-test.ts import { APPLICATION_UNIVERSAL_IDENTIFIER } from 'src/application-config'; @@ -1637,37 +1637,37 @@ describe('App installation', () => { }); ``` -### Running tests +### Rularea testelor -Make sure your local Twenty server is running, then: +Asigurați-vă că serverul Twenty local rulează, apoi: ```bash filename="Terminal" yarn test ``` -Or in watch mode during development: +Sau în modul watch în timpul dezvoltării: ```bash filename="Terminal" yarn test:watch ``` -### Type checking +### Verificarea tipurilor -You can also run type checking on your app without running tests: +Puteți rula și verificarea tipurilor pe aplicație fără a rula testele: ```bash filename="Terminal" yarn twenty typecheck ``` -This runs `tsc --noEmit` and reports any type errors. +Aceasta rulează `tsc --noEmit` și raportează orice erori de tip. ## Referință CLI -Beyond `dev`, `build`, `add`, and `typecheck`, the CLI provides commands for executing functions, viewing logs, and managing app installations. +Dincolo de `dev`, `build`, `add` și `typecheck`, CLI oferă comenzi pentru executarea funcțiilor, vizualizarea jurnalelor și gestionarea instalărilor de aplicații. -### Executing functions (`yarn twenty exec`) +### Executarea funcțiilor (`yarn twenty exec`) -Run a logic function manually without triggering it via HTTP, cron, or database event: +Rulați manual o funcție logică fără a o declanșa prin HTTP, cron sau eveniment de bază de date: ```bash filename="Terminal" # Execute by function name @@ -1684,9 +1684,9 @@ yarn twenty exec --preInstall yarn twenty exec --postInstall ``` -### Viewing function logs (`yarn twenty logs`) +### Vizualizarea jurnalelor funcțiilor (`yarn twenty logs`) -Stream execution logs for your app's logic functions: +Transmiteți în flux jurnalele de execuție pentru funcțiile logice ale aplicației: ```bash filename="Terminal" # Stream all function logs @@ -1700,12 +1700,12 @@ yarn twenty logs -u e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf ``` -This is different from `yarn twenty server logs`, which shows the Docker container logs. `yarn twenty logs` shows your app's function execution logs from the Twenty server. +Acest lucru este diferit de `yarn twenty server logs`, care afișează jurnalele containerului Docker. `yarn twenty logs` afișează jurnalele de execuție ale funcțiilor aplicației de pe serverul Twenty. -### Uninstalling an app (`yarn twenty uninstall`) +### Dezinstalarea unei aplicații (`yarn twenty uninstall`) -Remove your app from the active workspace: +Eliminați aplicația din spațiul de lucru activ: ```bash filename="Terminal" yarn twenty uninstall