i18n - docs translations (#19119)

Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
This commit is contained in:
github-actions[bot]
2026-03-30 14:39:38 +02:00
committed by GitHub
parent cb85a1b5a3
commit 107914b437
4 changed files with 388 additions and 388 deletions
@@ -15,21 +15,21 @@ Il pacchetto twenty-sdk fornisce blocchi tipizzati e funzioni helper da usare ne
L'SDK fornisce funzioni helper per definire le entità della tua app. Come descritto in [Rilevamento delle entità](/l/it/developers/extend/apps/getting-started#entity-detection), devi usare `export default define<Entity>({...})` affinché le tue entità vengano rilevate:
| Funzione | Scopo |
| -------------------------------- | ----------------------------------------------------------------------------------- |
| `defineApplication` | Configura i metadati dell'applicazione (obbligatorio, uno per app) |
| `defineObject` | Definisci oggetti personalizzati con campi |
| `defineField` | Extend existing objects with additional fields or define standalone relation fields |
| `defineLogicFunction` | Definisci funzioni logiche con handler |
| `definePreInstallLogicFunction` | Definisci una funzione logica di pre-installazione (una per app) |
| `definePostInstallLogicFunction` | Definisci una funzione logica di post-installazione (una per app) |
| `defineFrontComponent` | Definisci componenti front-end per un'interfaccia utente personalizzata |
| `defineRole` | Configura i permessi dei ruoli e l'accesso agli oggetti |
| `defineView` | Definisci viste salvate per gli oggetti |
| `defineNavigationMenuItem` | Definisci i link di navigazione della barra laterale |
| `defineSkill` | Definisci le competenze dell'agente IA |
| `defineAgent` | Define AI agents |
| `definePageLayout` | Define custom page layouts |
| Funzione | Scopo |
| -------------------------------- | ----------------------------------------------------------------------------------------------- |
| `defineApplication` | Configura i metadati dell'applicazione (obbligatorio, uno per app) |
| `defineObject` | Definisci oggetti personalizzati con campi |
| `defineField` | Estendi gli oggetti esistenti con campi aggiuntivi oppure definisci campi di relazione autonomi |
| `defineLogicFunction` | Definisci funzioni logiche con handler |
| `definePreInstallLogicFunction` | Definisci una funzione logica di pre-installazione (una per app) |
| `definePostInstallLogicFunction` | Definisci una funzione logica di post-installazione (una per app) |
| `defineFrontComponent` | Definisci componenti front-end per un'interfaccia utente personalizzata |
| `defineRole` | Configura i permessi dei ruoli e l'accesso agli oggetti |
| `defineView` | Definisci viste salvate per gli oggetti |
| `defineNavigationMenuItem` | Definisci i link di navigazione della barra laterale |
| `defineSkill` | Definisci le competenze dell'agente IA |
| `defineAgent` | Definisci gli agenti IA |
| `definePageLayout` | Definisci layout di pagina personalizzati |
Queste funzioni convalidano la configurazione in fase di build e offrono il completamento automatico nell'IDE e la sicurezza dei tipi.
@@ -112,7 +112,7 @@ Punti chiave:
* Il `universalIdentifier` deve essere univoco e stabile tra i deployment.
* Ogni campo richiede un `name`, `type`, `label` e il proprio `universalIdentifier` stabile.
* L'array `fields` è facoltativo: puoi definire oggetti senza campi personalizzati.
* You can scaffold new objects using `yarn twenty add`, which guides you through naming, fields, and relationships.
* Puoi generare nuovi oggetti con `yarn twenty add`, che ti guida nella denominazione, nei campi e nelle relazioni.
<Note>
**I campi base vengono creati automaticamente.** Quando definisci un oggetto personalizzato, Twenty aggiunge automaticamente i campi standard
@@ -124,7 +124,7 @@ ma non è consigliato.
### Definire campi sugli oggetti esistenti
Use `defineField()` to add fields to objects you don't own — such as standard Twenty objects (Person, Company, etc.) or objects from other apps. Unlike inline fields in `defineObject()`, standalone fields require an `objectUniversalIdentifier` to specify which object they extend:
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:
```typescript
// src/fields/company-loyalty-tier.field.ts
@@ -147,35 +147,35 @@ export default defineField({
Punti chiave:
* `objectUniversalIdentifier` identifies the target object. For standard objects, use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` exported from `twenty-sdk`.
* When defining fields inline in `defineObject()`, you do **not** need `objectUniversalIdentifier` — it's inherited from the parent object.
* `defineField()` is the only way to add fields to objects you didn't create with `defineObject()`.
* `objectUniversalIdentifier` identifica l'oggetto di destinazione. Per gli oggetti standard, usa `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` esportati da `twenty-sdk`.
* Quando definisci campi inline in `defineObject()`, **non** hai bisogno di `objectUniversalIdentifier` — viene ereditato dall'oggetto padre.
* `defineField()` è l'unico modo per aggiungere campi a oggetti che non hai creato con `defineObject()`.
### Relazioni
Relations connect objects together. In Twenty, relations are always **bidirectional** — you define both sides, and each side references the other.
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.
There are two relation types:
Esistono due tipi di relazione:
| Tipo di relazione | Descrizione | Has foreign key? |
| ----------------- | ------------------------------------------------------------- | ---------------------- |
| `MANY_TO_ONE` | Many records of this object point to one record of the target | Yes (`joinColumnName`) |
| `ONE_TO_MANY` | One record of this object has many records of the target | No (inverse side) |
| Tipo di relazione | Descrizione | Ha una chiave esterna? |
| ----------------- | --------------------------------------------------------------------- | ---------------------- |
| `MANY_TO_ONE` | Molti record di questo oggetto puntano a un record della destinazione | Sì (`joinColumnName`) |
| `ONE_TO_MANY` | Un record di questo oggetto ha molti record della destinazione | No (lato inverso) |
#### How relations work
#### Come funzionano le relazioni
Every relation requires **two fields** that reference each other:
Ogni relazione richiede **due campi** che fanno riferimento l'uno all'altro:
1. The **MANY_TO_ONE** side — lives on the object that holds the foreign key
2. The **ONE_TO_MANY** side — lives on the object that owns the collection
1. Il lato **MANY_TO_ONE** — risiede sull'oggetto che detiene la chiave esterna
2. Il lato **ONE_TO_MANY** — risiede sull'oggetto che possiede la collezione
Both fields use `FieldType.RELATION` and cross-reference each other via `relationTargetFieldMetadataUniversalIdentifier`.
Entrambi i campi usano `FieldType.RELATION` e si riferiscono reciprocamente tramite `relationTargetFieldMetadataUniversalIdentifier`.
#### Example: Post Card has many Recipients
#### Esempio: Post Card ha molti destinatari
Suppose a `PostCard` can be sent to many `PostCardRecipient` records. Each recipient belongs to exactly one post card.
Supponiamo che un `PostCard` possa essere inviato a molti record `PostCardRecipient`. Ogni destinatario appartiene esattamente a una sola cartolina.
**Step 1: Define the ONE_TO_MANY side on PostCard** (the "one" side):
**Passaggio 1: definisci il lato ONE_TO_MANY su PostCard** (il lato "uno"):
```typescript
// src/fields/post-card-recipients-on-post-card.field.ts
@@ -203,7 +203,7 @@ export default defineField({
});
```
**Step 2: Define the MANY_TO_ONE side on PostCardRecipient** (the "many" side — holds the foreign key):
**Passaggio 2: definisci il lato MANY_TO_ONE su PostCardRecipient** (il lato "molti" — contiene la chiave esterna):
```typescript
// src/fields/post-card-on-post-card-recipient.field.ts
@@ -234,12 +234,12 @@ export default defineField({
```
<Note>
**Circular imports:** Both relation fields reference each other's `universalIdentifier`. To avoid circular import issues, export your field IDs as named constants from each file, and import them in the other file. The build system resolves these at compile time.
**Importazioni circolari:** Entrambi i campi di relazione fanno riferimento all'`universalIdentifier` dell'altro. Per evitare problemi di importazioni circolari, esporta gli ID dei campi come costanti denominate da ciascun file e importale nell'altro file. Il sistema di build le risolve in fase di compilazione.
</Note>
#### Relating to standard objects
#### Relazioni con gli oggetti standard
To create a relation with a built-in Twenty object (Person, Company, etc.), use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS`:
Per creare una relazione con un oggetto Twenty integrato (Person, Company, ecc.), usa `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS`:
```typescript
// src/fields/person-on-self-hosting-user.field.ts
@@ -274,20 +274,20 @@ export default defineField({
});
```
#### Relation field properties
#### Proprietà dei campi di relazione
| Proprietà | Obbligatorio | Descrizione |
| ------------------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------- |
| `tipo` | Sì | Must be `FieldType.RELATION` |
| `relationTargetObjectMetadataUniversalIdentifier` | Sì | The `universalIdentifier` of the target object |
| `relationTargetFieldMetadataUniversalIdentifier` | Sì | The `universalIdentifier` of the matching field on the target object |
| `universalSettings.relationType` | Sì | `RelationType.MANY_TO_ONE` or `RelationType.ONE_TO_MANY` |
| `universalSettings.onDelete` | MANY_TO_ONE only | What happens when the referenced record is deleted: `CASCADE`, `SET_NULL`, `RESTRICT`, or `NO_ACTION` |
| `universalSettings.joinColumnName` | MANY_TO_ONE only | Database column name for the foreign key (e.g., `postCardId`) |
| Proprietà | Obbligatorio | Descrizione |
| ------------------------------------------------- | ---------------- | ---------------------------------------------------------------------------------------------------------- |
| `tipo` | Sì | Deve essere `FieldType.RELATION` |
| `relationTargetObjectMetadataUniversalIdentifier` | Sì | L'`universalIdentifier` dell'oggetto di destinazione |
| `relationTargetFieldMetadataUniversalIdentifier` | Sì | L'`universalIdentifier` del campo corrispondente sull'oggetto di destinazione |
| `universalSettings.relationType` | Sì | `RelationType.MANY_TO_ONE` or `RelationType.ONE_TO_MANY` |
| `universalSettings.onDelete` | Solo MANY_TO_ONE | Cosa accade quando il record referenziato viene eliminato: `CASCADE`, `SET_NULL`, `RESTRICT` o `NO_ACTION` |
| `universalSettings.joinColumnName` | Solo MANY_TO_ONE | Nome della colonna del database per la chiave esterna (ad es., `postCardId`) |
#### Inline relation fields in defineObject
#### Campi di relazione inline in defineObject
You can also define relation fields directly inside `defineObject()`. In that case, omit `objectUniversalIdentifier` — it's inherited from the parent object:
Puoi anche definire i campi di relazione direttamente all'interno di `defineObject()`. In tal caso, ometti `objectUniversalIdentifier` — viene ereditato dall'oggetto padre:
```typescript
export default defineObject({
@@ -354,21 +354,21 @@ Note:
* `defaultRoleUniversalIdentifier` deve corrispondere al file del ruolo (vedi sotto).
* Le funzioni di pre-installazione e post-installazione vengono rilevate automaticamente durante la build del manifesto. Vedi [Funzioni di pre-installazione](#pre-install-functions) e [Funzioni di post-installazione](#post-install-functions).
#### Marketplace metadata
#### Metadati del marketplace
If you plan to [publish your app](/l/it/developers/extend/apps/publishing), these optional fields control how your app appears in the marketplace:
Se prevedi di [pubblicare la tua app](/l/it/developers/extend/apps/publishing), questi campi opzionali controllano come la tua app appare nel marketplace:
| Campo | Descrizione |
| ------------------ | --------------------------------------------------- |
| `autore` | Author or company name |
| `categoria` | App category for marketplace filtering |
| `logoUrl` | Path to your app logo (relative to `./assets/`) |
| `screenshots` | Array of screenshot paths (relative to `./assets/`) |
| `aboutDescription` | Longer markdown description for the "About" tab |
| `websiteUrl` | Link to your website |
| `termsUrl` | Link to terms of service |
| `emailSupport` | Support email address |
| `issueReportUrl` | Link to issue tracker |
| Campo | Descrizione |
| ------------------ | ----------------------------------------------------------- |
| `autore` | Nome dell'autore o dell'azienda |
| `categoria` | Categoria dell'app per il filtraggio nel marketplace |
| `logoUrl` | Percorso del logo della tua app (relativo a `./assets/`) |
| `screenshots` | Array di percorsi degli screenshot (relativi a `./assets/`) |
| `aboutDescription` | Descrizione markdown più lunga per la scheda "Informazioni" |
| `websiteUrl` | Link al tuo sito web |
| `termsUrl` | Link ai Termini di servizio |
| `emailSupport` | Indirizzo email di supporto |
| `issueReportUrl` | Link al sistema di tracciamento dei problemi |
#### Ruoli e permessi
@@ -376,7 +376,7 @@ Le applicazioni possono definire ruoli che incapsulano i permessi sugli oggetti
* La chiave API di runtime iniettata come `TWENTY_API_KEY` è derivata da questo ruolo funzione predefinito.
* Il client tipizzato sarà limitato ai permessi concessi a quel ruolo.
* Follow least-privilege: create a dedicated role with only the permissions your functions need, then reference its universal identifier.
* Segui il principio del privilegio minimo: crea un ruolo dedicato con solo i permessi necessari alle tue funzioni, quindi fai riferimento al suo identificatore universale.
##### Ruolo funzione predefinito (*.role.ts)
@@ -429,7 +429,7 @@ L'`universalIdentifier` di questo ruolo viene quindi referenziato in `applicatio
Note:
* Start from the scaffolded role, then progressively restrict it following least-privilege.
* Parti dal ruolo generato dallo scaffolder, quindi restringilo progressivamente seguendo il principio del privilegio minimo.
* Sostituisci `objectPermissions` e `fieldPermissions` con gli oggetti/campi di cui le tue funzioni hanno bisogno.
* `permissionFlags` controllano l'accesso alle funzionalità a livello di piattaforma. Mantienili al minimo; aggiungi solo ciò che ti serve.
* Vedi un esempio funzionante nell'app Hello World: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
@@ -543,7 +543,7 @@ Punti chiave:
* È consentita una sola funzione di pre-installazione per applicazione. La build del manifesto genererà un errore se ne viene rilevata più di una.
* L'`universalIdentifier` della funzione viene impostato automaticamente come `preInstallLogicFunctionUniversalIdentifier` nel manifesto dell'applicazione durante la build — non è necessario farvi riferimento in `defineApplication()`.
* Il timeout predefinito è impostato a 300 secondi (5 minuti) per consentire attività di preparazione più lunghe.
* Pre-install functions do not need triggersthey are invoked by the platform before installation or manually via `exec --preInstall`.
* Le funzioni di pre-installazione non necessitano di trigger — vengono invocate dalla piattaforma prima dell'installazione o manualmente tramite `exec --preInstall`.
### Funzioni post-installazione
@@ -581,7 +581,7 @@ Punti chiave:
* È consentita una sola funzione di post-installazione per applicazione. La build del manifesto genererà un errore se ne viene rilevata più di una.
* L'`universalIdentifier` della funzione viene impostato automaticamente come `postInstallLogicFunctionUniversalIdentifier` nel manifesto dell'applicazione durante la build — non è necessario farvi riferimento in `defineApplication()`.
* Il timeout predefinito è impostato a 300 secondi (5 minuti) per consentire attività di configurazione più lunghe, come il popolamento dei dati.
* Post-install functions do not need triggersthey are invoked by the platform during installation or manually via `exec --postInstall`.
* Le funzioni di post-installazione non necessitano di trigger — vengono invocate dalla piattaforma durante l'installazione o manualmente tramite `exec --postInstall`.
### Payload del trigger di route
@@ -625,15 +625,15 @@ const handler = async (event: RoutePayload) => {
Il tipo `RoutePayload` ha la seguente struttura:
| Proprietà | Tipo | Descrizione |
| ---------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | Intestazioni HTTP (solo quelle elencate in `forwardedRequestHeaders`) |
| `queryStringParameters` | `Record<string, string \| undefined>` | Parametri della query string (valori multipli uniti da virgole) |
| `pathParameters` | `Record<string, string \| undefined>` | Path parameters extracted from the route pattern (e.g., `/users/:id` -> `{ id: '123' }`) |
| `body` | `object \| null` | Corpo della richiesta analizzato (JSON) |
| `isBase64Encoded` | `boolean` | Indica se il corpo è codificato in base64 |
| `requestContext.http.method` | `string` | Metodo HTTP (GET, POST, PUT, PATCH, DELETE) |
| `requestContext.http.path` | `string` | Percorso della richiesta non elaborato |
| Proprietà | Tipo | Descrizione |
| ---------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `headers` | `Record<string, string \| undefined>` | Intestazioni HTTP (solo quelle elencate in `forwardedRequestHeaders`) |
| `queryStringParameters` | `Record<string, string \| undefined>` | Parametri della query string (valori multipli uniti da virgole) |
| `pathParameters` | `Record<string, string \| undefined>` | Parametri di percorso estratti dal pattern della route (ad es., `/users/:id` -> `{ id: '123' }`) |
| `body` | `object \| null` | Corpo della richiesta analizzato (JSON) |
| `isBase64Encoded` | `boolean` | Indica se il corpo è codificato in base64 |
| `requestContext.http.method` | `string` | Metodo HTTP (GET, POST, PUT, PATCH, DELETE) |
| `requestContext.http.path` | `string` | Percorso della richiesta non elaborato |
### Inoltro delle intestazioni HTTP
@@ -675,7 +675,7 @@ const handler = async (event: RoutePayload) => {
Puoi creare nuove funzioni in due modi:
* **Scaffolded**: Run `yarn twenty add` and choose the option to add a new logic function. Questo genera un file iniziale con un handler e una configurazione.
* **Generata dallo scaffolder**: Esegui `yarn twenty add` e scegli l'opzione per aggiungere una nuova funzione logica. Questo genera un file iniziale con un handler e una configurazione.
* **Manuale**: Crea un nuovo file `*.logic-function.ts` e usa `defineLogicFunction()`, seguendo lo stesso schema.
### Contrassegnare una funzione logica come strumento
@@ -776,7 +776,7 @@ Punti chiave:
Puoi creare nuovi componenti front-end in due modi:
* **Scaffolded**: Run `yarn twenty add` and choose the option to add a new front component.
* **Generata dallo scaffolder**: Esegui `yarn twenty add` e scegli l'opzione per aggiungere un nuovo componente front-end.
* **Manuale**: Crea un nuovo file `.tsx` e usa `defineFrontComponent()`, seguendo lo stesso schema.
### Abilità
@@ -811,21 +811,21 @@ Punti chiave:
Puoi creare nuove skill in due modi:
* **Scaffolded**: Run `yarn twenty add` and choose the option to add a new skill.
* **Generata dallo scaffolder**: Esegui `yarn twenty add` e scegli l'opzione per aggiungere una nuova skill.
* **Manuale**: Crea un nuovo file e usa `defineSkill()`, seguendo lo stesso schema.
### Typed API clients (`twenty-client-sdk`)
### Client API tipizzati (`twenty-client-sdk`)
The `twenty-client-sdk` package provides two typed GraphQL clients for interacting with the Twenty API from your logic functions and front components:
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:
| Client | Importa | Endpoint | Generated? |
| ------------------- | ---------------------------- | ---------------------------------------------- | ---------------------- |
| `CoreApiClient` | `twenty-client-sdk/core` | `/graphql` — workspace data (records, objects) | Yes, at dev/build time |
| `MetadataApiClient` | `twenty-client-sdk/metadata` | `/metadata` — workspace config, file uploads | No, ships pre-built |
| Client | Importa | Endpoint | Generato? |
| ------------------- | ---------------------------- | ------------------------------------------------------------------------ | -------------------------- |
| `CoreApiClient` | `twenty-client-sdk/core` | `/graphql` — dati dello spazio di lavoro (record, oggetti) | Sì, in fase di dev/build |
| `MetadataApiClient` | `twenty-client-sdk/metadata` | `/metadata` — configurazione dello spazio di lavoro, caricamenti di file | No, fornito pronto all'uso |
#### CoreApiClient
`CoreApiClient` is the main client for querying and mutating workspace data. It is **generated from your workspace schema** during `yarn twenty dev` or `yarn twenty build`, so it's 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.
```typescript
import { CoreApiClient } from 'twenty-client-sdk/core';
@@ -859,15 +859,15 @@ const { createCompany } = await client.mutation({
});
```
The client uses a selection-set syntax: pass `true` to include a field, use `__args` for arguments, and nest objects for relations. You get full autocompletion and type checking based on your workspace schema.
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.
<Note>
**CoreApiClient is generated at dev/build time.** If you try to 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, generates a typed client using `@genql/cli`, writes the generated sources to `node_modules/twenty-client-sdk/dist/core/generated/`, and replaces the stubs in `node_modules/twenty-client-sdk/dist/core.mjs` and `node_modules/twenty-client-sdk/dist/core.cjs`.
**CoreApiClient viene generato in fase di dev/build.** Se provi a usarlo senza eseguire prima `yarn twenty dev` o `yarn twenty build`, genererà un errore. La generazione avviene automaticamente — la CLI esegue l'introspezione dello schema GraphQL del tuo spazio di lavoro, genera un client tipizzato usando `@genql/cli`, scrive le sorgenti generate in `node_modules/twenty-client-sdk/dist/core/generated/` e sostituisce gli stub in `node_modules/twenty-client-sdk/dist/core.mjs` e `node_modules/twenty-client-sdk/dist/core.cjs`.
</Note>
#### Using CoreSchema for type annotations
#### 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, utili per tipizzare lo stato dei componenti o i parametri delle funzioni:
```typescript
import { CoreApiClient, CoreSchema } from 'twenty-client-sdk/core';
@@ -890,7 +890,7 @@ setCompany(result.company);
#### MetadataApiClient
`MetadataApiClient` ships pre-built with the SDK (no generation required). It queries the `/metadata` endpoint for workspace configuration, applications, and file uploads:
`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:
```typescript
import { MetadataApiClient } from 'twenty-client-sdk/metadata';
@@ -912,18 +912,18 @@ const { findManyApplications } = await metadataClient.query({
});
```
#### Runtime credentials
#### Credenziali di runtime
When your code runs on Twenty (logic functions or front components), the platform injects credentials as environment variables:
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` — Base URL of the Twenty API
* `TWENTY_API_KEY` — Short-lived key scoped to your application's default function role
* `TWENTY_API_URL` — URL di base dell'API di Twenty
* `TWENTY_API_KEY` — Chiave a breve durata con ambito al ruolo funzione predefinito della tua applicazione
You do **not** need to pass these to the clientsthey read from `process.env` automatically. The API key's permissions are determined by the role referenced in `defaultRoleUniversalIdentifier` in your `application-config.ts`.
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`.
#### Caricamento dei file
`MetadataApiClient` includes an `uploadFile` method for attaching files to file-type fields. It implements the [GraphQL multipart request specification](https://github.com/jaydenseric/graphql-multipart-request-spec):
`MetadataApiClient` include un metodo `uploadFile` per allegare file ai campi di tipo file. Implementa la [specifica delle richieste GraphQL multipart](https://github.com/jaydenseric/graphql-multipart-request-spec):
```typescript
import { MetadataApiClient } from 'twenty-client-sdk/metadata';
@@ -953,7 +953,7 @@ console.log(uploadedFile);
Punti chiave:
* Uses the field's `universalIdentifier` (not its workspace-specific ID), so your upload code works across any workspace where your app is installed.
* Usa l'`universalIdentifier` del campo (non il suo ID specifico dello spazio di lavoro), quindi il tuo codice di upload funziona in qualsiasi spazio di lavoro in cui la tua app è installata.
* L'`url` restituito è un URL firmato che puoi usare per accedere al file caricato.
### Esempio Hello World
@@ -15,21 +15,21 @@ Biblioteca twenty-sdk oferă blocuri de bază tipizate și funcții ajutătoare
SDK-ul oferă funcții ajutătoare pentru definirea entităților aplicației. După cum este descris în [Detectarea entităților](/l/ro/developers/extend/apps/getting-started#entity-detection), trebuie să folosiți `export default define<Entity>({...})` pentru ca entitățile să fie detectate:
| Funcție | Scop |
| -------------------------------- | ----------------------------------------------------------------------------------- |
| `defineApplication` | Configurați metadatele aplicației (obligatoriu, una per aplicație) |
| `defineObject` | Definiți obiecte personalizate cu câmpuri |
| `defineField` | Extend existing objects with additional fields or define standalone relation fields |
| `defineLogicFunction` | Definiți funcții de logică cu handleri |
| `definePreInstallLogicFunction` | Definește o funcție logică de pre-instalare (una per aplicație) |
| `definePostInstallLogicFunction` | Definește o funcție logică post-instalare (una per aplicație) |
| `defineFrontComponent` | Definiți componente Front pentru interfața de utilizator personalizată |
| `defineRole` | Configurați permisiunile rolurilor și accesul la obiecte |
| `defineView` | Definește vizualizări salvate pentru obiecte |
| `defineNavigationMenuItem` | Definește linkuri de navigare în bara laterală |
| `defineSkill` | Definiți abilități pentru agentul AI |
| `defineAgent` | Define AI agents |
| `definePageLayout` | Define custom page layouts |
| Funcție | Scop |
| -------------------------------- | -------------------------------------------------------------------------------------------------- |
| `defineApplication` | Configurați metadatele aplicației (obligatoriu, una per aplicație) |
| `defineObject` | Definiți obiecte personalizate cu câmpuri |
| `defineField` | Extindeți obiectele existente cu câmpuri suplimentare sau definiți câmpuri de relație independente |
| `defineLogicFunction` | Definiți funcții de logică cu handleri |
| `definePreInstallLogicFunction` | Definește o funcție logică de pre-instalare (una per aplicație) |
| `definePostInstallLogicFunction` | Definește o funcție logică post-instalare (una per aplicație) |
| `defineFrontComponent` | Definiți componente Front pentru interfața de utilizator personalizată |
| `defineRole` | Configurați permisiunile rolurilor și accesul la obiecte |
| `defineView` | Definește vizualizări salvate pentru obiecte |
| `defineNavigationMenuItem` | Definește linkuri de navigare în bara laterală |
| `defineSkill` | Definiți abilități pentru agentul AI |
| `defineAgent` | Definiți agenți AI |
| `definePageLayout` | Definiți machete de pagină personalizate |
Aceste funcții validează configurația în timpul build-ului și oferă completare automată în IDE și siguranța tipurilor.
@@ -112,7 +112,7 @@ Puncte cheie:
* `universalIdentifier` trebuie să fie unic și stabil între implementări.
* Fiecare câmp necesită un `name`, un `type`, un `label` și propriul `universalIdentifier` stabil.
* Matricea `fields` este opțională — puteți defini obiecte fără câmpuri personalizate.
* You can scaffold new objects using `yarn twenty add`, which guides you through naming, fields, and relationships.
* Puteți genera obiecte noi folosind `yarn twenty add`, care vă ghidează prin denumire, câmpuri și relații.
<Note>
**Câmpurile de bază sunt create automat.** Când definiți un obiect personalizat, Twenty adaugă automat câmpuri standard
@@ -124,7 +124,7 @@ dar acest lucru nu este recomandat.
### Definirea câmpurilor pe obiecte existente
Use `defineField()` to add fields to objects you don't own — such as standard Twenty objects (Person, Company, etc.) or objects from other apps. Unlike inline fields in `defineObject()`, standalone fields require an `objectUniversalIdentifier` to specify which object they extend:
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:
```typescript
// src/fields/company-loyalty-tier.field.ts
@@ -147,35 +147,35 @@ export default defineField({
Puncte cheie:
* `objectUniversalIdentifier` identifies the target object. For standard objects, use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` exported from `twenty-sdk`.
* When defining fields inline in `defineObject()`, you do **not** need `objectUniversalIdentifier` — it's inherited from the parent object.
* `defineField()` is the only way to add fields to objects you didn't create with `defineObject()`.
* `objectUniversalIdentifier` identifică obiectul țintă. Pentru obiectele standard, utilizați `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` exportați din `twenty-sdk`.
* Atunci când definiți câmpuri inline în `defineObject()`, nu aveți nevoie de `objectUniversalIdentifier` — este moștenit de la obiectul părinte.
* `defineField()` este singura modalitate de a adăuga câmpuri la obiecte pe care nu le-ați creat cu `defineObject()`.
### Relații
Relations connect objects together. In Twenty, relations are always **bidirectional** you define both sides, and each side references the other.
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ă.
There are two relation types:
Există două tipuri de relații:
| Tip relație | Descriere | Has foreign key? |
| ------------- | ------------------------------------------------------------- | ---------------------- |
| `MANY_TO_ONE` | Many records of this object point to one record of the target | Yes (`joinColumnName`) |
| `ONE_TO_MANY` | One record of this object has many records of the target | No (inverse side) |
| Tip relație | Descriere | Are cheie străină? |
| ------------- | ---------------------------------------------------------------------------------- | --------------------- |
| `MANY_TO_ONE` | Multe înregistrări ale acestui obiect indică către o singură înregistrare a țintei | Da (`joinColumnName`) |
| `ONE_TO_MANY` | O înregistrare a acestui obiect are multe înregistrări ale țintei | Nu (partea inversă) |
#### How relations work
#### Cum funcționează relațiile
Every relation requires **two fields** that reference each other:
Fiecare relație necesită **două câmpuri** care se referențiază reciproc:
1. The **MANY_TO_ONE** side — lives on the object that holds the foreign key
2. The **ONE_TO_MANY** side — lives on the object that owns the collection
1. Partea **MANY_TO_ONE** — se află pe obiectul care deține cheia străină
2. Partea **ONE_TO_MANY** — se află pe obiectul care deține colecția
Both fields use `FieldType.RELATION` and cross-reference each other via `relationTargetFieldMetadataUniversalIdentifier`.
Ambele câmpuri folosesc `FieldType.RELATION` și se referențiază încrucișat prin `relationTargetFieldMetadataUniversalIdentifier`.
#### Example: Post Card has many Recipients
#### Exemplu: Post Card are mulți destinatari
Suppose a `PostCard` can be sent to many `PostCardRecipient` records. Each recipient belongs to exactly one post card.
Presupuneți că un `PostCard` poate fi trimis către multe înregistrări `PostCardRecipient`. Fiecare destinatar aparține exact unui Post Card.
**Step 1: Define the ONE_TO_MANY side on PostCard** (the "one" side):
**Pasul 1: Definiți partea ONE_TO_MANY pe PostCard** (partea "one"):
```typescript
// src/fields/post-card-recipients-on-post-card.field.ts
@@ -203,7 +203,7 @@ export default defineField({
});
```
**Step 2: Define the MANY_TO_ONE side on PostCardRecipient** (the "many" side — holds the foreign key):
**Pasul 2: Definiți partea MANY_TO_ONE pe PostCardRecipient** (partea "many" — deține cheia străină):
```typescript
// src/fields/post-card-on-post-card-recipient.field.ts
@@ -234,12 +234,12 @@ export default defineField({
```
<Note>
**Circular imports:** Both relation fields reference each other's `universalIdentifier`. To avoid circular import issues, export your field IDs as named constants from each file, and import them in the other file. The build system resolves these at compile time.
**Importuri circulare:** Ambele câmpuri de relație se referă unul la celălalt prin `universalIdentifier`. Pentru a evita problemele de import circular, exportați ID-urile câmpurilor ca constante denumite din fiecare fișier și importați-le în celălalt fișier. Sistemul de build le rezolvă în timpul compilării.
</Note>
#### Relating to standard objects
#### Relaționarea cu obiectele standard
To create a relation with a built-in Twenty object (Person, Company, etc.), use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS`:
Pentru a crea o relație cu un obiect Twenty încorporat (Person, Company etc.), utilizați `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS`:
```typescript
// src/fields/person-on-self-hosting-user.field.ts
@@ -274,20 +274,20 @@ export default defineField({
});
```
#### Relation field properties
#### Proprietăți ale câmpului de relație
| Proprietate | Obligatoriu | Descriere |
| ------------------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------- |
| `tip` | Da | Must be `FieldType.RELATION` |
| `relationTargetObjectMetadataUniversalIdentifier` | Da | The `universalIdentifier` of the target object |
| `relationTargetFieldMetadataUniversalIdentifier` | Da | The `universalIdentifier` of the matching field on the target object |
| `universalSettings.relationType` | Da | `RelationType.MANY_TO_ONE` or `RelationType.ONE_TO_MANY` |
| `universalSettings.onDelete` | MANY_TO_ONE only | What happens when the referenced record is deleted: `CASCADE`, `SET_NULL`, `RESTRICT`, or `NO_ACTION` |
| `universalSettings.joinColumnName` | MANY_TO_ONE only | Database column name for the foreign key (e.g., `postCardId`) |
| Proprietate | Obligatoriu | Descriere |
| ------------------------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------- |
| `tip` | Da | Trebuie să fie `FieldType.RELATION` |
| `relationTargetObjectMetadataUniversalIdentifier` | Da | `universalIdentifier` al obiectului țintă |
| `relationTargetFieldMetadataUniversalIdentifier` | Da | `universalIdentifier` al câmpului corespunzător de pe obiectul țintă |
| `universalSettings.relationType` | Da | `RelationType.MANY_TO_ONE` sau `RelationType.ONE_TO_MANY` |
| `universalSettings.onDelete` | Doar MANY_TO_ONE | Ce se întâmplă atunci când înregistrarea referențiată este ștearsă: `CASCADE`, `SET_NULL`, `RESTRICT` sau `NO_ACTION` |
| `universalSettings.joinColumnName` | Doar MANY_TO_ONE | Numele coloanei din baza de date pentru cheia străină (de ex., `postCardId`) |
#### Inline relation fields in defineObject
#### Câmpuri de relație inline în defineObject
You can also define relation fields directly inside `defineObject()`. In that case, omit `objectUniversalIdentifier` — it's inherited from the parent object:
Puteți defini, de asemenea, câmpuri de relație direct în `defineObject()`. În acest caz, omiteți `objectUniversalIdentifier` — este moștenit de la obiectul părinte:
```typescript
export default defineObject({
@@ -354,21 +354,21 @@ Notițe:
* `defaultRoleUniversalIdentifier` trebuie să corespundă fișierului de rol (vedeți mai jos).
* Funcțiile de pre-instalare și post-instalare sunt detectate automat în timpul construirii manifestului. Vezi [Funcții de pre-instalare](#pre-install-functions) și [Funcții post-instalare](#post-install-functions).
#### Marketplace metadata
#### Metadate pentru marketplace
If you plan to [publish your app](/l/ro/developers/extend/apps/publishing), these optional fields control how your app 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 aplicația apare în marketplace:
| Câmp | Descriere |
| ------------------ | --------------------------------------------------- |
| `autor` | Author or company name |
| `categorie` | App category for marketplace filtering |
| `logoUrl` | Path to your app logo (relative to `./assets/`) |
| `screenshots` | Array of screenshot paths (relative to `./assets/`) |
| `aboutDescription` | Longer markdown description for the "About" tab |
| `websiteUrl` | Link to your website |
| `termsUrl` | Link to terms of service |
| `emailSupport` | Support email address |
| `issueReportUrl` | Link to issue tracker |
| Câmp | Descriere |
| ------------------ | ------------------------------------------------------------- |
| `autor` | Numele autorului sau al companiei |
| `categorie` | Categoria aplicației pentru filtrarea în marketplace |
| `logoUrl` | Calea către logo-ul aplicației (relativă la `./assets/`) |
| `screenshots` | Listă de căi către capturi de ecran (relative la `./assets/`) |
| `aboutDescription` | Descriere markdown mai lungă pentru fila "About" |
| `websiteUrl` | Link către site-ul dvs. |
| `termsUrl` | Link către termenii de serviciu |
| `emailSupport` | Adresă de e-mail pentru suport |
| `issueReportUrl` | Link către sistemul de urmărire a problemelor |
#### Roluri și permisiuni
@@ -376,7 +376,7 @@ Aplicațiile pot defini roluri care încapsulează permisiuni asupra obiectelor
* Cheia API de runtime injectată ca `TWENTY_API_KEY` este derivată din acest rol implicit pentru funcții.
* Clientul tipizat va fi restricționat la permisiunile acordate acelui rol.
* Follow least-privilege: create a dedicated role with only the permissions your functions need, then reference its universal identifier.
* Respectați principiul celui mai mic privilegiu: creați un rol dedicat doar cu permisiunile de care au nevoie funcțiile, apoi referiți identificatorul său universal.
##### Rol implicit pentru funcții (*.role.ts)
@@ -429,7 +429,7 @@ export default defineRole({
Notițe:
* Start from the scaffolded role, then progressively restrict it following least-privilege.
* Porniți de la rolul generat, apoi restrângeți-l progresiv urmând principiul celui mai mic privilegiu.
* Înlocuiți `objectPermissions` și `fieldPermissions` cu obiectele/câmpurile de care au nevoie funcțiile.
* `permissionFlags` controlează accesul la capabilități la nivelul platformei. Mențineți-le la minimum; adăugați doar ceea ce aveți nevoie.
* Vedeți un exemplu funcțional în aplicația Hello World: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
@@ -543,7 +543,7 @@ Puncte cheie:
* Este permisă o singură funcție de pre-instalare per aplicație. Construirea manifestului va genera o eroare dacă este detectată mai mult de una.
* Proprietatea `universalIdentifier` a funcției este setată automat ca `preInstallLogicFunctionUniversalIdentifier` în manifestul aplicației în timpul build-ului — nu este nevoie să o referi în `defineApplication()`.
* Timpul de expirare implicit este setat la 300 de secunde (5 minute) pentru a permite sarcini de pregătire mai lungi.
* Pre-install functions do not need triggers — they are invoked by the platform before installation or manually via `exec --preInstall`.
* Funcțiile de pre-instalare nu au nevoie de declanșatoare — sunt invocate de platformă înainte de instalare sau manual prin `exec --preInstall`.
### Funcții post-instalare
@@ -581,7 +581,7 @@ Puncte cheie:
* Este permisă o singură funcție de post-instalare per aplicație. Construirea manifestului va genera o eroare dacă este detectată mai mult de una.
* Proprietatea `universalIdentifier` a funcției este setată automat ca `postInstallLogicFunctionUniversalIdentifier` în manifestul aplicației în timpul build-ului — nu este nevoie să o referi în `defineApplication()`.
* Timpul de expirare implicit este setat la 300 de secunde (5 minute) pentru a permite sarcini de configurare mai lungi, cum ar fi popularea datelor.
* Post-install functions do not need triggers — they are invoked by the platform during installation or manually via `exec --postInstall`.
* Funcțiile post-instalare nu au nevoie de declanșatoare — sunt invocate de platformă în timpul instalării sau manual prin `exec --postInstall`.
### Payload-ul declanșatorului de rută
@@ -625,15 +625,15 @@ const handler = async (event: RoutePayload) => {
Tipul `RoutePayload` are următoarea structură:
| Proprietate | Tip | Descriere |
| ---------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | Anteturi HTTP (doar cele listate în `forwardedRequestHeaders`) |
| `queryStringParameters` | `Record<string, string \| undefined>` | Parametri query string (valorile multiple unite cu virgule) |
| `pathParameters` | `Record<string, string \| undefined>` | Path parameters extracted from the route pattern (e.g., `/users/:id` -> `{ id: '123' }`) |
| `body` | `object \| null` | Corpul cererii analizat (JSON) |
| `isBase64Encoded` | `boolean` | Indică dacă corpul este codificat în base64 |
| `requestContext.http.method` | `string` | Metoda HTTP (GET, POST, PUT, PATCH, DELETE) |
| `requestContext.http.path` | `string` | Calea brută a cererii |
| Proprietate | Tip | Descriere |
| ---------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | Anteturi HTTP (doar cele listate în `forwardedRequestHeaders`) |
| `queryStringParameters` | `Record<string, string \| undefined>` | Parametri query string (valorile multiple unite cu virgule) |
| `pathParameters` | `Record<string, string \| undefined>` | Parametri de cale extrași din modelul rutei (de ex., `/users/:id` -> `{ id: '123' }`) |
| `body` | `object \| null` | Corpul cererii analizat (JSON) |
| `isBase64Encoded` | `boolean` | Indică dacă corpul este codificat în base64 |
| `requestContext.http.method` | `string` | Metoda HTTP (GET, POST, PUT, PATCH, DELETE) |
| `requestContext.http.path` | `string` | Calea brută a cererii |
### Transmiterea anteturilor HTTP
@@ -675,7 +675,7 @@ const handler = async (event: RoutePayload) => {
Puteți crea funcții noi în două moduri:
* **Scaffolded**: Run `yarn twenty add` and choose the option to add a new logic function. Aceasta generează un fișier inițial cu un handler și o configurație.
* **Generat**: Rulați `yarn twenty add` și alegeți opțiunea de a adăuga o funcție de logică nouă. Aceasta generează un fișier inițial cu un handler și o configurație.
* **Manual**: Creați un fișier nou `*.logic-function.ts` și folosiți `defineLogicFunction()`, urmând același model.
### Marcarea unei funcții logice drept instrument
@@ -776,7 +776,7 @@ Puncte cheie:
Puteți crea componente Front noi în două moduri:
* **Scaffolded**: Run `yarn twenty add` and choose the option to add a new front component.
* **Generat**: Rulați `yarn twenty add` și alegeți opțiunea de a adăuga o componentă Front nouă.
* **Manual**: Creați un fișier nou `.tsx` și folosiți `defineFrontComponent()`, urmând același model.
### Abilități
@@ -811,21 +811,21 @@ Puncte cheie:
Puteți crea abilități noi în două moduri:
* **Scaffolded**: Run `yarn twenty add` and choose the option to add a new skill.
* **Generat**: Rulați `yarn twenty add` și alegeți opțiunea de a adăuga o abilitate nouă.
* **Manual**: Creați un fișier nou și folosiți `defineSkill()`, urmând același model.
### Typed API clients (`twenty-client-sdk`)
### Clienți API tipați (`twenty-client-sdk`)
The `twenty-client-sdk` package provides two typed GraphQL clients for interacting with the Twenty API from your logic functions and front components:
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:
| Client | Importați | Endpoint | Generated? |
| ------------------- | ---------------------------- | ---------------------------------------------- | ---------------------- |
| `CoreApiClient` | `twenty-client-sdk/core` | `/graphql` — workspace data (records, objects) | Yes, at dev/build time |
| `MetadataApiClient` | `twenty-client-sdk/metadata` | `/metadata` — workspace config, file uploads | No, ships pre-built |
| Client | Importați | Endpoint | Generat? |
| ------------------- | ---------------------------- | ------------------------------------------------------------------- | ---------------------------- |
| `CoreApiClient` | `twenty-client-sdk/core` | `/graphql` — date ale spațiului de lucru (înregistrări, obiecte) | Da, în timpul dev/build |
| `MetadataApiClient` | `twenty-client-sdk/metadata` | `/metadata` — configurarea spațiului de lucru, încărcări de fișiere | Nu, este livrat preconstruit |
#### CoreApiClient
`CoreApiClient` is the main client for querying and mutating workspace data. It is **generated from your workspace schema** during `yarn twenty dev` or `yarn twenty build`, so it's 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 dvs. de lucru în timpul `yarn twenty dev` sau `yarn twenty build`, astfel încât este complet tipat pentru a corespunde obiectelor și câmpurilor dvs.
```typescript
import { CoreApiClient } from 'twenty-client-sdk/core';
@@ -859,15 +859,15 @@ const { createCompany } = await client.mutation({
});
```
The client uses a selection-set syntax: pass `true` to include a field, use `__args` for arguments, and nest objects for relations. You get full autocompletion and type checking based on your workspace schema.
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.
<Note>
**CoreApiClient is generated at dev/build time.** If you try to 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, generates a typed client using `@genql/cli`, writes the generated sources to `node_modules/twenty-client-sdk/dist/core/generated/`, and replaces the stubs in `node_modules/twenty-client-sdk/dist/core.mjs` and `node_modules/twenty-client-sdk/dist/core.cjs`.
**CoreApiClient este generat în timpul dev/build.** Dacă încercați să î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-ul introspectează schema GraphQL a spațiului dvs. de lucru, generează un client tipat folosind `@genql/cli`, scrie sursele generate în `node_modules/twenty-client-sdk/dist/core/generated/` și înlocuiește stubs-urile din `node_modules/twenty-client-sdk/dist/core.mjs` și `node_modules/twenty-client-sdk/dist/core.cjs`.
</Note>
#### Using CoreSchema for type annotations
#### 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 se potrivesc obiectelor din spațiul dvs. de lucru, utile pentru tiparea stării componentelor sau a parametrilor funcțiilor:
```typescript
import { CoreApiClient, CoreSchema } from 'twenty-client-sdk/core';
@@ -890,7 +890,7 @@ setCompany(result.company);
#### MetadataApiClient
`MetadataApiClient` ships pre-built with the SDK (no generation required). It queries the `/metadata` endpoint for workspace configuration, applications, and file uploads:
`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:
```typescript
import { MetadataApiClient } from 'twenty-client-sdk/metadata';
@@ -912,18 +912,18 @@ const { findManyApplications } = await metadataClient.query({
});
```
#### Runtime credentials
#### Acreditări la rulare
When your code runs on Twenty (logic functions or front components), the platform injects credentials as environment variables:
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` — Base URL of the Twenty API
* `TWENTY_API_KEY` — Short-lived key scoped to your application's default function role
* `TWENTY_API_URL` — URL-ul de bază al API-ului Twenty
* `TWENTY_API_KEY` — Cheie cu durată scurtă, limitată la rolul implicit de funcție al aplicației
You do **not** need to pass these to the clients — they read from `process.env` automatically. The API key's permissions are determined by the role referenced in `defaultRoleUniversalIdentifier` in your `application-config.ts`.
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`.
#### Încărcarea fișierelor
`MetadataApiClient` includes an `uploadFile` method for attaching files to file-type fields. It implements the [GraphQL multipart request specification](https://github.com/jaydenseric/graphql-multipart-request-spec):
`MetadataApiClient` include o metodă `uploadFile` pentru atașarea fișierelor la câmpuri de tip fișier. Implementează [specificația pentru cereri GraphQL multipart](https://github.com/jaydenseric/graphql-multipart-request-spec):
```typescript
import { MetadataApiClient } from 'twenty-client-sdk/metadata';
@@ -953,7 +953,7 @@ console.log(uploadedFile);
Puncte cheie:
* Uses the field's `universalIdentifier` (not its workspace-specific ID), so your upload code works across any workspace where your app is installed.
* Folosește `universalIdentifier` al câmpului (nu ID-ul specific spațiului de lucru), astfel încât codul dvs. de încărcare funcționează în orice spațiu de lucru în care aplicația dvs. este instalată.
* `url` returnat este un URL semnat pe care îl poți folosi pentru a accesa fișierul încărcat.
### Exemplu Hello World
@@ -15,21 +15,21 @@ description: Определяйте объекты, функции логики,
SDK предоставляет вспомогательные функции для определения сущностей вашего приложения. Как описано в [Обнаружение сущностей](/l/ru/developers/extend/apps/getting-started#entity-detection), вы должны использовать `export default define<Entity>({...})`, чтобы ваши сущности были обнаружены:
| Функция | Назначение |
| -------------------------------- | ----------------------------------------------------------------------------------- |
| `defineApplication` | Настройка метаданных приложения (обязательно, по одному на приложение) |
| `defineObject` | Определяет пользовательские объекты с полями |
| `defineField` | Extend existing objects with additional fields or define standalone relation fields |
| `defineLogicFunction` | Определение логических функций с обработчиками |
| `definePreInstallLogicFunction` | Определяет предустановочную логическую функцию (по одной на приложение) |
| `definePostInstallLogicFunction` | Определяет послеустановочную логическую функцию (по одной на приложение) |
| `defineFrontComponent` | Определение фронт-компонентов для настраиваемого интерфейса |
| `defineRole` | Настраивает права роли и доступ к объектам |
| `defineView` | Определяйте сохранённые представления для объектов |
| `defineNavigationMenuItem` | Определяйте ссылки боковой панели навигации |
| `defineSkill` | Определение навыков агента ИИ |
| `defineAgent` | Define AI agents |
| `definePageLayout` | Define custom page layouts |
| Функция | Назначение |
| -------------------------------- | ----------------------------------------------------------------------------------------------- |
| `defineApplication` | Настройка метаданных приложения (обязательно, по одному на приложение) |
| `defineObject` | Определяет пользовательские объекты с полями |
| `defineField` | Расширяйте существующие объекты дополнительными полями или определяйте отдельные поля отношений |
| `defineLogicFunction` | Определение логических функций с обработчиками |
| `definePreInstallLogicFunction` | Определяет предустановочную логическую функцию (по одной на приложение) |
| `definePostInstallLogicFunction` | Определяет послеустановочную логическую функцию (по одной на приложение) |
| `defineFrontComponent` | Определение фронт-компонентов для настраиваемого интерфейса |
| `defineRole` | Настраивает права роли и доступ к объектам |
| `defineView` | Определяйте сохранённые представления для объектов |
| `defineNavigationMenuItem` | Определяйте ссылки боковой панели навигации |
| `defineSkill` | Определение навыков агента ИИ |
| `defineAgent` | Определяйте агентов ИИ |
| `definePageLayout` | Определяйте пользовательские макеты страниц |
Эти функции проверяют вашу конфигурацию на этапе сборки и обеспечивают автодополнение в IDE и безопасность типов.
@@ -112,7 +112,7 @@ export default defineObject({
* `universalIdentifier` должен быть уникальным и стабильным между развёртываниями.
* Каждому полю требуются `name`, `type`, `label` и собственный стабильный `universalIdentifier`.
* Массив `fields` необязателен — вы можете определять объекты без пользовательских полей.
* You can scaffold new objects using `yarn twenty add`, which guides you through naming, fields, and relationships.
* Вы можете сгенерировать новые объекты с помощью `yarn twenty add`, который проведёт вас через выбор именования, полей и связей.
<Note>
**Базовые поля создаются автоматически.** Когда вы определяете пользовательский объект, Twenty автоматически добавляет стандартные поля,
@@ -124,7 +124,7 @@ export default defineObject({
### Определение полей для существующих объектов
Use `defineField()` to add fields to objects you don't own — such as standard Twenty objects (Person, Company, etc.) or objects from other apps. Unlike inline fields in `defineObject()`, standalone fields require an `objectUniversalIdentifier` to specify which object they extend:
Используйте `defineField()` для добавления полей к объектам, которые вам не принадлежат — например, к стандартным объектам Twenty (Person, Company и т. д.). или к объектам из других приложений. В отличие от встроенных полей в `defineObject()`, отдельные поля требуют `objectUniversalIdentifier`, чтобы указать, какой объект они расширяют:
```typescript
// src/fields/company-loyalty-tier.field.ts
@@ -147,35 +147,35 @@ export default defineField({
Основные моменты:
* `objectUniversalIdentifier` identifies the target object. For standard objects, use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` exported from `twenty-sdk`.
* When defining fields inline in `defineObject()`, you do **not** need `objectUniversalIdentifier` — it's inherited from the parent object.
* `defineField()` is the only way to add fields to objects you didn't create with `defineObject()`.
* `objectUniversalIdentifier` определяет целевой объект. Для стандартных объектов используйте `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS`, экспортируемые из `twenty-sdk`.
* При определении полей непосредственно в `defineObject()` вам не нужен `objectUniversalIdentifier` — он наследуется от родительского объекта.
* `defineField()` — единственный способ добавить поля к объектам, которые вы не создавали с помощью `defineObject()`.
### Связи
Relations connect objects together. In Twenty, relations are always **bidirectional** — you define both sides, and each side references the other.
Отношения связывают объекты между собой. В Twenty отношения всегда двунаправленные — вы определяете обе стороны, и каждая сторона ссылается на другую.
There are two relation types:
Существуют два типа отношений:
| Тип отношения | Описание | Has foreign key? |
| ------------- | ------------------------------------------------------------- | ---------------------- |
| `MANY_TO_ONE` | Many records of this object point to one record of the target | Yes (`joinColumnName`) |
| `ONE_TO_MANY` | One record of this object has many records of the target | No (inverse side) |
| Тип отношения | Описание | Есть внешний ключ? |
| ------------- | --------------------------------------------------------------------- | ---------------------- |
| `MANY_TO_ONE` | Многие записи этого объекта указывают на одну запись целевого объекта | Да (`joinColumnName`) |
| `ONE_TO_MANY` | Одна запись этого объекта имеет много записей целевого объекта | Нет (обратная сторона) |
#### How relations work
#### Как работают отношения
Every relation requires **two fields** that reference each other:
Каждое отношение требует **двух полей**, которые ссылаются друг на друга:
1. The **MANY_TO_ONE** side — lives on the object that holds the foreign key
2. The **ONE_TO_MANY** side — lives on the object that owns the collection
1. Сторона **MANY_TO_ONE** — находится в объекте, который содержит внешний ключ
2. Сторона **ONE_TO_MANY** — находится в объекте, которому принадлежит коллекция
Both fields use `FieldType.RELATION` and cross-reference each other via `relationTargetFieldMetadataUniversalIdentifier`.
Оба поля используют `FieldType.RELATION` и ссылаются друг на друга через `relationTargetFieldMetadataUniversalIdentifier`.
#### Example: Post Card has many Recipients
#### Пример: Почтовая открытка имеет много получателей
Suppose a `PostCard` can be sent to many `PostCardRecipient` records. Each recipient belongs to exactly one post card.
Предположим, `PostCard` может быть отправлен множству записей `PostCardRecipient`. Каждый получатель относится ровно к одной открытке.
**Step 1: Define the ONE_TO_MANY side on PostCard** (the "one" side):
**Шаг 1: Определите сторону ONE_TO_MANY на PostCard** (сторона "one"):
```typescript
// src/fields/post-card-recipients-on-post-card.field.ts
@@ -203,7 +203,7 @@ export default defineField({
});
```
**Step 2: Define the MANY_TO_ONE side on PostCardRecipient** (the "many" side — holds the foreign key):
**Шаг 2: Определите сторону MANY_TO_ONE на PostCardRecipient** (сторона "many" — содержит внешний ключ):
```typescript
// src/fields/post-card-on-post-card-recipient.field.ts
@@ -234,12 +234,12 @@ export default defineField({
```
<Note>
**Circular imports:** Both relation fields reference each other's `universalIdentifier`. To avoid circular import issues, export your field IDs as named constants from each file, and import them in the other file. The build system resolves these at compile time.
**Циклические импорты:** Оба поля отношений ссылаются на `universalIdentifier` друг друга. Чтобы избежать проблем с циклическими импортами, экспортируйте идентификаторы полей как именованные константы из каждого файла и импортируйте их в другом файле. Система сборки разрешает это на этапе компиляции.
</Note>
#### Relating to standard objects
#### Связывание со стандартными объектами
To create a relation with a built-in Twenty object (Person, Company, etc.), use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS`:
Чтобы создать отношение со встроенным объектом Twenty (Person, Company и т. д.), используйте `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS`:
```typescript
// src/fields/person-on-self-hosting-user.field.ts
@@ -274,20 +274,20 @@ export default defineField({
});
```
#### Relation field properties
#### Свойства поля отношения
| Свойство | Обязательно | Описание |
| ------------------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------- |
| `type` | Да | Must be `FieldType.RELATION` |
| `relationTargetObjectMetadataUniversalIdentifier` | Да | The `universalIdentifier` of the target object |
| `relationTargetFieldMetadataUniversalIdentifier` | Да | The `universalIdentifier` of the matching field on the target object |
| `universalSettings.relationType` | Да | `RelationType.MANY_TO_ONE` or `RelationType.ONE_TO_MANY` |
| `universalSettings.onDelete` | MANY_TO_ONE only | What happens when the referenced record is deleted: `CASCADE`, `SET_NULL`, `RESTRICT`, or `NO_ACTION` |
| `universalSettings.joinColumnName` | MANY_TO_ONE only | Database column name for the foreign key (e.g., `postCardId`) |
| Свойство | Обязательно | Описание |
| ------------------------------------------------- | ---------------------- | ----------------------------------------------------------------------------------------------- |
| `type` | Да | Должно быть `FieldType.RELATION` |
| `relationTargetObjectMetadataUniversalIdentifier` | Да | `universalIdentifier` целевого объекта |
| `relationTargetFieldMetadataUniversalIdentifier` | Да | `universalIdentifier` соответствующего поля на целевом объекте |
| `universalSettings.relationType` | Да | `RelationType.MANY_TO_ONE` или `RelationType.ONE_TO_MANY` |
| `universalSettings.onDelete` | Только для MANY_TO_ONE | Что происходит при удалении связанной записи: `CASCADE`, `SET_NULL`, `RESTRICT` или `NO_ACTION` |
| `universalSettings.joinColumnName` | Только для MANY_TO_ONE | Имя столбца базы данных для внешнего ключа (например, `postCardId`) |
#### Inline relation fields in defineObject
#### Встроенные поля отношений в defineObject
You can also define relation fields directly inside `defineObject()`. In that case, omit `objectUniversalIdentifier` — it's inherited from the parent object:
Вы также можете определять поля отношений непосредственно внутри `defineObject()`. В этом случае опустите `objectUniversalIdentifier` — он наследуется от родительского объекта:
```typescript
export default defineObject({
@@ -354,21 +354,21 @@ export default defineApplication({
* `defaultRoleUniversalIdentifier` должен соответствовать файлу роли (см. ниже).
* Предустановочные и послеустановочные функции автоматически обнаруживаются во время сборки манифеста. См. [Предустановочные функции](#pre-install-functions) и [Послеустановочные функции](#post-install-functions).
#### Marketplace metadata
#### Метаданные маркетплейса
If you plan to [publish your app](/l/ru/developers/extend/apps/publishing), these optional fields control how your app appears in the marketplace:
Если вы планируете [опубликовать приложение](/l/ru/developers/extend/apps/publishing), эти необязательные поля определяют, как ваше приложение отображается в маркетплейсе:
| Поле | Описание |
| ------------------ | --------------------------------------------------- |
| `author` | Author or company name |
| `category` | App category for marketplace filtering |
| `logoUrl` | Path to your app logo (relative to `./assets/`) |
| `screenshots` | Array of screenshot paths (relative to `./assets/`) |
| `aboutDescription` | Longer markdown description for the "About" tab |
| `websiteUrl` | Link to your website |
| `termsUrl` | Link to terms of service |
| `emailSupport` | Support email address |
| `issueReportUrl` | Link to issue tracker |
| Поле | Описание |
| ------------------ | ------------------------------------------------------------ |
| `author` | Имя автора или название компании |
| `category` | Категория приложения для фильтрации в маркетплейсе |
| `logoUrl` | Путь к логотипу вашего приложения (относительно `./assets/`) |
| `screenshots` | Массив путей к скриншотам (относительно `./assets/`) |
| `aboutDescription` | Расширенное описание в Markdown для вкладки "About" |
| `websiteUrl` | Ссылка на ваш сайт |
| `termsUrl` | Ссылка на условия предоставления услуг |
| `emailSupport` | Адрес электронной почты поддержки |
| `issueReportUrl` | Ссылка на систему отслеживания проблем |
#### Роли и разрешения
@@ -376,7 +376,7 @@ If you plan to [publish your app](/l/ru/developers/extend/apps/publishing), thes
* Ключ API во время выполнения, подставляемый как `TWENTY_API_KEY`, получается из этой роли функции по умолчанию.
* Типизированный клиент будет ограничен правами, предоставленными этой ролью.
* Follow least-privilege: create a dedicated role with only the permissions your functions need, then reference its universal identifier.
* Следуйте принципу наименьших привилегий: создайте отдельную роль только с теми правами, которые нужны вашим функциям, и укажите её универсальный идентификатор.
##### Роль функции по умолчанию (*.role.ts)
@@ -429,7 +429,7 @@ export default defineRole({
Заметки:
* Start from the scaffolded role, then progressively restrict it following least-privilege.
* Начните со сгенерированной роли, затем постепенно ограничивайте её, следуя принципу наименьших привилегий.
* Замените `objectPermissions` и `fieldPermissions` на объекты/поля, которые нужны вашим функциям.
* `permissionFlags` управляют доступом к возможностям на уровне платформы. Держите их минимальными; добавляйте только то, что нужно.
* См. рабочий пример в приложении Hello World: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
@@ -543,7 +543,7 @@ yarn twenty exec --preInstall
* Для каждого приложения допускается только одна предустановочная функция. Сборка манифеста завершится ошибкой, если будет обнаружено более одной такой функции.
* Параметр `universalIdentifier` функции автоматически устанавливается как `preInstallLogicFunctionUniversalIdentifier` в манифесте приложения во время сборки — вам не нужно ссылаться на него в `defineApplication()`.
* Тайм-аут по умолчанию установлен на 300 секунд (5 минут), чтобы обеспечить выполнение более длительных задач подготовки.
* Pre-install functions do not need triggers — they are invoked by the platform before installation or manually via `exec --preInstall`.
* Предустановочным функциям не нужны триггеры — платформа вызывает их перед установкой или вручную через `exec --preInstall`.
### Послеустановочные функции
@@ -581,7 +581,7 @@ yarn twenty exec --postInstall
* Для каждого приложения допускается только одна послеустановочная функция. Сборка манифеста завершится ошибкой, если будет обнаружено более одной такой функции.
* Параметр `universalIdentifier` функции автоматически устанавливается как `postInstallLogicFunctionUniversalIdentifier` в манифесте приложения во время сборки — вам не нужно ссылаться на него в `defineApplication()`.
* Тайм-аут по умолчанию установлен на 300 секунд (5 минут), чтобы позволить выполнять более длительные задачи настройки, такие как инициализация данных.
* Post-install functions do not need triggers — they are invoked by the platform during installation or manually via `exec --postInstall`.
* Постустановочным функциям не нужны триггеры — платформа вызывает их во время установки или вручную через `exec --postInstall`.
### Полезная нагрузка триггера маршрута
@@ -625,15 +625,15 @@ const handler = async (event: RoutePayload) => {
Тип `RoutePayload` имеет следующую структуру:
| Свойство | Тип | Описание |
| ---------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | HTTP-заголовки (только перечисленные в `forwardedRequestHeaders`) |
| `queryStringParameters` | `Record<string, string \| undefined>` | Параметры строки запроса (несколько значений объединяются запятыми) |
| `pathParameters` | `Record<string, string \| undefined>` | Path parameters extracted from the route pattern (e.g., `/users/:id` -> `{ id: '123' }`) |
| `body` | `object \| null` | Разобранное тело запроса (JSON) |
| `isBase64Encoded` | `логический тип` | Является ли тело закодированным в base64 |
| `requestContext.http.method` | `строка` | Метод HTTP (GET, POST, PUT, PATCH, DELETE) |
| `requestContext.http.path` | `строка` | Необработанный путь запроса |
| Свойство | Тип | Описание |
| ---------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | HTTP-заголовки (только перечисленные в `forwardedRequestHeaders`) |
| `queryStringParameters` | `Record<string, string \| undefined>` | Параметры строки запроса (несколько значений объединяются запятыми) |
| `pathParameters` | `Record<string, string \| undefined>` | Параметры пути, извлечённые из шаблона маршрута (например, `/users/:id` -> `{ id: '123' }`) |
| `body` | `object \| null` | Разобранное тело запроса (JSON) |
| `isBase64Encoded` | `логический тип` | Является ли тело закодированным в base64 |
| `requestContext.http.method` | `строка` | Метод HTTP (GET, POST, PUT, PATCH, DELETE) |
| `requestContext.http.path` | `строка` | Необработанный путь запроса |
### Проброс HTTP-заголовков
@@ -675,7 +675,7 @@ const handler = async (event: RoutePayload) => {
Вы можете создать новые функции двумя способами:
* **Scaffolded**: Run `yarn twenty add` and choose the option to add a new logic function. Это создаёт стартовый файл с обработчиком и конфигурацией.
* **Сгенерировано**: Запустите `yarn twenty add` и выберите опцию добавления новой логической функции. Это создаёт стартовый файл с обработчиком и конфигурацией.
* **Вручную**: Создайте новый файл `*.logic-function.ts` и используйте `defineLogicFunction()`, следуя тому же шаблону.
### Пометка логической функции как инструмента
@@ -776,7 +776,7 @@ export default defineFrontComponent({
Вы можете создать новые фронт-компоненты двумя способами:
* **Scaffolded**: Run `yarn twenty add` and choose the option to add a new front component.
* **Сгенерировано**: Запустите `yarn twenty add` и выберите опцию добавления нового фронт-компонента.
* **Вручную**: Создайте новый файл `.tsx` и используйте `defineFrontComponent()`, следуя тому же шаблону.
### Навыки
@@ -811,21 +811,21 @@ export default defineSkill({
Вы можете создать новые навыки двумя способами:
* **Scaffolded**: Run `yarn twenty add` and choose the option to add a new skill.
* **Сгенерировано**: Запустите `yarn twenty add` и выберите опцию добавления нового навыка.
* **Вручную**: Создайте новый файл и используйте `defineSkill()`, следуя тому же шаблону.
### Typed API clients (`twenty-client-sdk`)
### Типизированные клиенты API (`twenty-client-sdk`)
The `twenty-client-sdk` package provides two typed GraphQL clients for interacting with the Twenty API from your logic functions and front components:
Пакет `twenty-client-sdk` предоставляет два типизированных клиента GraphQL для взаимодействия с API Twenty из ваших логических функций и фронт-компонентов:
| Клиент | Импорт | Endpoint | Generated? |
| ------------------- | ---------------------------- | ---------------------------------------------- | ---------------------- |
| `CoreApiClient` | `twenty-client-sdk/core` | `/graphql` — workspace data (records, objects) | Yes, at dev/build time |
| `MetadataApiClient` | `twenty-client-sdk/metadata` | `/metadata` — workspace config, file uploads | No, ships pre-built |
| Клиент | Импорт | Конечная точка | Генерируется? |
| ------------------- | ---------------------------- | ----------------------------------------------------------------- | -------------------------------- |
| `CoreApiClient` | `twenty-client-sdk/core` | `/graphql` — данные рабочего пространства (записи, объекты) | Да, на этапе dev/build |
| `MetadataApiClient` | `twenty-client-sdk/metadata` | `/metadata` — конфигурация рабочего пространства, загрузка файлов | Нет, поставляется в готовом виде |
#### CoreApiClient
`CoreApiClient` is the main client for querying and mutating workspace data. It is **generated from your workspace schema** during `yarn twenty dev` or `yarn twenty build`, so it's fully typed to match your objects and fields.
`CoreApiClient` — основной клиент для запросов и изменений данных рабочего пространства. Он генерируется из схемы вашего рабочего пространства во время `yarn twenty dev` или `yarn twenty build`, поэтому он полностью типизирован в соответствии с вашими объектами и полями.
```typescript
import { CoreApiClient } from 'twenty-client-sdk/core';
@@ -859,15 +859,15 @@ const { createCompany } = await client.mutation({
});
```
The client uses a selection-set syntax: pass `true` to include a field, use `__args` for arguments, and nest objects for relations. You get full autocompletion and type checking based on your workspace schema.
Клиент использует синтаксис selection-set: передайте `true`, чтобы включить поле, используйте `__args` для аргументов и вкладывайте объекты для отношений. Вы получаете полное автодополнение и проверку типов на основе схемы вашего рабочего пространства.
<Note>
**CoreApiClient is generated at dev/build time.** If you try to 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, generates a typed client using `@genql/cli`, writes the generated sources to `node_modules/twenty-client-sdk/dist/core/generated/`, and replaces the stubs in `node_modules/twenty-client-sdk/dist/core.mjs` and `node_modules/twenty-client-sdk/dist/core.cjs`.
**CoreApiClient генерируется на этапе dev/build.** Если вы попытаетесь использовать его, не запустив сначала `yarn twenty dev` или `yarn twenty build`, он выбросит ошибку. Генерация происходит автоматически — CLI анализирует GraphQL-схему вашего рабочего пространства, генерирует типизированный клиент с помощью `@genql/cli`, записывает сгенерированные исходники в `node_modules/twenty-client-sdk/dist/core/generated/` и заменяет заглушки в `node_modules/twenty-client-sdk/dist/core.mjs` и `node_modules/twenty-client-sdk/dist/core.cjs`.
</Note>
#### Using CoreSchema for type annotations
#### Использование CoreSchema для аннотаций типов
`CoreSchema` provides TypeScript types matching your workspace objects, useful for typing component state or function parameters:
`CoreSchema` предоставляет типы TypeScript, соответствующие объектам вашего рабочего пространства, что полезно для типизации состояния компонентов или параметров функций:
```typescript
import { CoreApiClient, CoreSchema } from 'twenty-client-sdk/core';
@@ -890,7 +890,7 @@ setCompany(result.company);
#### MetadataApiClient
`MetadataApiClient` ships pre-built with the SDK (no generation required). It queries the `/metadata` endpoint for workspace configuration, applications, and file uploads:
`MetadataApiClient` поставляется в готовом виде вместе с SDK (генерация не требуется). Он выполняет запросы к эндпоинту `/metadata` для получения конфигурации рабочего пространства, приложений и загрузки файлов:
```typescript
import { MetadataApiClient } from 'twenty-client-sdk/metadata';
@@ -912,18 +912,18 @@ const { findManyApplications } = await metadataClient.query({
});
```
#### Runtime credentials
#### Учётные данные времени выполнения
When your code runs on Twenty (logic functions or front components), the platform injects credentials as environment variables:
Когда ваш код выполняется на Twenty (логические функции или фронт-компоненты), платформа предоставляет учётные данные в виде переменных окружения:
* `TWENTY_API_URL` — Base URL of the Twenty API
* `TWENTY_API_KEY` — Short-lived key scoped to your application's default function role
* `TWENTY_API_URL` — базовый URL API Twenty
* `TWENTY_API_KEY` — краткоживущий ключ, ограниченный ролью функции по умолчанию вашего приложения
You do **not** need to pass these to the clients — they read from `process.env` automatically. The API key's permissions are determined by the role referenced in `defaultRoleUniversalIdentifier` in your `application-config.ts`.
Вам не нужно передавать их клиентам — они автоматически читаются из `process.env`. Права ключа API определяются ролью, указанной в `defaultRoleUniversalIdentifier` в вашем `application-config.ts`.
#### Загрузка файлов
`MetadataApiClient` includes an `uploadFile` method for attaching files to file-type fields. It implements the [GraphQL multipart request specification](https://github.com/jaydenseric/graphql-multipart-request-spec):
`MetadataApiClient` включает метод `uploadFile` для прикрепления файлов к полям типа файла. Он реализует [спецификацию многочастных запросов GraphQL](https://github.com/jaydenseric/graphql-multipart-request-spec):
```typescript
import { MetadataApiClient } from 'twenty-client-sdk/metadata';
@@ -953,7 +953,7 @@ console.log(uploadedFile);
Основные моменты:
* Uses the field's `universalIdentifier` (not its workspace-specific ID), so your upload code works across any workspace where your app is installed.
* Он использует `universalIdentifier` поля (а не его идентификатор, специфичный для рабочего пространства), поэтому ваш код загрузки будет работать в любом рабочем пространстве, где установлено ваше приложение.
* Возвращаемый `url` — это подписанный URL, который можно использовать для доступа к загруженному файлу.
### Пример Hello World
@@ -15,21 +15,21 @@ twenty-sdk, uygulamanız içinde kullandığınız türlendirilmiş yapı taşla
SDK, uygulama varlıklarınızı tanımlamak için yardımcı fonksiyonlar sağlar. [Varlık algılama](/l/tr/developers/extend/apps/getting-started#entity-detection) bölümünde açıklandığı gibi, varlıklarınızın algılanması için `export default define<Entity>({...})` kullanmalısınız:
| Fonksiyon | Amaç |
| -------------------------------- | ----------------------------------------------------------------------------------- |
| `defineApplication` | Uygulama meta verilerini yapılandırın (zorunlu, uygulama başına bir adet) |
| `defineObject` | Alanlara sahip özel nesneler tanımlayın |
| `defineField` | Extend existing objects with additional fields or define standalone relation fields |
| `defineLogicFunction` | İşleyicilerle mantık fonksiyonları tanımlayın |
| `definePreInstallLogicFunction` | Bir kurulum öncesi mantık işlevi tanımlayın (uygulama başına bir adet) |
| `definePostInstallLogicFunction` | Bir kurulum sonrası mantık işlevi tanımlayın (uygulama başına bir adet) |
| `defineFrontComponent` | Özel kullanıcı arayüzü için ön uç bileşenlerini tanımlayın |
| `defineRole` | Rol izinlerini ve nesne erişimini yapılandırın |
| `defineView` | Nesneler için kaydedilmiş görünümler tanımlayın |
| `defineNavigationMenuItem` | Kenar çubuğu gezinme bağlantılarını tanımlayın |
| `defineSkill` | Yapay zekâ ajanı yeteneklerini tanımlayın |
| `defineAgent` | Define AI agents |
| `definePageLayout` | Define custom page layouts |
| Fonksiyon | Amaç |
| -------------------------------- | ---------------------------------------------------------------------------------- |
| `defineApplication` | Uygulama meta verilerini yapılandırın (zorunlu, uygulama başına bir adet) |
| `defineObject` | Alanlara sahip özel nesneler tanımlayın |
| `defineField` | Mevcut nesneleri ek alanlarla genişletin veya bağımsız ilişki alanları tanımlayın. |
| `defineLogicFunction` | İşleyicilerle mantık fonksiyonları tanımlayın |
| `definePreInstallLogicFunction` | Bir kurulum öncesi mantık işlevi tanımlayın (uygulama başına bir adet) |
| `definePostInstallLogicFunction` | Bir kurulum sonrası mantık işlevi tanımlayın (uygulama başına bir adet) |
| `defineFrontComponent` | Özel kullanıcı arayüzü için ön uç bileşenlerini tanımlayın |
| `defineRole` | Rol izinlerini ve nesne erişimini yapılandırın |
| `defineView` | Nesneler için kaydedilmiş görünümler tanımlayın |
| `defineNavigationMenuItem` | Kenar çubuğu gezinme bağlantılarını tanımlayın |
| `defineSkill` | Yapay zekâ ajanı yeteneklerini tanımlayın |
| `defineAgent` | Yapay zekâ ajanlarını tanımlayın. |
| `definePageLayout` | Özel sayfa düzenlerini tanımlayın. |
Bu fonksiyonlar, derleme zamanında yapılandırmanızı doğrular ve IDE otomatik tamamlama ile tür güvenliği sağlar.
@@ -112,7 +112,7 @@ export default defineObject({
* `universalIdentifier` dağıtımlar arasında benzersiz ve kararlı olmalıdır.
* Her alan bir `name`, `type`, `label` ve kendi kararlı `universalIdentifier` değerini gerektirir.
* `fields` dizisi isteğe bağlıdır — özel alanlar olmadan da nesneler tanımlayabilirsiniz.
* You can scaffold new objects using `yarn twenty add`, which guides you through naming, fields, and relationships.
* `yarn twenty add` kullanarak, adlandırma, alanlar ve ilişkiler konusunda sizi yönlendirerek yeni nesneler oluşturabilirsiniz.
<Note>
**Temel alanlar otomatik olarak oluşturulur.** Özel bir nesne tanımladığınızda Twenty, standart alanları otomatik olarak ekler
@@ -124,7 +124,7 @@ ancak bu önerilmez.
### Mevcut nesneler üzerinde alanları tanımlama
Use `defineField()` to add fields to objects you don't own — such as standard Twenty objects (Person, Company, etc.) or objects from other apps. Unlike inline fields in `defineObject()`, standalone fields require an `objectUniversalIdentifier` to specify which object they extend:
Sahibi olmadığınız nesnelere alan eklemek için `defineField()` kullanın — standart Twenty nesneleri (Person, Company, vb.) gibi. veya diğer uygulamalardaki nesneler. `defineObject()` içindeki satır içi alanların aksine, bağımsız alanlar hangi nesneyi genişlettiklerini belirtmek için bir `objectUniversalIdentifier` gerektirir:
```typescript
// src/fields/company-loyalty-tier.field.ts
@@ -147,35 +147,35 @@ export default defineField({
Önemli noktalar:
* `objectUniversalIdentifier` identifies the target object. For standard objects, use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` exported from `twenty-sdk`.
* When defining fields inline in `defineObject()`, you do **not** need `objectUniversalIdentifier` — it's inherited from the parent object.
* `defineField()` is the only way to add fields to objects you didn't create with `defineObject()`.
* `objectUniversalIdentifier` hedef nesneyi tanımlar. Standart nesneler için, `twenty-sdk`'den dışa aktarılan `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS`'ı kullanın.
* Alanları `defineObject()` içinde satır içi tanımlarken, `objectUniversalIdentifier`'a ihtiyacınız yoktur — üst nesneden devralınır.
* `defineField()`, `defineObject()` ile oluşturmadığınız nesnelere alan eklemenin tek yoludur.
### İlişkiler
Relations connect objects together. In Twenty, relations are always **bidirectional** — you define both sides, and each side references the other.
İlişkiler nesneleri birbirine bağlar. Twenty'de ilişkiler her zaman **çift yönlüdür** — her iki tarafı da tanımlarsınız ve her taraf diğerine başvurur.
There are two relation types:
İki ilişki türü vardır:
| İlişki türü | Açıklama | Has foreign key? |
| ------------- | ------------------------------------------------------------- | ---------------------- |
| `MANY_TO_ONE` | Many records of this object point to one record of the target | Yes (`joinColumnName`) |
| `ONE_TO_MANY` | One record of this object has many records of the target | No (inverse side) |
| İlişki türü | Açıklama | Yabancı anahtar var mı? |
| ------------- | --------------------------------------------------------- | ----------------------- |
| `MANY_TO_ONE` | Bu nesnenin birçok kaydı, hedefin bir kaydını işaret eder | Evet (`joinColumnName`) |
| `ONE_TO_MANY` | Bu nesnenin bir kaydı, hedefin birçok kaydına sahiptir | Hayır (ters taraf) |
#### How relations work
#### İlişkiler nasıl çalışır
Every relation requires **two fields** that reference each other:
Her ilişki, birbirine referans veren iki alan gerektirir:
1. The **MANY_TO_ONE** side — lives on the object that holds the foreign key
2. The **ONE_TO_MANY** side — lives on the object that owns the collection
1. **MANY_TO_ONE** tarafı — yabancı anahtarı tutan nesne üzerinde bulunur
2. **ONE_TO_MANY** tarafı — koleksiyona sahip olan nesne üzerinde bulunur
Both fields use `FieldType.RELATION` and cross-reference each other via `relationTargetFieldMetadataUniversalIdentifier`.
Her iki alan da `FieldType.RELATION` kullanır ve `relationTargetFieldMetadataUniversalIdentifier` aracılığıyla birbirine karşılıklı referans verir.
#### Example: Post Card has many Recipients
#### Örnek: Posta Kartı'nın birçok Alıcısı vardır
Suppose a `PostCard` can be sent to many `PostCardRecipient` records. Each recipient belongs to exactly one post card.
Bir `PostCard`'ın birçok `PostCardRecipient` kaydına gönderilebildiğini varsayalım. Her alıcı tam olarak bir posta kartına aittir.
**Step 1: Define the ONE_TO_MANY side on PostCard** (the "one" side):
**Adım 1: PostCard üzerinde ONE_TO_MANY tarafını tanımlayın** ("bir" taraf):
```typescript
// src/fields/post-card-recipients-on-post-card.field.ts
@@ -203,7 +203,7 @@ export default defineField({
});
```
**Step 2: Define the MANY_TO_ONE side on PostCardRecipient** (the "many" side — holds the foreign key):
**Adım 2: PostCardRecipient üzerinde MANY_TO_ONE tarafını tanımlayın** ("çok" taraf — yabancı anahtarı tutar):
```typescript
// src/fields/post-card-on-post-card-recipient.field.ts
@@ -234,12 +234,12 @@ export default defineField({
```
<Note>
**Circular imports:** Both relation fields reference each other's `universalIdentifier`. To avoid circular import issues, export your field IDs as named constants from each file, and import them in the other file. The build system resolves these at compile time.
**Döngüsel içe aktarmalar:** Her iki ilişki alanı da birbirlerinin `universalIdentifier` değerine referans verir. Döngüsel içe aktarma sorunlarından kaçınmak için, alan kimliklerinizi her dosyadan adlandırılmış sabitler olarak dışa aktarın ve diğer dosyada içe aktarın. Derleme sistemi bunları derleme zamanında çözer.
</Note>
#### Relating to standard objects
#### Standart nesnelerle ilişkilendirme
To create a relation with a built-in Twenty object (Person, Company, etc.), use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS`:
Yerleşik bir Twenty nesnesiyle (Person, Company, vb.) ilişki oluşturmak için `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` kullanın:
```typescript
// src/fields/person-on-self-hosting-user.field.ts
@@ -274,20 +274,20 @@ export default defineField({
});
```
#### Relation field properties
#### İlişki alanı özellikleri
| Özellik | Zorunlu | Açıklama |
| ------------------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------- |
| `type` | Evet | Must be `FieldType.RELATION` |
| `relationTargetObjectMetadataUniversalIdentifier` | Evet | The `universalIdentifier` of the target object |
| `relationTargetFieldMetadataUniversalIdentifier` | Evet | The `universalIdentifier` of the matching field on the target object |
| `universalSettings.relationType` | Evet | `RelationType.MANY_TO_ONE` or `RelationType.ONE_TO_MANY` |
| `universalSettings.onDelete` | MANY_TO_ONE only | What happens when the referenced record is deleted: `CASCADE`, `SET_NULL`, `RESTRICT`, or `NO_ACTION` |
| `universalSettings.joinColumnName` | MANY_TO_ONE only | Database column name for the foreign key (e.g., `postCardId`) |
| Özellik | Zorunlu | Açıklama |
| ------------------------------------------------- | -------------------- | -------------------------------------------------------------------------------------------- |
| `type` | Evet | `FieldType.RELATION` olmalıdır |
| `relationTargetObjectMetadataUniversalIdentifier` | Evet | Hedef nesnenin `universalIdentifier` değeri |
| `relationTargetFieldMetadataUniversalIdentifier` | Evet | Hedef nesnedeki eşleşen alanın `universalIdentifier` değeri |
| `universalSettings.relationType` | Evet | `RelationType.MANY_TO_ONE` veya `RelationType.ONE_TO_MANY` |
| `universalSettings.onDelete` | Yalnızca MANY_TO_ONE | Başvurulan kayıt silindiğinde ne olacağı: `CASCADE`, `SET_NULL`, `RESTRICT` veya `NO_ACTION` |
| `universalSettings.joinColumnName` | Yalnızca MANY_TO_ONE | Yabancı anahtar için veritabanı sütun adı (örn. `postCardId`) |
#### Inline relation fields in defineObject
#### defineObject içinde satır içi ilişki alanları
You can also define relation fields directly inside `defineObject()`. In that case, omit `objectUniversalIdentifier` — it's inherited from the parent object:
İlişki alanlarını doğrudan `defineObject()` içinde de tanımlayabilirsiniz. Bu durumda, `objectUniversalIdentifier`'ı atlayın — üst nesneden devralınır:
```typescript
export default defineObject({
@@ -354,21 +354,21 @@ Notlar:
* `defaultRoleUniversalIdentifier`, rol dosyasıyla eşleşmelidir (aşağıya bakın).
* Kurulum öncesi ve kurulum sonrası işlevler, manifest oluşturma sırasında otomatik olarak algılanır. Bkz. [Kurulum öncesi işlevler](#pre-install-functions) ve [Kurulum sonrası işlevler](#post-install-functions).
#### Marketplace metadata
#### Pazaryeri meta verileri
If you plan to [publish your app](/l/tr/developers/extend/apps/publishing), these optional fields control how your app appears in the marketplace:
Eğer [uygulamanızı yayımlamayı](/l/tr/developers/extend/apps/publishing) planlıyorsanız, bu isteğe bağlı alanlar uygulamanızın pazaryerinde nasıl görüneceğini kontrol eder:
| Alan | Açıklama |
| ------------------ | --------------------------------------------------- |
| `author` | Author or company name |
| `category` | App category for marketplace filtering |
| `logoUrl` | Path to your app logo (relative to `./assets/`) |
| `screenshots` | Array of screenshot paths (relative to `./assets/`) |
| `aboutDescription` | Longer markdown description for the "About" tab |
| `websiteUrl` | Link to your website |
| `termsUrl` | Link to terms of service |
| `emailSupport` | Support email address |
| `issueReportUrl` | Link to issue tracker |
| Alan | Açıklama |
| ------------------ | ------------------------------------------------------------- |
| `author` | Yazar veya şirket adı |
| `category` | Pazaryerinde filtreleme için uygulama kategorisi |
| `logoUrl` | Uygulama logonuzun yolu (`./assets/` dizinine göre) |
| `screenshots` | Ekran görüntüsü yollarının dizisi (`./assets/` dizinine göre) |
| `aboutDescription` | "Hakkında" sekmesi için daha uzun bir markdown açıklaması |
| `websiteUrl` | Web sitenize bağlantı |
| `termsUrl` | Hizmet Koşulları'na bağlantı |
| `emailSupport` | Destek e-posta adresi |
| `issueReportUrl` | Sorun izleyicisine bağlantı |
#### Roller ve izinler
@@ -376,7 +376,7 @@ Uygulamalar, çalışma alanınızdaki nesneler ve eylemler üzerindeki izinleri
* `TWENTY_API_KEY` olarak enjekte edilen çalışma zamanı API anahtarı bu varsayılan fonksiyon rolünden türetilir.
* Türlendirilmiş istemci, o role tanınan izinlerle sınırlandırılır.
* Follow least-privilege: create a dedicated role with only the permissions your functions need, then reference its universal identifier.
* En az ayrıcalık ilkesini izleyin: Yalnızca fonksiyonlarınızın ihtiyaç duyduğu izinlere sahip özel bir rol oluşturun ve ardından evrensel tanımlayıcısına referans verin.
##### Varsayılan fonksiyon rolü (*.role.ts)
@@ -429,7 +429,7 @@ Bu rolün `universalIdentifier` değeri daha sonra `application-config.ts` için
Notlar:
* Start from the scaffolded role, then progressively restrict it following least-privilege.
* Oluşturulan rolden başlayın ve en az ayrıcalık ilkesini izleyerek bunu aşamalı olarak kısıtlayın.
* `objectPermissions` ve `fieldPermissions` değerlerini, fonksiyonlarınızın ihtiyaç duyduğu nesneler/alanlarla değiştirin.
* `permissionFlags`, platform düzeyindeki yeteneklere erişimi kontrol eder. Minimumda tutun; yalnızca ihtiyacınız olanları ekleyin.
* Çalışan bir örneği Hello World uygulamasında görün: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
@@ -543,7 +543,7 @@ yarn twenty exec --preInstall
* Uygulama başına yalnızca bir kurulum öncesi işlevine izin verilir. Birden fazla tespit edilirse manifest oluşturma hataya düşer.
* İşlevin `universalIdentifier` değeri, oluşturma sırasında uygulama manifestinde otomatik olarak `preInstallLogicFunctionUniversalIdentifier` olarak ayarlanır — `defineApplication()` içinde buna atıfta bulunmanıza gerek yoktur.
* Varsayılan zaman aşımı, daha uzun hazırlık görevlerine izin vermek için 300 saniye (5 dakika) olarak ayarlanmıştır.
* Pre-install functions do not need triggers — they are invoked by the platform before installation or manually via `exec --preInstall`.
* Kurulum öncesi işlevlerin tetikleyicilere ihtiyacı yoktur — kurulumdan önce platform tarafından veya `exec --preInstall` aracılığıyla manuel olarak çağrılırlar.
### Kurulum sonrası işlevler
@@ -581,7 +581,7 @@ yarn twenty exec --postInstall
* Uygulama başına yalnızca bir kurulum sonrası işlevine izin verilir. Birden fazla tespit edilirse manifest oluşturma hataya düşer.
* İşlevin `universalIdentifier` değeri, oluşturma sırasında uygulama manifestinde otomatik olarak `postInstallLogicFunctionUniversalIdentifier` olarak ayarlanır — `defineApplication()` içinde buna atıfta bulunmanıza gerek yoktur.
* Varsayılan zaman aşımı, veri tohumlama gibi daha uzun kurulum görevlerine izin vermek için 300 saniye (5 dakika) olarak ayarlanmıştır.
* Post-install functions do not need triggers — they are invoked by the platform during installation or manually via `exec --postInstall`.
* Kurulum sonrası işlevlerin tetikleyicilere ihtiyacı yoktur — kurulum sırasında platform tarafından veya `exec --postInstall` aracılığıyla manuel olarak çağrılırlar.
### Rota tetikleyicisi yükü
@@ -625,15 +625,15 @@ const handler = async (event: RoutePayload) => {
`RoutePayload` türünün yapısı şu şekildedir:
| Özellik | Tür | Açıklama |
| ---------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | HTTP başlıkları (`forwardedRequestHeaders` içinde listelenenlerle sınırlı) |
| `queryStringParameters` | `Record<string, string \| undefined>` | Sorgu dizesi parametreleri (birden çok değer virgülle birleştirilir) |
| `pathParameters` | `Record<string, string \| undefined>` | Path parameters extracted from the route pattern (e.g., `/users/:id` -> `{ id: '123' }`) |
| `body` | `object \| null` | Ayrıştırılmış istek gövdesi (JSON) |
| `isBase64Encoded` | `boolean` | Gövdenin base64 ile kodlanıp kodlanmadığı |
| `requestContext.http.method` | `string` | HTTP yöntemi (GET, POST, PUT, PATCH, DELETE) |
| `requestContext.http.path` | `string` | Ham istek yolu |
| Özellik | Tür | Açıklama |
| ---------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | HTTP başlıkları (`forwardedRequestHeaders` içinde listelenenlerle sınırlı) |
| `queryStringParameters` | `Record<string, string \| undefined>` | Sorgu dizesi parametreleri (birden çok değer virgülle birleştirilir) |
| `pathParameters` | `Record<string, string \| undefined>` | Rota deseninden çıkarılan yol parametreleri (örn., `/users/:id` -> `{ id: '123' }`) |
| `body` | `object \| null` | Ayrıştırılmış istek gövdesi (JSON) |
| `isBase64Encoded` | `boolean` | Gövdenin base64 ile kodlanıp kodlanmadığı |
| `requestContext.http.method` | `string` | HTTP yöntemi (GET, POST, PUT, PATCH, DELETE) |
| `requestContext.http.path` | `string` | Ham istek yolu |
### HTTP başlıklarını iletme
@@ -675,7 +675,7 @@ const handler = async (event: RoutePayload) => {
Yeni fonksiyonları iki şekilde oluşturabilirsiniz:
* **Scaffolded**: Run `yarn twenty add` and choose the option to add a new logic function. Bu, bir işleyici ve yapılandırma içeren bir başlangıç dosyası oluşturur.
* **Şablondan**: `yarn twenty add` çalıştırın ve yeni bir mantık fonksiyonu ekleme seçeneğini seçin. Bu, bir işleyici ve yapılandırma içeren bir başlangıç dosyası oluşturur.
* **Manuel**: Yeni bir `*.logic-function.ts` dosyası oluşturun ve aynı deseni izleyerek `defineLogicFunction()` kullanın.
### Bir mantık işlevini araç olarak işaretleme
@@ -776,7 +776,7 @@ export default defineFrontComponent({
Yeni ön uç bileşenlerini iki şekilde oluşturabilirsiniz:
* **Scaffolded**: Run `yarn twenty add` and choose the option to add a new front component.
* **Şablondan**: `yarn twenty add` çalıştırın ve yeni bir ön uç bileşeni ekleme seçeneğini seçin.
* **Manuel**: Aynı deseni izleyerek yeni bir `.tsx` dosyası oluşturun ve `defineFrontComponent()` kullanın.
### Beceriler
@@ -811,21 +811,21 @@ export default defineSkill({
Yeni yetenekleri iki şekilde oluşturabilirsiniz:
* **Scaffolded**: Run `yarn twenty add` and choose the option to add a new skill.
* **Şablondan**: `yarn twenty add` çalıştırın ve yeni bir yetenek ekleme seçeneğini seçin.
* **Manuel**: Yeni bir dosya oluşturun ve aynı deseni izleyerek `defineSkill()` kullanın.
### Typed API clients (`twenty-client-sdk`)
### Tipli API istemcileri (`twenty-client-sdk`)
The `twenty-client-sdk` package provides two typed GraphQL clients for interacting with the Twenty API from your logic functions and front components:
`twenty-client-sdk` paketi, mantık fonksiyonlarınızdan ve ön uç bileşenlerinizden Twenty API ile etkileşim kurmak için iki tipli GraphQL istemcisi sağlar:
| İstemci | İçe Aktar | Endpoint | Generated? |
| ------------------- | ---------------------------- | ---------------------------------------------- | ---------------------- |
| `CoreApiClient` | `twenty-client-sdk/core` | `/graphql` — workspace data (records, objects) | Yes, at dev/build time |
| `MetadataApiClient` | `twenty-client-sdk/metadata` | `/metadata` — workspace config, file uploads | No, ships pre-built |
| İstemci | İçe Aktar | Uç nokta | Oluşturuldu mu? |
| ------------------- | ---------------------------- | ------------------------------------------------------------- | --------------------------------------- |
| `CoreApiClient` | `twenty-client-sdk/core` | `/graphql` — çalışma alanı verileri (kayıtlar, nesneler) | Evet, geliştirme/derleme zamanında |
| `MetadataApiClient` | `twenty-client-sdk/metadata` | `/metadata` — çalışma alanı yapılandırması, dosya yüklemeleri | Hayır, önceden hazırlanmış olarak gelir |
#### CoreApiClient
`CoreApiClient` is the main client for querying and mutating workspace data. It is **generated from your workspace schema** during `yarn twenty dev` or `yarn twenty build`, so it's fully typed to match your objects and fields.
`CoreApiClient`, çalışma alanı verilerini sorgulamak ve değiştirmek için ana istemcidir. `yarn twenty dev` veya `yarn twenty build` sırasında çalışma alanı şemanızdan oluşturulur; bu nedenle nesnelerinize ve alanlarınıza uyacak şekilde tamamen tiplendirilmiştir.
```typescript
import { CoreApiClient } from 'twenty-client-sdk/core';
@@ -859,15 +859,15 @@ const { createCompany } = await client.mutation({
});
```
The client uses a selection-set syntax: pass `true` to include a field, use `__args` for arguments, and nest objects for relations. You get full autocompletion and type checking based on your workspace schema.
İstemci bir seçim kümesi sözdizimi kullanır: Bir alanı dahil etmek için `true` geçin, bağımsız değişkenler için `__args` kullanın ve ilişkiler için nesneleri iç içe yerleştirin. Çalışma alanı şemanıza göre tam otomatik tamamlama ve tip denetimi elde edersiniz.
<Note>
**CoreApiClient is generated at dev/build time.** If you try to 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, generates a typed client using `@genql/cli`, writes the generated sources to `node_modules/twenty-client-sdk/dist/core/generated/`, and replaces the stubs in `node_modules/twenty-client-sdk/dist/core.mjs` and `node_modules/twenty-client-sdk/dist/core.cjs`.
**CoreApiClient geliştirme/derleme zamanında oluşturulur.** Bunu önce `yarn twenty dev` veya `yarn twenty build` çalıştırmadan kullanmaya çalışırsanız, hata verir. Oluşturma otomatik olarak gerçekleşir — CLI, çalışma alanınızın GraphQL şemasını inceler, `@genql/cli` kullanarak tipli bir istemci üretir, üretilen kaynakları `node_modules/twenty-client-sdk/dist/core/generated/` dizinine yazar ve `node_modules/twenty-client-sdk/dist/core.mjs` ile `node_modules/twenty-client-sdk/dist/core.cjs` içindeki taslakları değiştirir.
</Note>
#### Using CoreSchema for type annotations
#### Tür açıklamalarıin CoreSchema'yı kullanma
`CoreSchema` provides TypeScript types matching your workspace objects, useful for typing component state or function parameters:
`CoreSchema`, çalışma alanı nesnelerinize uyan TypeScript türleri sağlar; bileşen durumunu veya işlev parametrelerini tiplemek için kullanışlıdır:
```typescript
import { CoreApiClient, CoreSchema } from 'twenty-client-sdk/core';
@@ -890,7 +890,7 @@ setCompany(result.company);
#### MetadataApiClient
`MetadataApiClient` ships pre-built with the SDK (no generation required). It queries the `/metadata` endpoint for workspace configuration, applications, and file uploads:
`MetadataApiClient`, SDK ile birlikte önceden hazırlanmış olarak gelir (oluşturma gerektirmez). Çalışma alanı yapılandırması, uygulamalar ve dosya yüklemeleri için `/metadata` uç noktasını sorgular:
```typescript
import { MetadataApiClient } from 'twenty-client-sdk/metadata';
@@ -912,18 +912,18 @@ const { findManyApplications } = await metadataClient.query({
});
```
#### Runtime credentials
#### Çalışma zamanı kimlik bilgileri
When your code runs on Twenty (logic functions or front components), the platform injects credentials as environment variables:
Kodunuz Twenty üzerinde çalıştığında (mantık işlevleri veya ön uç bileşenleri), platform kimlik bilgilerini ortam değişkenleri olarak enjekte eder:
* `TWENTY_API_URL` — Base URL of the Twenty API
* `TWENTY_API_KEY` — Short-lived key scoped to your application's default function role
* `TWENTY_API_URL` — Twenty API'nin temel URL'si
* `TWENTY_API_KEY` — Uygulamanızın varsayılan fonksiyon rolü kapsamına sahip kısa ömürlü anahtar
You do **not** need to pass these to the clients — they read from `process.env` automatically. The API key's permissions are determined by the role referenced in `defaultRoleUniversalIdentifier` in your `application-config.ts`.
Bunları istemcilere iletmeniz gerekmez — otomatik olarak `process.env`'den okurlar. API anahtarının izinleri, `application-config.ts` içinde `defaultRoleUniversalIdentifier` ile referans verilen role göre belirlenir.
#### Dosya yükleme
`MetadataApiClient` includes an `uploadFile` method for attaching files to file-type fields. It implements the [GraphQL multipart request specification](https://github.com/jaydenseric/graphql-multipart-request-spec):
`MetadataApiClient`, dosya türü alanlara dosya eklemek için bir `uploadFile` yöntemi içerir. [GraphQL çok parçalı istek spesifikasyonunu](https://github.com/jaydenseric/graphql-multipart-request-spec) uygular:
```typescript
import { MetadataApiClient } from 'twenty-client-sdk/metadata';
@@ -953,7 +953,7 @@ console.log(uploadedFile);
Önemli noktalar:
* Uses the field's `universalIdentifier` (not its workspace-specific ID), so your upload code works across any workspace where your app is installed.
* Alan için `universalIdentifier` kullanır (çalışma alanına özgü kimliği değil), böylece yükleme kodunuz uygulamanızın yüklü olduğu herhangi bir çalışma alanında çalışır.
* Döndürülen `url`, yüklenen dosyaya erişmek için kullanabileceğiniz imzalı bir URL'dir.
### Hello World örneği