i18n - docs translations (#19234)
Created by Github action Co-authored-by: github-actions <github-actions@twenty.com>
This commit is contained in:
committed by
GitHub
parent
f3e2e00e79
commit
1622c87b7a
@@ -4,24 +4,24 @@ description: Defina objetos, funções de lógica, componentes de front-end e mu
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Apps are currently in alpha. The feature works but is still evolving.
|
||||
Os aplicativos estão atualmente em testes alfa. O recurso é funcional, mas ainda está evoluindo.
|
||||
</Warning>
|
||||
|
||||
The `twenty-sdk` package provides typed building blocks to create your app. This page covers every entity type and API client available in the SDK.
|
||||
O pacote `twenty-sdk` fornece blocos de construção tipados para criar seu app. Esta página cobre todos os tipos de entidade e clientes de API disponíveis no SDK.
|
||||
|
||||
## DefineEntity functions
|
||||
## Funções DefineEntity
|
||||
|
||||
The SDK provides functions to define your app entities. You must use `export default defineEntity({...})` for the SDK to detect your entities. Essas funções validam sua configuração em tempo de compilação e oferecem autocompletar na IDE e segurança de tipos.
|
||||
O SDK fornece funções para definir as entidades do seu app. Você deve usar `export default defineEntity({...})` para que o SDK detecte suas entidades. Essas funções validam sua configuração em tempo de compilação e oferecem autocompletar na IDE e segurança de tipos.
|
||||
|
||||
<Note>
|
||||
**File organization is up to you.**
|
||||
Entity detection is AST-based — the SDK finds `export default defineEntity(...)` calls regardless of where the file lives. Grouping files by type (e.g., `logic-functions/`, `roles/`) is just a convention, not a requirement.
|
||||
**A organização de arquivos fica a seu critério.**
|
||||
A detecção de entidades é baseada em AST — o SDK encontra chamadas a `export default defineEntity(...)` independentemente de onde o arquivo esteja. Agrupar arquivos por tipo (por exemplo, `logic-functions/`, `roles/`) é apenas uma convenção, não um requisito.
|
||||
</Note>
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="defineRole" description="Configura permissões de papéis e acesso a objetos">
|
||||
|
||||
Roles encapsulate permissions on your workspace's objects and actions.
|
||||
Papéis encapsulam permissões sobre os objetos e ações do seu espaço de trabalho.
|
||||
|
||||
```ts restricted-company-role.ts
|
||||
import {
|
||||
@@ -69,12 +69,12 @@ export default defineRole({
|
||||
</Accordion>
|
||||
<Accordion title="defineApplication" description="Configurar metadados do aplicativo (obrigatório, um por app)">
|
||||
|
||||
Every app must have exactly one `defineApplication` call that describes:
|
||||
Todo app deve ter exatamente uma chamada a `defineApplication` que descreve:
|
||||
|
||||
* **Identity**: identifiers, display name, and description.
|
||||
* **Permissions**: which role its functions and front components use.
|
||||
* **(Optional) Variables**: key–value pairs exposed to your functions as environment variables.
|
||||
* **(Optional) Pre-install / post-install functions**: logic functions that run before or after installation.
|
||||
* **Identidade**: identificadores, nome de exibição e descrição.
|
||||
* **Permissões**: qual papel é usado por suas funções e componentes de front-end.
|
||||
* **Variáveis (opcional)**: pares chave–valor expostos às suas funções como variáveis de ambiente.
|
||||
* **(Opcional) Funções de pré-instalação/pós-instalação**: funções de lógica que são executadas antes ou depois da instalação.
|
||||
|
||||
```ts src/application-config.ts
|
||||
import { defineApplication } from 'twenty-sdk';
|
||||
@@ -98,21 +98,21 @@ export default defineApplication({
|
||||
```
|
||||
|
||||
Notas:
|
||||
* `universalIdentifier` fields are deterministic IDs you own. Generate them once and keep them stable across syncs.
|
||||
* `applicationVariables` become environment variables for your functions and front components (e.g., `DEFAULT_RECIPIENT_NAME` is available as `process.env.DEFAULT_RECIPIENT_NAME`).
|
||||
* `defaultRoleUniversalIdentifier` must reference a role defined with `defineRole()` (see above).
|
||||
* Pre-install and post-install functions are detected automatically during the manifest build — you do not need to reference them in `defineApplication()`.
|
||||
* Os campos `universalIdentifier` são IDs determinísticos que você controla. Gere-os uma vez e mantenha-os estáveis entre sincronizações.
|
||||
* `applicationVariables` tornam-se variáveis de ambiente para suas funções e componentes de front-end (por exemplo, `DEFAULT_RECIPIENT_NAME` fica disponível como `process.env.DEFAULT_RECIPIENT_NAME`).
|
||||
* `defaultRoleUniversalIdentifier` deve fazer referência a um papel definido com `defineRole()` (veja acima).
|
||||
* As funções de pré-instalação e pós-instalação são detectadas automaticamente durante a construção do manifesto — você não precisa referenciá-las em `defineApplication()`.
|
||||
|
||||
#### Metadados do Marketplace
|
||||
|
||||
If you plan to [publish your app](/l/pt/developers/extend/apps/publishing), these optional fields control how it appears in the marketplace:
|
||||
Se você planeja [publicar seu app](/l/pt/developers/extend/apps/publishing), estes campos opcionais controlam como seu app aparece no marketplace:
|
||||
|
||||
| Campo | Descrição |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `autor` | Nome do autor ou da empresa |
|
||||
| `categoria` | Categoria do app para filtragem no marketplace |
|
||||
| `logoUrl` | Path to your app logo (e.g., `public/logo.png`) |
|
||||
| `screenshots` | Array of screenshot paths (e.g., `public/screenshot-1.png`) |
|
||||
| `logoUrl` | Caminho para o logo do seu app (por exemplo, `public/logo.png`) |
|
||||
| `screenshots` | Array de caminhos de capturas de tela (por exemplo, `public/screenshot-1.png`) |
|
||||
| `aboutDescription` | Descrição em markdown mais longa para a aba "Sobre". Se omitido, o marketplace usa o `README.md` do pacote no npm |
|
||||
| `websiteUrl` | Link para seu site |
|
||||
| `termsUrl` | Link para os Termos de Serviço |
|
||||
@@ -121,15 +121,15 @@ If you plan to [publish your app](/l/pt/developers/extend/apps/publishing), thes
|
||||
|
||||
#### Papéis e permissões
|
||||
|
||||
The `defaultRoleUniversalIdentifier` in `application-config.ts` designates the default role used by your app's logic functions and front components. See `defineRole` above for details.
|
||||
O campo `defaultRoleUniversalIdentifier` em `application-config.ts` designa o papel padrão usado pelas funções de lógica e pelos componentes de front-end do seu app. Veja `defineRole` acima para detalhes.
|
||||
|
||||
* The runtime token injected as `TWENTY_APP_ACCESS_TOKEN` is derived from this role.
|
||||
* The typed client is restricted to the permissions granted to that role.
|
||||
* Follow least-privilege: create a dedicated role with only the permissions your functions need.
|
||||
* O token em tempo de execução injetado como `TWENTY_APP_ACCESS_TOKEN` é derivado desse papel.
|
||||
* O cliente tipado é restrito às permissões concedidas a esse papel.
|
||||
* Siga o princípio do menor privilégio: crie um papel dedicado com apenas as permissões de que suas funções precisam.
|
||||
|
||||
##### Default function role
|
||||
##### Papel de função padrão
|
||||
|
||||
When you scaffold a new app, the CLI creates a default role file:
|
||||
Ao criar um novo app com o scaffold, a CLI cria um arquivo de papel padrão:
|
||||
|
||||
```ts src/roles/default-role.ts
|
||||
import { defineRole, PermissionFlag } from 'twenty-sdk';
|
||||
@@ -155,16 +155,16 @@ export default defineRole({
|
||||
});
|
||||
```
|
||||
|
||||
This role's `universalIdentifier` is referenced in `application-config.ts` as `defaultRoleUniversalIdentifier`:
|
||||
O `universalIdentifier` desse papel é referenciado em `application-config.ts` como `defaultRoleUniversalIdentifier`:
|
||||
|
||||
* **\*.role.ts** defines what the role can do.
|
||||
* **\*.role.ts** define o que o papel pode fazer.
|
||||
* **application-config.ts** aponta para esse papel para que suas funções herdem suas permissões.
|
||||
|
||||
Notas:
|
||||
* Comece pelo papel gerado pelo scaffold e depois restrinja-o progressivamente seguindo o princípio do menor privilégio.
|
||||
* Replace `objectPermissions` and `fieldPermissions` with the objects and fields your functions actually need.
|
||||
* `permissionFlags` controlam o acesso a recursos em nível de plataforma. Keep them minimal.
|
||||
* See a working example: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
|
||||
* Substitua `objectPermissions` e `fieldPermissions` pelos objetos e campos de que suas funções realmente precisam.
|
||||
* `permissionFlags` controlam o acesso a recursos em nível de plataforma. Mantenha-os no mínimo necessário.
|
||||
* Veja um exemplo funcional: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="defineObject" description="Define objetos personalizados com campos">
|
||||
@@ -256,7 +256,7 @@ mas isso não é recomendado.
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="defineField — Standard fields" description="Estender objetos existentes com campos adicionais">
|
||||
<Accordion title="defineField — Campos padrão" description="Estender objetos existentes com campos adicionais">
|
||||
|
||||
Use `defineField()` para adicionar campos a objetos que não são seus — como objetos padrão do Twenty (Person, Company, etc.). ou a objetos de outros apps. Ao contrário dos campos inline em `defineObject()`, os campos independentes exigem um `objectUniversalIdentifier` para especificar qual objeto eles estendem:
|
||||
|
||||
@@ -284,7 +284,7 @@ Pontos-chave:
|
||||
* `defineField()` é a única forma de adicionar campos a objetos que você não criou com `defineObject()`.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="defineField — Relation fields" description="Connect objects together with bidirectional relations">
|
||||
<Accordion title="defineField — Campos de relação" description="Conecte objetos com relações bidirecionais">
|
||||
|
||||
As relações conectam objetos entre si. No Twenty, as relações são sempre **bidirecionais** — você define ambos os lados, e cada lado faz referência ao outro.
|
||||
|
||||
@@ -443,7 +443,7 @@ export default defineObject({
|
||||
});
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="defineLogicFunction" description="Define logic functions and their triggers">
|
||||
<Accordion title="defineLogicFunction" description="Defina funções de lógica e seus gatilhos">
|
||||
|
||||
Cada arquivo de função usa `defineLogicFunction()` para exportar uma configuração com um handler e gatilhos opcionais.
|
||||
|
||||
@@ -487,15 +487,15 @@ export default defineLogicFunction({
|
||||
});
|
||||
```
|
||||
|
||||
Available trigger types:
|
||||
* **httpRoute**: Exposes your function on an HTTP path and method **under the `/s/` endpoint**:
|
||||
> e.g. `path: '/post-card/create'` is callable at `https://your-twenty-server.com/s/post-card/create`
|
||||
Tipos de gatilho disponíveis:
|
||||
* **httpRoute**: Expõe sua função em um caminho e método HTTP **no endpoint `/s/`**:
|
||||
> por exemplo, `path: '/post-card/create'` é acessível em `https://your-twenty-server.com/s/post-card/create`
|
||||
* **cron**: Executa sua função em um agendamento usando uma expressão CRON.
|
||||
* **databaseEvent**: Executa em eventos do ciclo de vida de objetos do espaço de trabalho. Quando a operação do evento é `updated`, campos específicos a serem observados podem ser especificados no array `updatedFields`. Se deixar indefinido ou vazio, qualquer atualização acionará a função.
|
||||
> e.g. `person.updated`, `*.created`, `company.*`
|
||||
> por exemplo, `person.updated`, `*.created`, `company.*`
|
||||
|
||||
<Note>
|
||||
You can also manually execute a function using the CLI:
|
||||
Você também pode executar manualmente uma função usando a CLI:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty exec -n create-new-post-card -p '{"key": "value"}'
|
||||
@@ -505,7 +505,7 @@ yarn twenty exec -n create-new-post-card -p '{"key": "value"}'
|
||||
yarn twenty exec -y e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf
|
||||
```
|
||||
|
||||
You can watch logs with:
|
||||
Você pode acompanhar os logs com:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty logs
|
||||
@@ -514,9 +514,8 @@ yarn twenty logs
|
||||
|
||||
#### Payload de gatilho de rota
|
||||
|
||||
When a route trigger invokes your logic function, it receives a `RoutePayload` object that follows the
|
||||
[AWS HTTP API v2 format](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html).
|
||||
Import the `RoutePayload` type from `twenty-sdk`:
|
||||
Quando um gatilho de rota invoca sua função de lógica, ela recebe um objeto `RoutePayload` que segue o [formato HTTP API v2 da AWS](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html).
|
||||
Importe o tipo `RoutePayload` de `twenty-sdk`:
|
||||
|
||||
```ts
|
||||
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';
|
||||
@@ -533,9 +532,9 @@ O tipo `RoutePayload` tem a seguinte estrutura:
|
||||
|
||||
| Propriedade | Tipo | Descrição | Exemplo |
|
||||
| ---------------------------- | ------------------------------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
||||
| `headers` | `Record<string, string \| undefined>` | Cabeçalhos HTTP (apenas aqueles listados em `forwardedRequestHeaders`) | see section below |
|
||||
| `headers` | `Record<string, string \| undefined>` | Cabeçalhos HTTP (apenas aqueles listados em `forwardedRequestHeaders`) | veja a seção abaixo |
|
||||
| `queryStringParameters` | `Record<string, string \| undefined>` | Parâmetros de query string (valores múltiplos unidos por vírgulas) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
|
||||
| `pathParameters` | `Record<string, string \| undefined>` | Path parameters extracted from the route pattern | `/users/:id`, `/users/123` -> `{ id: '123' }` |
|
||||
| `pathParameters` | `Record<string, string \| undefined>` | Parâmetros de caminho extraídos do padrão de rota | `/users/:id`, `/users/123` -> `{ id: '123' }` |
|
||||
| `body` | `object \| null` | Corpo da requisição analisado (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
|
||||
| `isBase64Encoded` | `boolean` | Se o corpo está codificado em base64 | |
|
||||
| `requestContext.http.method` | `string` | Método HTTP (GET, POST, PUT, PATCH, DELETE) | |
|
||||
@@ -545,7 +544,7 @@ O tipo `RoutePayload` tem a seguinte estrutura:
|
||||
#### forwardedRequestHeaders
|
||||
|
||||
Por padrão, os cabeçalhos HTTP das requisições recebidas **não** são repassados para sua função de lógica por motivos de segurança.
|
||||
To access specific headers, list them in the `forwardedRequestHeaders` array:
|
||||
Para acessar cabeçalhos específicos, liste-os explicitamente no array `forwardedRequestHeaders`:
|
||||
|
||||
```ts
|
||||
export default defineLogicFunction({
|
||||
@@ -561,7 +560,7 @@ export default defineLogicFunction({
|
||||
});
|
||||
```
|
||||
|
||||
In your handler, access the forwarded headers like this:
|
||||
No seu handler, acesse os cabeçalhos encaminhados assim:
|
||||
|
||||
```ts
|
||||
const handler = async (event: RoutePayload) => {
|
||||
@@ -574,14 +573,14 @@ const handler = async (event: RoutePayload) => {
|
||||
```
|
||||
|
||||
<Note>
|
||||
Os nomes dos cabeçalhos são normalizados para minúsculas. Access them using lowercase keys (e.g., `event.headers['content-type']`).
|
||||
Os nomes dos cabeçalhos são normalizados para minúsculas. Acesse-os usando chaves em minúsculas (por exemplo, `event.headers['content-type']`).
|
||||
</Note>
|
||||
|
||||
#### Exposing a function as a tool
|
||||
#### Expor uma função como ferramenta
|
||||
|
||||
Funções lógicas podem ser expostas como **ferramentas** para agentes de IA e fluxos de trabalho. When marked as a tool, a function becomes discoverable by Twenty's AI features and can be used in workflow automations.
|
||||
Funções lógicas podem ser expostas como **ferramentas** para agentes de IA e fluxos de trabalho. Quando marcada como ferramenta, uma função fica detectável pelos recursos de IA do Twenty e pode ser usada em automações de fluxos de trabalho.
|
||||
|
||||
To mark a logic function as a tool, set `isTool: true`:
|
||||
Para marcar uma função de lógica como ferramenta, defina `isTool: true`:
|
||||
|
||||
```ts src/logic-functions/enrich-company.logic-function.ts
|
||||
import { defineLogicFunction } from 'twenty-sdk';
|
||||
@@ -617,8 +616,8 @@ export default defineLogicFunction({
|
||||
|
||||
Pontos-chave:
|
||||
|
||||
* You can combine `isTool` with triggers — a function can be both a tool (callable by AI agents) and triggered by events at the same time.
|
||||
* **`toolInputSchema`** (optional): A JSON Schema object describing the parameters your function accepts. The schema is computed automatically from source code static analysis, but you can set it explicitly:
|
||||
* Você pode combinar `isTool` com gatilhos — uma função pode ser ao mesmo tempo uma ferramenta (chamável por agentes de IA) e acionada por eventos.
|
||||
* **`toolInputSchema`** (opcional): Um objeto JSON Schema que descreve os parâmetros que sua função aceita. O schema é calculado automaticamente a partir da análise estática do código-fonte, mas você pode defini-lo explicitamente:
|
||||
|
||||
```ts
|
||||
export default defineLogicFunction({
|
||||
@@ -715,11 +714,11 @@ Pontos-chave:
|
||||
</Accordion>
|
||||
<Accordion title="defineFrontComponent" description="Definir componentes de front-end para UI personalizada">
|
||||
|
||||
Front components are React components that render directly inside Twenty's UI. They run in an **isolated Web Worker** using Remote DOM — your code is sandboxed but renders natively in the page, not in an iframe.
|
||||
Componentes de front-end são componentes React que renderizam diretamente dentro da UI do Twenty. Eles são executados em um Web Worker isolado usando Remote DOM — seu código é sandboxed, mas renderiza nativamente na página, não em um iframe.
|
||||
|
||||
#### Basic example
|
||||
#### Exemplo básico
|
||||
|
||||
The quickest way to see a front component in action is to register it as a **command**. Adding a `command` field with `isPinned: true` makes it appear as a quick-action button in the top-right corner of the page — no page layout needed:
|
||||
A maneira mais rápida de ver um componente de front-end em ação é registrá-lo como um **comando**. Adicionar um campo `command` com `isPinned: true` faz com que ele apareça como um botão de ação rápida no canto superior direito da página — não é necessário layout de página:
|
||||
|
||||
```tsx src/front-components/hello-world.tsx
|
||||
import { defineFrontComponent } from 'twenty-sdk';
|
||||
@@ -749,24 +748,24 @@ export default defineFrontComponent({
|
||||
});
|
||||
```
|
||||
|
||||
After syncing with `yarn twenty dev`, the quick action appears in the top-right corner of the page:
|
||||
Após sincronizar com `yarn twenty dev`, a ação rápida aparece no canto superior direito da página:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Quick action button in the top-right corner" />
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Botão de ação rápida no canto superior direito" />
|
||||
</div>
|
||||
|
||||
Click it to render the component inline.
|
||||
Clique nele para renderizar o componente inline.
|
||||
|
||||
{/* TODO: add screenshot of the rendered front component */}
|
||||
|
||||
#### Configuration fields
|
||||
#### Campos de configuração
|
||||
|
||||
| Campo | Obrigatório | Descrição |
|
||||
| --------------------- | ----------- | ----------------------------------------------------------------------------------- |
|
||||
| `universalIdentifier` | Sim | Stable unique ID for this component |
|
||||
| `component` | Sim | A React component function |
|
||||
| `name` | Não | Display name |
|
||||
| `description` | Não | Description of what the component does |
|
||||
| `universalIdentifier` | Sim | ID único e estável para este componente |
|
||||
| `component` | Sim | Uma função de componente React |
|
||||
| `name` | Não | Nome de Exibição |
|
||||
| `description` | Não | Descrição do que o componente faz |
|
||||
| `isHeadless` | Não | Set to `true` if the component has no visible UI (see below) |
|
||||
| `command` | Não | Register the component as a command (see [command options](#command-options) below) |
|
||||
|
||||
|
||||
@@ -4,142 +4,142 @@ description: Crie seu primeiro app do Twenty em minutos.
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Apps are currently in alpha. The feature works but is still evolving.
|
||||
Os aplicativos estão atualmente em testes alfa. O recurso é funcional, mas ainda está evoluindo.
|
||||
</Warning>
|
||||
|
||||
Os apps permitem que você estenda o Twenty com objetos, campos, funções de lógica, habilidades de IA e componentes de UI personalizados — tudo gerenciado como código.
|
||||
|
||||
## Pré-requisitos
|
||||
|
||||
Before you begin, make sure the following is installed on your machine:
|
||||
Antes de começar, verifique se o seguinte está instalado na sua máquina:
|
||||
|
||||
* **Node.js 24+** — [Download here](https://nodejs.org/)
|
||||
* **Yarn 4** — Comes with Node.js via Corepack. Enable it by running `corepack enable`
|
||||
* **Docker** — [Download here](https://www.docker.com/products/docker-desktop/). Required to run a local Twenty instance. Not needed if you already have a Twenty server running.
|
||||
* **Node.js 24+** — [Baixe aqui](https://nodejs.org/)
|
||||
* **Yarn 4** — Vem com o Node.js via Corepack. Ative-o executando `corepack enable`
|
||||
* **Docker** — [Baixe aqui](https://www.docker.com/products/docker-desktop/). Necessário para executar uma instância local do Twenty. Não é necessário se você já tiver um servidor Twenty em execução.
|
||||
|
||||
## Step 1: Scaffold your app
|
||||
## Passo 1: Gere o scaffold do seu aplicativo
|
||||
|
||||
Open a terminal and run:
|
||||
Abra um terminal e execute:
|
||||
|
||||
```bash filename="Terminal"
|
||||
npx create-twenty-app@latest my-twenty-app
|
||||
```
|
||||
|
||||
You will be prompted to enter a name and a description for your app. Press **Enter** to accept the defaults.
|
||||
Será solicitado que você informe um nome e uma descrição para o seu aplicativo. Pressione **Enter** para aceitar os valores padrão.
|
||||
|
||||
This creates a new folder called `my-twenty-app` with everything you need.
|
||||
Isso cria uma nova pasta chamada `my-twenty-app` com tudo de que você precisa.
|
||||
|
||||
<Note>
|
||||
The scaffolder supports these flags:
|
||||
O gerador de scaffold oferece suporte a estas flags:
|
||||
|
||||
* `--minimal` — scaffold only the essential files, no examples (default)
|
||||
* `--exhaustive` — scaffold all example entities
|
||||
* `--name <name>` — set the app name (skips the prompt)
|
||||
* `--display-name <displayName>` — set the display name (skips the prompt)
|
||||
* `--description <description>` — set the description (skips the prompt)
|
||||
* `--skip-local-instance` — skip the local server setup prompt
|
||||
* `--minimal` — gera apenas os arquivos essenciais, sem exemplos (padrão)
|
||||
* `--exhaustive` — gera todas as entidades de exemplo
|
||||
* `--name <name>` — define o nome do aplicativo (pula o prompt)
|
||||
* `--display-name <displayName>` — define o nome de exibição (pula o prompt)
|
||||
* `--description <description>` — define a descrição (pula o prompt)
|
||||
* `--skip-local-instance` — ignora o prompt de configuração do servidor local
|
||||
</Note>
|
||||
|
||||
## Step 2: Set up a local Twenty instance
|
||||
## Passo 2: Configure uma instância local do Twenty
|
||||
|
||||
The scaffolder will ask:
|
||||
O gerador de scaffold perguntará:
|
||||
|
||||
> **Would you like to set up a local Twenty instance?**
|
||||
> **Você gostaria de configurar uma instância local do Twenty?**
|
||||
|
||||
* **Type `yes`** (recommended) — This pulls the `twenty-app-dev` Docker image and starts a local Twenty server on port `2020`. Make sure Docker is running before you continue.
|
||||
* **Type `no`** — Choose this if you already have a Twenty server running locally.
|
||||
* **Digite `yes`** (recomendado) — Isso baixa a imagem Docker `twenty-app-dev` e inicia um servidor Twenty local na porta `2020`. Certifique-se de que o Docker esteja em execução antes de continuar.
|
||||
* **Digite `no`** — Escolha esta opção se você já tiver um servidor Twenty em execução localmente.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Should start local instance?" />
|
||||
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Deve iniciar instância local?" />
|
||||
</div>
|
||||
|
||||
## Step 3: Sign in to your workspace
|
||||
## Passo 3: Faça login no seu espaço de trabalho
|
||||
|
||||
Next, a browser window will open with the Twenty login page. Sign in with the pre-seeded demo account:
|
||||
Em seguida, uma janela do navegador será aberta com a página de login do Twenty. Faça login com a conta de demonstração pré-configurada:
|
||||
|
||||
* **Email:** `tim@apple.dev`
|
||||
* **Password:** `tim@apple.dev`
|
||||
* **E-mail:** `tim@apple.dev`
|
||||
* **Senha:** `tim@apple.dev`
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/login.png" alt="Twenty login screen" />
|
||||
<img src="/images/docs/developers/extends/apps/login.png" alt="Tela de login do Twenty" />
|
||||
</div>
|
||||
|
||||
## Step 4: Authorize the app
|
||||
## Passo 4: Autorize o aplicativo
|
||||
|
||||
After you sign in, you will see an authorization screen. This lets your app interact with your workspace.
|
||||
Após fazer login, você verá uma tela de autorização. Isso permite que seu aplicativo interaja com seu espaço de trabalho.
|
||||
|
||||
Click **Authorize** to continue.
|
||||
Clique em **Authorize** para continuar.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/authorize.png" alt="Twenty CLI authorization screen" />
|
||||
<img src="/images/docs/developers/extends/apps/authorize.png" alt="Tela de autorização da CLI do Twenty" />
|
||||
</div>
|
||||
|
||||
Once authorized, your terminal will confirm that everything is set up.
|
||||
Depois de autorizado, seu terminal confirmará que tudo está configurado.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="App scaffolded successfully" />
|
||||
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="Scaffold do aplicativo criado com sucesso" />
|
||||
</div>
|
||||
|
||||
## Step 5: Start developing
|
||||
## Passo 5: Comece a desenvolver
|
||||
|
||||
Go into your new app folder and start the development server:
|
||||
Entre na nova pasta do seu aplicativo e inicie o servidor de desenvolvimento:
|
||||
|
||||
```bash filename="Terminal"
|
||||
cd my-twenty-app
|
||||
yarn twenty dev
|
||||
```
|
||||
|
||||
This watches your source files, rebuilds on every change, and syncs your app to the local Twenty server automatically. You should see a live status panel in your terminal.
|
||||
Isso observa seus arquivos-fonte, recompila a cada alteração e sincroniza seu aplicativo com o servidor Twenty local automaticamente. Você deverá ver um painel de status em tempo real no seu terminal.
|
||||
|
||||
For more detailed output (build logs, sync requests, error traces), use the `--verbose` flag:
|
||||
Para uma saída mais detalhada (logs de build, solicitações de sincronização, rastros de erro), use a flag `--verbose`:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev --verbose
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Dev mode is only available on Twenty instances running in development (`NODE_ENV=development`). Production instances reject dev sync requests. Use `yarn twenty deploy` to deploy to production servers — see [Publishing Apps](/l/pt/developers/extend/apps/publishing) for details.
|
||||
O modo de desenvolvimento só está disponível em instâncias do Twenty em modo de desenvolvimento (`NODE_ENV=development`). Instâncias de produção rejeitam solicitações de sincronização de desenvolvimento. Use `yarn twenty deploy` para fazer o deploy em servidores de produção — veja [Publicando aplicativos](/l/pt/developers/extend/apps/publishing) para detalhes.
|
||||
</Warning>
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Dev mode terminal output" />
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Saída do terminal no modo de desenvolvimento" />
|
||||
</div>
|
||||
|
||||
## Step 6: See your app in Twenty
|
||||
## Passo 6: Veja seu aplicativo no Twenty
|
||||
|
||||
Open [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) in your browser. Navigate to **Settings > Apps** and select the **Developer** tab. You should see your app listed under **Your Apps**:
|
||||
Abra [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) no seu navegador. Navegue até **Settings > Apps** e selecione a aba **Developer**. Você deverá ver seu aplicativo listado em **Your Apps**:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-1.png" alt="Your Apps list showing My twenty app" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-1.png" alt="Lista Your Apps exibindo My twenty app" />
|
||||
</div>
|
||||
|
||||
Click on **My twenty app** to open its **application registration**. A registration is a server-level record that describes your app — its name, unique identifier, OAuth credentials, and source (local, npm, or tarball). It lives on the server, not inside any specific workspace. When you install an app into a workspace, Twenty creates a workspace-scoped **application** that points back to this registration. One registration can be installed across multiple workspaces on the same server.
|
||||
Clique em **My twenty app** para abrir o seu **registro do aplicativo**. Um registro é um registro em nível de servidor que descreve seu aplicativo — seu nome, identificador exclusivo, credenciais OAuth e origem (local, npm ou tarball). Ele reside no servidor, não dentro de nenhum espaço de trabalho específico. Quando você instala um aplicativo em um espaço de trabalho, o Twenty cria uma **aplicação** com escopo do espaço de trabalho que aponta para esse registro. Um registro pode ser instalado em vários espaços de trabalho no mesmo servidor.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-2.png" alt="Application registration details" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-2.png" alt="Detalhes do registro do aplicativo" />
|
||||
</div>
|
||||
|
||||
Click **View installed app** to see the installed app. The **About** tab shows the current version and management options:
|
||||
Clique em **View installed app** para ver o aplicativo instalado. A aba **About** mostra a versão atual e as opções de gerenciamento:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-3.png" alt="Installed app — About tab" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-3.png" alt="Aplicativo instalado — aba About" />
|
||||
</div>
|
||||
|
||||
Switch to the **Content** tab to see everything your app provides — objects, fields, logic functions, and agents:
|
||||
Altere para a aba **Content** para ver tudo o que seu aplicativo oferece — objetos, campos, funções de lógica e agentes:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-4.png" alt="Installed app — Content tab" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-4.png" alt="Aplicativo instalado — aba Content" />
|
||||
</div>
|
||||
|
||||
You are all set! Edit any file in `src/` and the changes will be picked up automatically.
|
||||
Tudo pronto! Edite qualquer arquivo em `src/` e as alterações serão detectadas automaticamente.
|
||||
|
||||
Head over to [Building Apps](/l/pt/developers/extend/apps/building) for a detailed guide on creating objects, logic functions, front components, skills, and more.
|
||||
Acesse [Criando aplicativos](/l/pt/developers/extend/apps/building) para um guia detalhado sobre criação de objetos, funções de lógica, componentes de front-end, habilidades e mais.
|
||||
|
||||
---
|
||||
|
||||
## Project structure
|
||||
## Estrutura do projeto
|
||||
|
||||
The scaffolder generates the following file structure (shown with `--exhaustive` mode, which includes examples for every entity type):
|
||||
O gerador de scaffold cria a seguinte estrutura de arquivos (mostrada com o modo `--exhaustive`, que inclui exemplos para cada tipo de entidade):
|
||||
|
||||
```text filename="my-twenty-app/"
|
||||
my-twenty-app/
|
||||
@@ -190,30 +190,30 @@ my-twenty-app/
|
||||
└── example-agent.ts # Example AI agent definition
|
||||
```
|
||||
|
||||
By default (`--minimal`), only the core files are created: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`. Use `--exhaustive` to include all the example files shown above.
|
||||
Por padrão (`--minimal`), apenas os arquivos principais são criados: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` e `logic-functions/post-install.ts`. Use `--exhaustive` para incluir todos os arquivos de exemplo mostrados acima.
|
||||
|
||||
### Key files
|
||||
### Arquivos principais
|
||||
|
||||
| File / Folder | Finalidade |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `package.json` | Declares your app name, version, and dependencies. Includes a `twenty` script so you can run `yarn twenty help` to see all commands. |
|
||||
| `src/application-config.ts` | **Required.** The main configuration file for your app. |
|
||||
| `src/roles/` | Defines roles that control what your logic functions can access. |
|
||||
| `src/logic-functions/` | Server-side functions triggered by routes, cron schedules, or database events. |
|
||||
| `src/front-components/` | React components that render inside Twenty's UI. |
|
||||
| `src/objects/` | Custom object definitions to extend your data model. |
|
||||
| `src/fields/` | Custom fields added to existing objects. |
|
||||
| `src/views/` | Saved view configurations. |
|
||||
| `src/navigation-menu-items/` | Custom links in the sidebar navigation. |
|
||||
| `src/skills/` | Habilidades que estendem os agentes de IA do Twenty. |
|
||||
| `src/agents/` | AI agents with custom prompts. |
|
||||
| `src/page-layouts/` | Custom page layouts for record views. |
|
||||
| `src/__tests__/` | Integration tests (setup + example test). |
|
||||
| `public/` | Static assets (images, fonts) served with your app. |
|
||||
| Arquivo / Pasta | Finalidade |
|
||||
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `package.json` | Declara o nome, a versão e as dependências do seu aplicativo. Inclui um script `twenty` para que você possa executar `yarn twenty help` e ver todos os comandos. |
|
||||
| `src/application-config.ts` | **Obrigatório.** O principal arquivo de configuração do seu aplicativo. |
|
||||
| `src/roles/` | Define papéis que controlam o que suas funções de lógica podem acessar. |
|
||||
| `src/logic-functions/` | Funções do lado do servidor acionadas por rotas, agendamentos do cron ou eventos de banco de dados. |
|
||||
| `src/front-components/` | Componentes React que renderizam dentro da interface do Twenty. |
|
||||
| `src/objects/` | Definições de objetos personalizados para estender seu modelo de dados. |
|
||||
| `src/fields/` | Campos personalizados adicionados a objetos existentes. |
|
||||
| `src/views/` | Configurações de visualizações salvas. |
|
||||
| `src/navigation-menu-items/` | Links personalizados na navegação da barra lateral. |
|
||||
| `src/skills/` | Habilidades que estendem os agentes de IA do Twenty. |
|
||||
| `src/agents/` | Agentes de IA com prompts personalizados. |
|
||||
| `src/page-layouts/` | Layouts de página personalizados para visualizações de registros. |
|
||||
| `src/__tests__/` | Testes de integração (configuração + teste de exemplo). |
|
||||
| `public/` | Recursos estáticos (imagens, fontes) servidos com seu aplicativo. |
|
||||
|
||||
## Managing remotes
|
||||
## Gerenciando remotos
|
||||
|
||||
A **remote** is a Twenty server that your app connects to. During setup, the scaffolder creates one for you automatically. You can add more remotes or switch between them at any time.
|
||||
Um **remoto** é um servidor Twenty ao qual seu aplicativo se conecta. Durante a configuração, o gerador de scaffold cria um para você automaticamente. Você pode adicionar mais remotos ou alternar entre eles a qualquer momento.
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Add a new remote (opens a browser for OAuth login)
|
||||
@@ -232,11 +232,11 @@ yarn twenty remote list
|
||||
yarn twenty remote switch <name>
|
||||
```
|
||||
|
||||
Your credentials are stored in `~/.twenty/config.json`.
|
||||
Suas credenciais são armazenadas em `~/.twenty/config.json`.
|
||||
|
||||
## Local development server (`yarn twenty server`)
|
||||
## Servidor de desenvolvimento local (`yarn twenty server`)
|
||||
|
||||
The CLI can manage a local Twenty server running in Docker. This is the same server started automatically when you scaffold an app with `create-twenty-app`, but you can also manage it manually.
|
||||
A CLI pode gerenciar um servidor Twenty local em execução no Docker. Este é o mesmo servidor iniciado automaticamente quando você cria o scaffold de um aplicativo com `create-twenty-app`, mas você também pode gerenciá-lo manualmente.
|
||||
|
||||
### Iniciando o servidor
|
||||
|
||||
@@ -244,85 +244,85 @@ The CLI can manage a local Twenty server running in Docker. This is the same ser
|
||||
yarn twenty server start
|
||||
```
|
||||
|
||||
This pulls the `twentycrm/twenty-app-dev:latest` Docker image (if not already present), creates a container named `twenty-app-dev`, and starts it on port **2020**. The CLI waits until the server passes its health check before returning.
|
||||
Isso baixa a imagem Docker `twentycrm/twenty-app-dev:latest` (se ainda não estiver presente), cria um contêiner chamado `twenty-app-dev` e o inicia na porta **2020**. A CLI aguarda até que o servidor passe na verificação de integridade antes de retornar.
|
||||
|
||||
Two Docker volumes are created to persist data between restarts:
|
||||
Dois volumes do Docker são criados para persistir os dados entre reinicializações:
|
||||
|
||||
* `twenty-app-dev-data` — PostgreSQL database
|
||||
* `twenty-app-dev-storage` — file storage
|
||||
* `twenty-app-dev-data` — banco de dados PostgreSQL
|
||||
* `twenty-app-dev-storage` — armazenamento de arquivos
|
||||
|
||||
If port 2020 is already in use, you can start on a different port:
|
||||
Se a porta 2020 já estiver em uso, você pode iniciar em uma porta diferente:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server start --port 3030
|
||||
```
|
||||
|
||||
The CLI automatically configures the container's internal `NODE_PORT` and `SERVER_URL` to match the chosen port, so logic functions, OAuth, and all other internal networking work correctly.
|
||||
A CLI configura automaticamente as variáveis internas do contêiner `NODE_PORT` e `SERVER_URL` para corresponderem à porta escolhida, para que as funções de lógica, o OAuth e toda a comunicação interna de rede funcionem corretamente.
|
||||
|
||||
Once started, the server is automatically registered as the `local` remote in your CLI config.
|
||||
Depois de iniciado, o servidor é registrado automaticamente como o remoto `local` na configuração da sua CLI.
|
||||
|
||||
### Checking server status
|
||||
### Verificando o status do servidor
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server status
|
||||
```
|
||||
|
||||
Displays whether the server is running, its URL, and the default login credentials (`tim@apple.dev` / `tim@apple.dev`).
|
||||
Exibe se o servidor está em execução, sua URL e as credenciais de login padrão (`tim@apple.dev` / `tim@apple.dev`).
|
||||
|
||||
### Viewing server logs
|
||||
### Visualizando os logs do servidor
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server logs
|
||||
```
|
||||
|
||||
Streams the container logs. Use `--lines` to control how many recent lines to show:
|
||||
Transmite os logs do contêiner. Use `--lines` para controlar quantas linhas recentes mostrar:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server logs --lines 100
|
||||
```
|
||||
|
||||
### Stopping the server
|
||||
### Parando o servidor
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server stop
|
||||
```
|
||||
|
||||
Stops the container. Your data is preserved in the Docker volumes — the next `start` picks up where you left off.
|
||||
Interrompe o contêiner. Seus dados são preservados nos volumes do Docker — o próximo `start` continua de onde você parou.
|
||||
|
||||
### Resetting the server
|
||||
### Redefinindo o servidor
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server reset
|
||||
```
|
||||
|
||||
Removes the container **and** deletes both Docker volumes, wiping all data. The next `start` creates a fresh instance.
|
||||
Remove o contêiner **e** exclui os dois volumes do Docker, apagando todos os dados. O próximo `start` cria uma instância nova.
|
||||
|
||||
<Note>
|
||||
The server requires **Docker** to be running. If you see a "Docker not running" error, make sure Docker Desktop (or the Docker daemon) is started.
|
||||
O servidor requer que o **Docker** esteja em execução. Se você vir um erro "Docker not running", certifique-se de que o Docker Desktop (ou o daemon do Docker) esteja iniciado.
|
||||
</Note>
|
||||
|
||||
### Command reference
|
||||
### Referência de comandos
|
||||
|
||||
| Comando | Descrição |
|
||||
| -------------------------------------- | ---------------------------------------------- |
|
||||
| `yarn twenty server start` | Start the local server (pulls image if needed) |
|
||||
| `yarn twenty server start --port 3030` | Start on a custom port |
|
||||
| `yarn twenty server stop` | Stop the server (preserves data) |
|
||||
| `yarn twenty server status` | Show server status, URL, and credentials |
|
||||
| `yarn twenty server logs` | Stream server logs |
|
||||
| `yarn twenty server logs --lines 100` | Show the last 100 log lines |
|
||||
| `yarn twenty server reset` | Delete all data and start fresh |
|
||||
| Comando | Descrição |
|
||||
| -------------------------------------- | ------------------------------------------------------ |
|
||||
| `yarn twenty server start` | Inicia o servidor local (baixa a imagem se necessário) |
|
||||
| `yarn twenty server start --port 3030` | Iniciar em uma porta personalizada |
|
||||
| `yarn twenty server stop` | Interrompe o servidor (preserva os dados) |
|
||||
| `yarn twenty server status` | Mostra o status do servidor, a URL e as credenciais |
|
||||
| `yarn twenty server logs` | Transmite os logs do servidor |
|
||||
| `yarn twenty server logs --lines 100` | Mostra as últimas 100 linhas de log |
|
||||
| `yarn twenty server reset` | Exclui todos os dados e inicia do zero |
|
||||
|
||||
## CI with GitHub Actions
|
||||
## CI com GitHub Actions
|
||||
|
||||
The scaffolder generates a ready-to-use GitHub Actions workflow at `.github/workflows/ci.yml`. It runs your integration tests automatically on every push to `main` and on pull requests.
|
||||
O gerador de scaffold cria um workflow do GitHub Actions pronto para uso em `.github/workflows/ci.yml`. Ele executa seus testes de integração automaticamente a cada push para `main` e em pull requests.
|
||||
|
||||
The workflow:
|
||||
O workflow:
|
||||
|
||||
1. Checks out your code
|
||||
2. Spins up a temporary Twenty server using the `twentyhq/twenty/.github/actions/spawn-twenty-docker-image` action
|
||||
3. Installs dependencies with `yarn install --immutable`
|
||||
4. Runs `yarn test` with `TWENTY_API_URL` and `TWENTY_API_KEY` injected from the action outputs
|
||||
1. Faz checkout do seu código
|
||||
2. Inicializa um servidor Twenty temporário usando a ação `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
|
||||
3. Instala as dependências com `yarn install --immutable`
|
||||
4. Executa `yarn test` com `TWENTY_API_URL` e `TWENTY_API_KEY` injetados a partir das saídas da ação
|
||||
|
||||
```yaml .github/workflows/ci.yml
|
||||
name: CI
|
||||
@@ -369,21 +369,21 @@ jobs:
|
||||
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
|
||||
```
|
||||
|
||||
You don't need to configure any secrets — the `spawn-twenty-docker-image` action starts an ephemeral Twenty server directly in the runner and outputs the connection details. The `GITHUB_TOKEN` secret is provided automatically by GitHub.
|
||||
Você não precisa configurar nenhum segredo — a ação `spawn-twenty-docker-image` inicia um servidor Twenty efêmero diretamente no runner e fornece os detalhes de conexão. O segredo `GITHUB_TOKEN` é fornecido automaticamente pelo GitHub.
|
||||
|
||||
To pin a specific Twenty version instead of `latest`, change the `TWENTY_VERSION` environment variable at the top of the workflow.
|
||||
Para fixar uma versão específica do Twenty em vez de `latest`, altere a variável de ambiente `TWENTY_VERSION` no topo do workflow.
|
||||
|
||||
## Configuração manual (sem o gerador)
|
||||
|
||||
If you prefer to set things up yourself instead of using `create-twenty-app`, you can do it in two steps.
|
||||
Se preferir configurar tudo por conta própria em vez de usar `create-twenty-app`, você pode fazer isso em duas etapas.
|
||||
|
||||
**1. Add `twenty-sdk` and `twenty-client-sdk` as dependencies:**
|
||||
**1. Adicione `twenty-sdk` e `twenty-client-sdk` como dependências:**
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn add twenty-sdk twenty-client-sdk
|
||||
```
|
||||
|
||||
**2. Add a `twenty` script to your `package.json`:**
|
||||
**2. Adicione um script `twenty` ao seu `package.json`:**
|
||||
|
||||
```json filename="package.json"
|
||||
{
|
||||
@@ -393,19 +393,19 @@ yarn add twenty-sdk twenty-client-sdk
|
||||
}
|
||||
```
|
||||
|
||||
You can now run `yarn twenty dev`, `yarn twenty help`, and all other commands.
|
||||
Agora você pode executar `yarn twenty dev`, `yarn twenty help` e todos os outros comandos.
|
||||
|
||||
<Note>
|
||||
Do not install `twenty-sdk` globally. Always use it as a local project dependency so that each project can pin its own version.
|
||||
Não instale o `twenty-sdk` globalmente. Use-o sempre como uma dependência local do projeto para que cada projeto possa fixar sua própria versão.
|
||||
</Note>
|
||||
|
||||
## Resolução de Problemas
|
||||
|
||||
If you run into issues:
|
||||
Se você tiver problemas:
|
||||
|
||||
* Make sure **Docker is running** before starting the scaffolder with a local instance.
|
||||
* Make sure you are using **Node.js 24+** (`node -v` to check).
|
||||
* Make sure **Corepack is enabled** (`corepack enable`) so Yarn 4 is available.
|
||||
* Try deleting `node_modules` and running `yarn install` again if dependencies seem broken.
|
||||
* Certifique-se de que o **Docker está em execução** antes de iniciar o scaffolder com uma instância local.
|
||||
* Certifique-se de que está usando **Node.js 24+** (`node -v` para verificar).
|
||||
* Certifique-se de que o **Corepack está ativado** (`corepack enable`) para que o Yarn 4 esteja disponível.
|
||||
* Tente excluir `node_modules` e executar `yarn install` novamente se as dependências parecerem corrompidas.
|
||||
|
||||
Still stuck? Ask for help on the [Twenty Discord](https://discord.com/channels/1130383047699738754/1130386664812982322).
|
||||
Ainda com dificuldades? Peça ajuda no [Discord da Twenty](https://discord.com/channels/1130383047699738754/1130386664812982322).
|
||||
|
||||
@@ -4,24 +4,24 @@ description: Определяйте объекты, функции логики,
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Apps are currently in alpha. The feature works but is still evolving.
|
||||
Приложения сейчас проходят альфа-тестирование. Функция работает, но продолжает развиваться.
|
||||
</Warning>
|
||||
|
||||
The `twenty-sdk` package provides typed building blocks to create your app. This page covers every entity type and API client available in the SDK.
|
||||
Пакет `twenty-sdk` предоставляет типизированные строительные блоки для создания вашего приложения. На этой странице описаны все типы сущностей и клиенты API, доступные в SDK.
|
||||
|
||||
## DefineEntity functions
|
||||
## Функции DefineEntity
|
||||
|
||||
The SDK provides functions to define your app entities. You must use `export default defineEntity({...})` for the SDK to detect your entities. Эти функции проверяют вашу конфигурацию на этапе сборки и обеспечивают автодополнение в IDE и безопасность типов.
|
||||
SDK предоставляет функции для определения сущностей вашего приложения. Вы должны использовать `export default defineEntity({...})`, чтобы SDK обнаруживал ваши сущности. Эти функции проверяют вашу конфигурацию на этапе сборки и обеспечивают автодополнение в IDE и безопасность типов.
|
||||
|
||||
<Note>
|
||||
**File organization is up to you.**
|
||||
Entity detection is AST-based — the SDK finds `export default defineEntity(...)` calls regardless of where the file lives. Grouping files by type (e.g., `logic-functions/`, `roles/`) is just a convention, not a requirement.
|
||||
**Организация файлов — на ваше усмотрение.**
|
||||
Обнаружение сущностей основано на AST — SDK находит вызовы `export default defineEntity(...)` независимо от расположения файла. Группировка файлов по типу (например, `logic-functions/`, `roles/`) — это лишь соглашение, а не требование.
|
||||
</Note>
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="defineRole" description="Настраивает права роли и доступ к объектам">
|
||||
|
||||
Roles encapsulate permissions on your workspace's objects and actions.
|
||||
Роли инкапсулируют права на объекты и действия вашего рабочего пространства.
|
||||
|
||||
```ts restricted-company-role.ts
|
||||
import {
|
||||
@@ -69,12 +69,12 @@ export default defineRole({
|
||||
</Accordion>
|
||||
<Accordion title="defineApplication" description="Настройка метаданных приложения (обязательно, по одному на приложение)">
|
||||
|
||||
Every app must have exactly one `defineApplication` call that describes:
|
||||
В каждом приложении должен быть ровно один вызов `defineApplication`, который описывает:
|
||||
|
||||
* **Identity**: identifiers, display name, and description.
|
||||
* **Permissions**: which role its functions and front components use.
|
||||
* **(Optional) Variables**: key–value pairs exposed to your functions as environment variables.
|
||||
* **(Optional) Pre-install / post-install functions**: logic functions that run before or after installation.
|
||||
* **Идентификация**: идентификаторы, отображаемое имя и описание.
|
||||
* **Разрешения**: какую роль используют его функции и фронтенд-компоненты.
|
||||
* **(Необязательно) Переменные**: пары ключ–значение, доступные вашим функциям как переменные окружения.
|
||||
* **(Необязательно) Предустановочные / постустановочные функции**: логические функции, которые запускаются до или после установки.
|
||||
|
||||
```ts src/application-config.ts
|
||||
import { defineApplication } from 'twenty-sdk';
|
||||
@@ -98,21 +98,21 @@ export default defineApplication({
|
||||
```
|
||||
|
||||
Заметки:
|
||||
* `universalIdentifier` fields are deterministic IDs you own. Generate them once and keep them stable across syncs.
|
||||
* `applicationVariables` become environment variables for your functions and front components (e.g., `DEFAULT_RECIPIENT_NAME` is available as `process.env.DEFAULT_RECIPIENT_NAME`).
|
||||
* `defaultRoleUniversalIdentifier` must reference a role defined with `defineRole()` (see above).
|
||||
* Pre-install and post-install functions are detected automatically during the manifest build — you do not need to reference them in `defineApplication()`.
|
||||
* Поля `universalIdentifier` — это детерминированные идентификаторы, которые принадлежат вам. Сгенерируйте их один раз и сохраняйте неизменными между синхронизациями.
|
||||
* `applicationVariables` становятся переменными окружения для ваших функций и фронтенд-компонентов (например, `DEFAULT_RECIPIENT_NAME` доступна как `process.env.DEFAULT_RECIPIENT_NAME`).
|
||||
* `defaultRoleUniversalIdentifier` должен ссылаться на роль, определённую с помощью `defineRole()` (см. выше).
|
||||
* Предустановочные и постустановочные функции обнаруживаются автоматически во время сборки манифеста — вам не нужно указывать их в `defineApplication()`.
|
||||
|
||||
#### Метаданные маркетплейса
|
||||
|
||||
If you plan to [publish your app](/l/ru/developers/extend/apps/publishing), these optional fields control how it appears in the marketplace:
|
||||
Если вы планируете [опубликовать приложение](/l/ru/developers/extend/apps/publishing), эти необязательные поля определяют, как оно отображается в маркетплейсе:
|
||||
|
||||
| Поле | Описание |
|
||||
| ------------------ | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| `author` | Имя автора или название компании |
|
||||
| `category` | Категория приложения для фильтрации в маркетплейсе |
|
||||
| `logoUrl` | Path to your app logo (e.g., `public/logo.png`) |
|
||||
| `screenshots` | Array of screenshot paths (e.g., `public/screenshot-1.png`) |
|
||||
| `logoUrl` | Путь к логотипу вашего приложения (например, `public/logo.png`) |
|
||||
| `screenshots` | Массив путей к скриншотам (например, `public/screenshot-1.png`) |
|
||||
| `aboutDescription` | Расширенное описание в Markdown для вкладки "About". Если опущено, маркетплейс использует `README.md` пакета из npm |
|
||||
| `websiteUrl` | Ссылка на ваш сайт |
|
||||
| `termsUrl` | Ссылка на условия предоставления услуг |
|
||||
@@ -121,15 +121,15 @@ If you plan to [publish your app](/l/ru/developers/extend/apps/publishing), thes
|
||||
|
||||
#### Роли и разрешения
|
||||
|
||||
The `defaultRoleUniversalIdentifier` in `application-config.ts` designates the default role used by your app's logic functions and front components. See `defineRole` above for details.
|
||||
Поле `defaultRoleUniversalIdentifier` в `application-config.ts` обозначает роль по умолчанию, используемую логическими функциями и фронтенд-компонентами вашего приложения. Подробности см. в `defineRole` выше.
|
||||
|
||||
* The runtime token injected as `TWENTY_APP_ACCESS_TOKEN` is derived from this role.
|
||||
* The typed client is restricted to the permissions granted to that role.
|
||||
* Follow least-privilege: create a dedicated role with only the permissions your functions need.
|
||||
* Токен времени выполнения, подставляемый как `TWENTY_APP_ACCESS_TOKEN`, формируется из этой роли.
|
||||
* Типизированный клиент ограничен правами, предоставленными этой ролью.
|
||||
* Следуйте принципу наименьших привилегий: создайте отдельную роль только с теми правами, которые нужны вашим функциям.
|
||||
|
||||
##### Default function role
|
||||
##### Роль функции по умолчанию
|
||||
|
||||
When you scaffold a new app, the CLI creates a default role file:
|
||||
Когда вы генерируете новое приложение, CLI создаёт файл роли по умолчанию:
|
||||
|
||||
```ts src/roles/default-role.ts
|
||||
import { defineRole, PermissionFlag } from 'twenty-sdk';
|
||||
@@ -155,16 +155,16 @@ export default defineRole({
|
||||
});
|
||||
```
|
||||
|
||||
This role's `universalIdentifier` is referenced in `application-config.ts` as `defaultRoleUniversalIdentifier`:
|
||||
Значение `universalIdentifier` этой роли указывается в `application-config.ts` как `defaultRoleUniversalIdentifier`:
|
||||
|
||||
* **\*.role.ts** defines what the role can do.
|
||||
* **\*.role.ts** определяет, что может делать роль.
|
||||
* **application-config.ts** указывает на эту роль, чтобы ваши функции наследовали её права.
|
||||
|
||||
Заметки:
|
||||
* Начните со сгенерированной роли, затем постепенно ограничивайте её, следуя принципу наименьших привилегий.
|
||||
* Replace `objectPermissions` and `fieldPermissions` with the objects and fields your functions actually need.
|
||||
* `permissionFlags` управляют доступом к возможностям на уровне платформы. Keep them minimal.
|
||||
* See a working example: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
|
||||
* Замените `objectPermissions` и `fieldPermissions` на объекты и поля, которые действительно нужны вашим функциям.
|
||||
* `permissionFlags` управляют доступом к возможностям на уровне платформы. Сведите их к минимуму.
|
||||
* См. рабочий пример: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="defineObject" description="Определяет пользовательские объекты с полями">
|
||||
@@ -256,7 +256,7 @@ export default defineObject({
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="defineField — Standard fields" description="Расширение существующих объектов дополнительными полями">
|
||||
<Accordion title="defineField — Стандартные поля" description="Расширение существующих объектов дополнительными полями">
|
||||
|
||||
Используйте `defineField()` для добавления полей к объектам, которые вам не принадлежат — например, к стандартным объектам Twenty (Person, Company и т. д.). или к объектам из других приложений. В отличие от встроенных полей в `defineObject()`, отдельные поля требуют `objectUniversalIdentifier`, чтобы указать, какой объект они расширяют:
|
||||
|
||||
@@ -284,7 +284,7 @@ export default defineField({
|
||||
* `defineField()` — единственный способ добавить поля к объектам, которые вы не создавали с помощью `defineObject()`.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="defineField — Relation fields" description="Connect objects together with bidirectional relations">
|
||||
<Accordion title="defineField — Поля связей" description="Связывайте объекты двунаправленными связями">
|
||||
|
||||
Отношения связывают объекты между собой. В Twenty отношения всегда двунаправленные — вы определяете обе стороны, и каждая сторона ссылается на другую.
|
||||
|
||||
@@ -443,7 +443,7 @@ export default defineObject({
|
||||
});
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="defineLogicFunction" description="Define logic functions and their triggers">
|
||||
<Accordion title="defineLogicFunction" description="Определяйте логические функции и их триггеры">
|
||||
|
||||
Каждый файл функции использует `defineLogicFunction()` для экспорта конфигурации с обработчиком и необязательными триггерами.
|
||||
|
||||
@@ -487,15 +487,15 @@ export default defineLogicFunction({
|
||||
});
|
||||
```
|
||||
|
||||
Available trigger types:
|
||||
* **httpRoute**: Exposes your function on an HTTP path and method **under the `/s/` endpoint**:
|
||||
> e.g. `path: '/post-card/create'` is callable at `https://your-twenty-server.com/s/post-card/create`
|
||||
Доступные типы триггеров:
|
||||
* **httpRoute**: Публикует вашу функцию по HTTP-пути и методу **под конечной точкой `/s/`**:
|
||||
> например, `path: '/post-card/create'` вызывается по адресу `https://your-twenty-server.com/s/post-card/create`
|
||||
* **cron**: Запускает вашу функцию по расписанию с использованием выражения CRON.
|
||||
* **databaseEvent**: Запускается при событиях жизненного цикла объектов рабочего пространства. Когда операция события — `updated`, можно указать конкретные поля для отслеживания в массиве `updatedFields`. Если оставить не заданным или пустым, любое обновление будет вызывать функцию.
|
||||
> e.g. `person.updated`, `*.created`, `company.*`
|
||||
> например, `person.updated`, `*.created`, `company.*`
|
||||
|
||||
<Note>
|
||||
You can also manually execute a function using the CLI:
|
||||
Вы также можете вручную выполнить функцию с помощью CLI:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty exec -n create-new-post-card -p '{"key": "value"}'
|
||||
@@ -505,7 +505,7 @@ yarn twenty exec -n create-new-post-card -p '{"key": "value"}'
|
||||
yarn twenty exec -y e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf
|
||||
```
|
||||
|
||||
You can watch logs with:
|
||||
Вы можете просматривать логи с помощью:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty logs
|
||||
@@ -514,9 +514,8 @@ yarn twenty logs
|
||||
|
||||
#### Полезная нагрузка триггера маршрута
|
||||
|
||||
When a route trigger invokes your logic function, it receives a `RoutePayload` object that follows the
|
||||
[AWS HTTP API v2 format](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html).
|
||||
Import the `RoutePayload` type from `twenty-sdk`:
|
||||
Когда триггер маршрута вызывает вашу логическую функцию, она получает объект `RoutePayload`, который соответствует [формату AWS HTTP API v2](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html).
|
||||
Импортируйте тип `RoutePayload` из `twenty-sdk`:
|
||||
|
||||
```ts
|
||||
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';
|
||||
@@ -533,9 +532,9 @@ const handler = async (event: RoutePayload) => {
|
||||
|
||||
| Свойство | Тип | Описание | Пример |
|
||||
| ---------------------------- | ------------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
||||
| `headers` | `Record<string, string \| undefined>` | HTTP-заголовки (только перечисленные в `forwardedRequestHeaders`) | see section below |
|
||||
| `headers` | `Record<string, string \| undefined>` | HTTP-заголовки (только перечисленные в `forwardedRequestHeaders`) | см. раздел ниже |
|
||||
| `queryStringParameters` | `Record<string, string \| undefined>` | Параметры строки запроса (несколько значений объединяются запятыми) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
|
||||
| `pathParameters` | `Record<string, string \| undefined>` | Path parameters extracted from the route pattern | `/users/:id`, `/users/123` -> `{ id: '123' }` |
|
||||
| `pathParameters` | `Record<string, string \| undefined>` | Параметры пути, извлечённые из шаблона маршрута | `/users/:id`, `/users/123` -> `{ id: '123' }` |
|
||||
| `body` | `object \| null` | Разобранное тело запроса (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
|
||||
| `isBase64Encoded` | `логический тип` | Является ли тело закодированным в base64 | |
|
||||
| `requestContext.http.method` | `строка` | Метод HTTP (GET, POST, PUT, PATCH, DELETE) | |
|
||||
@@ -545,7 +544,7 @@ const handler = async (event: RoutePayload) => {
|
||||
#### forwardedRequestHeaders
|
||||
|
||||
По умолчанию HTTP-заголовки из входящих запросов **не** передаются в вашу логическую функцию по соображениям безопасности.
|
||||
To access specific headers, list them in the `forwardedRequestHeaders` array:
|
||||
Чтобы получить доступ к определённым заголовкам, перечислите их в массиве `forwardedRequestHeaders`:
|
||||
|
||||
```ts
|
||||
export default defineLogicFunction({
|
||||
@@ -561,7 +560,7 @@ export default defineLogicFunction({
|
||||
});
|
||||
```
|
||||
|
||||
In your handler, access the forwarded headers like this:
|
||||
В обработчике обращайтесь к переданным заголовкам следующим образом:
|
||||
|
||||
```ts
|
||||
const handler = async (event: RoutePayload) => {
|
||||
@@ -574,14 +573,14 @@ const handler = async (event: RoutePayload) => {
|
||||
```
|
||||
|
||||
<Note>
|
||||
Имена заголовков приводятся к нижнему регистру. Access them using lowercase keys (e.g., `event.headers['content-type']`).
|
||||
Имена заголовков приводятся к нижнему регистру. Обращайтесь к ним, используя ключи в нижнем регистре (например, `event.headers['content-type']`).
|
||||
</Note>
|
||||
|
||||
#### Exposing a function as a tool
|
||||
#### Предоставление функции как инструмента
|
||||
|
||||
Логические функции можно предоставлять как **инструменты** для ИИ-агентов и рабочих процессов. When marked as a tool, a function becomes discoverable by Twenty's AI features and can be used in workflow automations.
|
||||
Логические функции можно предоставлять как **инструменты** для ИИ-агентов и рабочих процессов. Когда функция помечена как инструмент, она становится доступной для функций ИИ Twenty и может использоваться в автоматизациях рабочих процессов.
|
||||
|
||||
To mark a logic function as a tool, set `isTool: true`:
|
||||
Чтобы пометить логическую функцию как инструмент, установите `isTool: true`:
|
||||
|
||||
```ts src/logic-functions/enrich-company.logic-function.ts
|
||||
import { defineLogicFunction } from 'twenty-sdk';
|
||||
@@ -617,8 +616,8 @@ export default defineLogicFunction({
|
||||
|
||||
Основные моменты:
|
||||
|
||||
* You can combine `isTool` with triggers — a function can be both a tool (callable by AI agents) and triggered by events at the same time.
|
||||
* **`toolInputSchema`** (optional): A JSON Schema object describing the parameters your function accepts. The schema is computed automatically from source code static analysis, but you can set it explicitly:
|
||||
* Вы можете комбинировать `isTool` с триггерами — функция может одновременно быть инструментом (вызываемым агентами ИИ) и запускаться событиями.
|
||||
* **`toolInputSchema`** (необязательно): объект JSON Schema, описывающий параметры, которые принимает ваша функция. Схема вычисляется автоматически на основе статического анализа исходного кода, но вы можете задать её явно:
|
||||
|
||||
```ts
|
||||
export default defineLogicFunction({
|
||||
@@ -715,11 +714,11 @@ yarn twenty exec --postInstall
|
||||
</Accordion>
|
||||
<Accordion title="defineFrontComponent" description="Определение фронт-компонентов для настраиваемого интерфейса">
|
||||
|
||||
Front components are React components that render directly inside Twenty's UI. They run in an **isolated Web Worker** using Remote DOM — your code is sandboxed but renders natively in the page, not in an iframe.
|
||||
Фронтенд-компоненты — это компоненты React, которые отображаются непосредственно внутри интерфейса Twenty. Они выполняются в изолированном Web Worker с использованием Remote DOM — ваш код изолирован (sandboxed), но рендерится нативно на странице, а не в iframe.
|
||||
|
||||
#### Basic example
|
||||
#### Простой пример
|
||||
|
||||
The quickest way to see a front component in action is to register it as a **command**. Adding a `command` field with `isPinned: true` makes it appear as a quick-action button in the top-right corner of the page — no page layout needed:
|
||||
Самый быстрый способ увидеть фронтенд-компонент в действии — зарегистрировать его как **команду**. Добавление поля `command` с `isPinned: true` делает его кнопкой быстрого действия в правом верхнем углу страницы — макет страницы не требуется:
|
||||
|
||||
```tsx src/front-components/hello-world.tsx
|
||||
import { defineFrontComponent } from 'twenty-sdk';
|
||||
@@ -749,24 +748,24 @@ export default defineFrontComponent({
|
||||
});
|
||||
```
|
||||
|
||||
After syncing with `yarn twenty dev`, the quick action appears in the top-right corner of the page:
|
||||
После синхронизации с помощью `yarn twenty dev` быстрое действие появится в правом верхнем углу страницы:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Quick action button in the top-right corner" />
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Кнопка быстрого действия в правом верхнем углу" />
|
||||
</div>
|
||||
|
||||
Click it to render the component inline.
|
||||
Нажмите её, чтобы отобразить компонент инлайн.
|
||||
|
||||
{/* TODO: add screenshot of the rendered front component */}
|
||||
|
||||
#### Configuration fields
|
||||
#### Поля конфигурации
|
||||
|
||||
| Поле | Обязательно | Описание |
|
||||
| --------------------- | ----------- | ----------------------------------------------------------------------------------- |
|
||||
| `universalIdentifier` | Да | Stable unique ID for this component |
|
||||
| `component` | Да | A React component function |
|
||||
| `name` | Нет | Display name |
|
||||
| `description` | Нет | Description of what the component does |
|
||||
| `universalIdentifier` | Да | Стабильный уникальный идентификатор для этого компонента |
|
||||
| `component` | Да | Функция компонента React |
|
||||
| `name` | Нет | Отображаемое имя |
|
||||
| `description` | Нет | Описание того, что делает компонент |
|
||||
| `isHeadless` | Нет | Set to `true` if the component has no visible UI (see below) |
|
||||
| `command` | Нет | Register the component as a command (see [command options](#command-options) below) |
|
||||
|
||||
|
||||
@@ -4,142 +4,142 @@ description: Создайте своё первое приложение Twenty
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Apps are currently in alpha. The feature works but is still evolving.
|
||||
Приложения сейчас проходят альфа-тестирование. Функция работает, но продолжает развиваться.
|
||||
</Warning>
|
||||
|
||||
Приложения позволяют расширять Twenty с помощью пользовательских объектов, полей, логических функций, навыков ИИ и UI-компонентов — всё это управляется как код.
|
||||
|
||||
## Требования
|
||||
|
||||
Before you begin, make sure the following is installed on your machine:
|
||||
Прежде чем начать, убедитесь, что на вашем компьютере установлено следующее:
|
||||
|
||||
* **Node.js 24+** — [Download here](https://nodejs.org/)
|
||||
* **Yarn 4** — Comes with Node.js via Corepack. Enable it by running `corepack enable`
|
||||
* **Docker** — [Download here](https://www.docker.com/products/docker-desktop/). Required to run a local Twenty instance. Not needed if you already have a Twenty server running.
|
||||
* **Node.js 24+** — [Скачать здесь](https://nodejs.org/)
|
||||
* **Yarn 4** — Поставляется вместе с Node.js через Corepack. Включите его, выполнив `corepack enable`
|
||||
* **Docker** — [Скачать здесь](https://www.docker.com/products/docker-desktop/). Требуется для запуска локального экземпляра Twenty. Не требуется, если у вас уже запущен сервер Twenty.
|
||||
|
||||
## Step 1: Scaffold your app
|
||||
## Шаг 1: Сгенерируйте каркас приложения
|
||||
|
||||
Open a terminal and run:
|
||||
Откройте терминал и выполните:
|
||||
|
||||
```bash filename="Terminal"
|
||||
npx create-twenty-app@latest my-twenty-app
|
||||
```
|
||||
|
||||
You will be prompted to enter a name and a description for your app. Press **Enter** to accept the defaults.
|
||||
Вам будет предложено ввести имя и описание вашего приложения. Нажмите **Enter**, чтобы принять значения по умолчанию.
|
||||
|
||||
This creates a new folder called `my-twenty-app` with everything you need.
|
||||
Будет создана новая папка `my-twenty-app` со всем необходимым.
|
||||
|
||||
<Note>
|
||||
The scaffolder supports these flags:
|
||||
Генератор поддерживает следующие флаги:
|
||||
|
||||
* `--minimal` — scaffold only the essential files, no examples (default)
|
||||
* `--exhaustive` — scaffold all example entities
|
||||
* `--name <name>` — set the app name (skips the prompt)
|
||||
* `--display-name <displayName>` — set the display name (skips the prompt)
|
||||
* `--description <description>` — set the description (skips the prompt)
|
||||
* `--skip-local-instance` — skip the local server setup prompt
|
||||
* `--minimal` — сгенерировать только основные файлы, без примеров (по умолчанию)
|
||||
* `--exhaustive` — сгенерировать все примеры сущностей
|
||||
* `--name <name>` — задать имя приложения (пропускает запрос)
|
||||
* `--display-name <displayName>` — задать отображаемое имя (пропускает запрос)
|
||||
* `--description <description>` — задать описание (пропускает запрос)
|
||||
* `--skip-local-instance` — пропустить запрос на настройку локального сервера
|
||||
</Note>
|
||||
|
||||
## Step 2: Set up a local Twenty instance
|
||||
## Шаг 2: Настройте локальный экземпляр Twenty
|
||||
|
||||
The scaffolder will ask:
|
||||
Скэффолдер спросит:
|
||||
|
||||
> **Would you like to set up a local Twenty instance?**
|
||||
> **Хотите настроить локальный экземпляр Twenty?**
|
||||
|
||||
* **Type `yes`** (recommended) — This pulls the `twenty-app-dev` Docker image and starts a local Twenty server on port `2020`. Make sure Docker is running before you continue.
|
||||
* **Type `no`** — Choose this if you already have a Twenty server running locally.
|
||||
* **Введите `yes`** (рекомендуется) — это скачает Docker-образ `twenty-app-dev` и запустит локальный сервер Twenty на порту `2020`. Перед продолжением убедитесь, что Docker запущен.
|
||||
* **Введите `no`** — выберите это, если у вас уже запущен локальный сервер Twenty.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Should start local instance?" />
|
||||
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Запустить локальный экземпляр?" />
|
||||
</div>
|
||||
|
||||
## Step 3: Sign in to your workspace
|
||||
## Шаг 3: Войдите в своё рабочее пространство
|
||||
|
||||
Next, a browser window will open with the Twenty login page. Sign in with the pre-seeded demo account:
|
||||
Затем откроется окно браузера со страницей входа в Twenty. Войдите, используя предварительно созданную демонстрационную учётную запись:
|
||||
|
||||
* **Email:** `tim@apple.dev`
|
||||
* **Password:** `tim@apple.dev`
|
||||
* **Электронная почта:** `tim@apple.dev`
|
||||
* **Пароль:** `tim@apple.dev`
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/login.png" alt="Twenty login screen" />
|
||||
<img src="/images/docs/developers/extends/apps/login.png" alt="Экран входа в Twenty" />
|
||||
</div>
|
||||
|
||||
## Step 4: Authorize the app
|
||||
## Шаг 4: Авторизуйте приложение
|
||||
|
||||
After you sign in, you will see an authorization screen. This lets your app interact with your workspace.
|
||||
После входа вы увидите экран авторизации. Это позволит вашему приложению взаимодействовать с вашим рабочим пространством.
|
||||
|
||||
Click **Authorize** to continue.
|
||||
Нажмите **Authorize**, чтобы продолжить.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/authorize.png" alt="Twenty CLI authorization screen" />
|
||||
<img src="/images/docs/developers/extends/apps/authorize.png" alt="Экран авторизации Twenty CLI" />
|
||||
</div>
|
||||
|
||||
Once authorized, your terminal will confirm that everything is set up.
|
||||
После авторизации в терминале появится подтверждение, что всё настроено.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="App scaffolded successfully" />
|
||||
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="Каркас приложения успешно создан" />
|
||||
</div>
|
||||
|
||||
## Step 5: Start developing
|
||||
## Шаг 5: Начните разработку
|
||||
|
||||
Go into your new app folder and start the development server:
|
||||
Перейдите в папку вашего нового приложения и запустите сервер разработки:
|
||||
|
||||
```bash filename="Terminal"
|
||||
cd my-twenty-app
|
||||
yarn twenty dev
|
||||
```
|
||||
|
||||
This watches your source files, rebuilds on every change, and syncs your app to the local Twenty server automatically. You should see a live status panel in your terminal.
|
||||
Он отслеживает исходные файлы, пересобирает при каждом изменении и автоматически синхронизирует ваше приложение с локальным сервером Twenty. В терминале должна появиться панель текущего статуса.
|
||||
|
||||
For more detailed output (build logs, sync requests, error traces), use the `--verbose` flag:
|
||||
Для более подробного вывода (журналы сборки, запросы синхронизации, трассировки ошибок) используйте флаг `--verbose`:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev --verbose
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Dev mode is only available on Twenty instances running in development (`NODE_ENV=development`). Production instances reject dev sync requests. Use `yarn twenty deploy` to deploy to production servers — see [Publishing Apps](/l/ru/developers/extend/apps/publishing) for details.
|
||||
Режим разработки доступен только на экземплярах Twenty, запущенных в режиме разработки (`NODE_ENV=development`). Экземпляры в продакшене отклоняют запросы синхронизации из режима разработки. Используйте `yarn twenty deploy` для развёртывания на продакшен-серверах — подробности см. в разделе [Публикация приложений](/l/ru/developers/extend/apps/publishing).
|
||||
</Warning>
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Dev mode terminal output" />
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Вывод терминала в режиме разработки" />
|
||||
</div>
|
||||
|
||||
## Step 6: See your app in Twenty
|
||||
## Шаг 6: Посмотрите своё приложение в Twenty
|
||||
|
||||
Open [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) in your browser. Navigate to **Settings > Apps** and select the **Developer** tab. You should see your app listed under **Your Apps**:
|
||||
Откройте [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) в браузере. Перейдите в **Settings > Apps** и выберите вкладку **Developer**. Вы должны увидеть своё приложение в разделе **Your Apps**:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-1.png" alt="Your Apps list showing My twenty app" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-1.png" alt="Список Your Apps с приложением My twenty app" />
|
||||
</div>
|
||||
|
||||
Click on **My twenty app** to open its **application registration**. A registration is a server-level record that describes your app — its name, unique identifier, OAuth credentials, and source (local, npm, or tarball). It lives on the server, not inside any specific workspace. When you install an app into a workspace, Twenty creates a workspace-scoped **application** that points back to this registration. One registration can be installed across multiple workspaces on the same server.
|
||||
Нажмите **My twenty app**, чтобы открыть его **регистрацию приложения**. Регистрация — это запись на уровне сервера, описывающая ваше приложение: его имя, уникальный идентификатор, учётные данные OAuth и источник (локальный, npm или tarball). Она хранится на сервере, а не внутри какого-либо конкретного рабочего пространства. Когда вы устанавливаете приложение в рабочее пространство, Twenty создаёт привязанное к рабочему пространству **приложение**, которое ссылается на эту регистрацию. Одну и ту же регистрацию можно установить в нескольких рабочих пространствах на одном сервере.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-2.png" alt="Application registration details" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-2.png" alt="Сведения о регистрации приложения" />
|
||||
</div>
|
||||
|
||||
Click **View installed app** to see the installed app. The **About** tab shows the current version and management options:
|
||||
Нажмите **View installed app**, чтобы посмотреть установленное приложение. Вкладка **About** показывает текущую версию и параметры управления:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-3.png" alt="Installed app — About tab" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-3.png" alt="Установленное приложение — вкладка About" />
|
||||
</div>
|
||||
|
||||
Switch to the **Content** tab to see everything your app provides — objects, fields, logic functions, and agents:
|
||||
Переключитесь на вкладку **Content**, чтобы увидеть всё, что предоставляет ваше приложение: объекты, поля, логические функции и агенты:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-4.png" alt="Installed app — Content tab" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-4.png" alt="Установленное приложение — вкладка Content" />
|
||||
</div>
|
||||
|
||||
You are all set! Edit any file in `src/` and the changes will be picked up automatically.
|
||||
Готово! Отредактируйте любой файл в `src/`, и изменения будут подхвачены автоматически.
|
||||
|
||||
Head over to [Building Apps](/l/ru/developers/extend/apps/building) for a detailed guide on creating objects, logic functions, front components, skills, and more.
|
||||
Перейдите к разделу [Создание приложений](/l/ru/developers/extend/apps/building) за подробным руководством по созданию объектов, логических функций, фронтенд-компонентов, навыков и многого другого.
|
||||
|
||||
---
|
||||
|
||||
## Project structure
|
||||
## Структура проекта
|
||||
|
||||
The scaffolder generates the following file structure (shown with `--exhaustive` mode, which includes examples for every entity type):
|
||||
Скэффолдер генерирует следующую структуру файлов (показано в режиме `--exhaustive`, который включает примеры для каждого типа сущностей):
|
||||
|
||||
```text filename="my-twenty-app/"
|
||||
my-twenty-app/
|
||||
@@ -190,30 +190,30 @@ my-twenty-app/
|
||||
└── example-agent.ts # Example AI agent definition
|
||||
```
|
||||
|
||||
By default (`--minimal`), only the core files are created: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`. Use `--exhaustive` to include all the example files shown above.
|
||||
По умолчанию (`--minimal`) создаются только основные файлы: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` и `logic-functions/post-install.ts`. Используйте `--exhaustive`, чтобы включить все показанные выше файлы-примеры.
|
||||
|
||||
### Key files
|
||||
### Ключевые файлы
|
||||
|
||||
| File / Folder | Назначение |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `package.json` | Declares your app name, version, and dependencies. Includes a `twenty` script so you can run `yarn twenty help` to see all commands. |
|
||||
| `src/application-config.ts` | **Required.** The main configuration file for your app. |
|
||||
| `src/roles/` | Defines roles that control what your logic functions can access. |
|
||||
| `src/logic-functions/` | Server-side functions triggered by routes, cron schedules, or database events. |
|
||||
| `src/front-components/` | React components that render inside Twenty's UI. |
|
||||
| `src/objects/` | Custom object definitions to extend your data model. |
|
||||
| `src/fields/` | Custom fields added to existing objects. |
|
||||
| `src/views/` | Saved view configurations. |
|
||||
| `src/navigation-menu-items/` | Custom links in the sidebar navigation. |
|
||||
| `src/skills/` | Навыки, расширяющие возможности ИИ-агентов Twenty. |
|
||||
| `src/agents/` | AI agents with custom prompts. |
|
||||
| `src/page-layouts/` | Custom page layouts for record views. |
|
||||
| `src/__tests__/` | Integration tests (setup + example test). |
|
||||
| `public/` | Static assets (images, fonts) served with your app. |
|
||||
| Файл / Папка | Назначение |
|
||||
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `package.json` | Содержит имя, версию и зависимости вашего приложения. Содержит скрипт `twenty`, чтобы вы могли выполнить `yarn twenty help` и увидеть все команды. |
|
||||
| `src/application-config.ts` | **Обязательно.** Основной файл конфигурации для вашего приложения. |
|
||||
| `src/roles/` | Определяет роли, которые контролируют доступ логических функций. |
|
||||
| `src/logic-functions/` | Серверные функции, запускаемые маршрутами, расписаниями cron или событиями базы данных. |
|
||||
| `src/front-components/` | Компоненты React, которые отображаются внутри интерфейса Twenty. |
|
||||
| `src/objects/` | Пользовательские определения объектов для расширения вашей модели данных. |
|
||||
| `src/fields/` | Пользовательские поля, добавляемые к существующим объектам. |
|
||||
| `src/views/` | Конфигурации сохранённых представлений. |
|
||||
| `src/navigation-menu-items/` | Пользовательские ссылки в боковой навигации. |
|
||||
| `src/skills/` | Навыки, расширяющие возможности ИИ-агентов Twenty. |
|
||||
| `src/agents/` | ИИ-агенты с пользовательскими промптами. |
|
||||
| `src/page-layouts/` | Пользовательские макеты страниц для представлений записей. |
|
||||
| `src/__tests__/` | Интеграционные тесты (настройка + пример теста). |
|
||||
| `public/` | Статические ресурсы (изображения, шрифты), обслуживаемые вместе с вашим приложением. |
|
||||
|
||||
## Managing remotes
|
||||
## Управление удалёнными серверами
|
||||
|
||||
A **remote** is a Twenty server that your app connects to. During setup, the scaffolder creates one for you automatically. You can add more remotes or switch between them at any time.
|
||||
Remote — это сервер Twenty, к которому подключается ваше приложение. Во время настройки скэффолдер автоматически создаст его для вас. Вы можете в любой момент добавлять новые remotes или переключаться между ними.
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Add a new remote (opens a browser for OAuth login)
|
||||
@@ -232,11 +232,11 @@ yarn twenty remote list
|
||||
yarn twenty remote switch <name>
|
||||
```
|
||||
|
||||
Your credentials are stored in `~/.twenty/config.json`.
|
||||
Ваши учётные данные хранятся в `~/.twenty/config.json`.
|
||||
|
||||
## Local development server (`yarn twenty server`)
|
||||
## Локальный сервер разработки (`yarn twenty server`)
|
||||
|
||||
The CLI can manage a local Twenty server running in Docker. This is the same server started automatically when you scaffold an app with `create-twenty-app`, but you can also manage it manually.
|
||||
CLI может управлять локальным сервером Twenty, запущенным в Docker. Это тот же сервер, который автоматически запускается при создании каркаса приложения с помощью `create-twenty-app`, но им можно управлять и вручную.
|
||||
|
||||
### Запуск сервера
|
||||
|
||||
@@ -244,85 +244,85 @@ The CLI can manage a local Twenty server running in Docker. This is the same ser
|
||||
yarn twenty server start
|
||||
```
|
||||
|
||||
This pulls the `twentycrm/twenty-app-dev:latest` Docker image (if not already present), creates a container named `twenty-app-dev`, and starts it on port **2020**. The CLI waits until the server passes its health check before returning.
|
||||
Эта команда скачивает Docker-образ `twentycrm/twenty-app-dev:latest` (если его ещё нет), создаёт контейнер с именем `twenty-app-dev` и запускает его на порту **2020**. CLI ждёт, пока сервер пройдёт проверку работоспособности, прежде чем вернуть управление.
|
||||
|
||||
Two Docker volumes are created to persist data between restarts:
|
||||
Создаются два тома Docker для сохранения данных между перезапусками:
|
||||
|
||||
* `twenty-app-dev-data` — PostgreSQL database
|
||||
* `twenty-app-dev-storage` — file storage
|
||||
* `twenty-app-dev-data` — база данных PostgreSQL
|
||||
* `twenty-app-dev-storage` — файловое хранилище
|
||||
|
||||
If port 2020 is already in use, you can start on a different port:
|
||||
Если порт 2020 уже используется, вы можете запустить на другом порту:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server start --port 3030
|
||||
```
|
||||
|
||||
The CLI automatically configures the container's internal `NODE_PORT` and `SERVER_URL` to match the chosen port, so logic functions, OAuth, and all other internal networking work correctly.
|
||||
CLI автоматически настраивает внутренние `NODE_PORT` и `SERVER_URL` контейнера в соответствии с выбранным портом, чтобы логические функции, OAuth и прочие внутренние сетевые взаимодействия работали корректно.
|
||||
|
||||
Once started, the server is automatically registered as the `local` remote in your CLI config.
|
||||
После запуска сервер автоматически регистрируется как remote `local` в конфигурации вашего CLI.
|
||||
|
||||
### Checking server status
|
||||
### Проверка состояния сервера
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server status
|
||||
```
|
||||
|
||||
Displays whether the server is running, its URL, and the default login credentials (`tim@apple.dev` / `tim@apple.dev`).
|
||||
Показывает, запущен ли сервер, его URL и учётные данные по умолчанию (`tim@apple.dev` / `tim@apple.dev`).
|
||||
|
||||
### Viewing server logs
|
||||
### Просмотр журналов сервера
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server logs
|
||||
```
|
||||
|
||||
Streams the container logs. Use `--lines` to control how many recent lines to show:
|
||||
Выводит журналы контейнера в потоковом режиме. Используйте `--lines`, чтобы задать, сколько последних строк показывать:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server logs --lines 100
|
||||
```
|
||||
|
||||
### Stopping the server
|
||||
### Остановка сервера
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server stop
|
||||
```
|
||||
|
||||
Stops the container. Your data is preserved in the Docker volumes — the next `start` picks up where you left off.
|
||||
Останавливает контейнер. Ваши данные сохраняются в томах Docker — следующий `start` продолжит с того места, где вы остановились.
|
||||
|
||||
### Resetting the server
|
||||
### Сброс сервера
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server reset
|
||||
```
|
||||
|
||||
Removes the container **and** deletes both Docker volumes, wiping all data. The next `start` creates a fresh instance.
|
||||
Удаляет контейнер и оба тома Docker, полностью стирая все данные. Следующий `start` создаст новый чистый экземпляр.
|
||||
|
||||
<Note>
|
||||
The server requires **Docker** to be running. If you see a "Docker not running" error, make sure Docker Desktop (or the Docker daemon) is started.
|
||||
Для работы сервера необходимо, чтобы **Docker** был запущен. Если вы видите ошибку "Docker not running", убедитесь, что запущен Docker Desktop (или демон Docker).
|
||||
</Note>
|
||||
|
||||
### Command reference
|
||||
### Справочник команд
|
||||
|
||||
| Команда | Описание |
|
||||
| -------------------------------------- | ---------------------------------------------- |
|
||||
| `yarn twenty server start` | Start the local server (pulls image if needed) |
|
||||
| `yarn twenty server start --port 3030` | Start on a custom port |
|
||||
| `yarn twenty server stop` | Stop the server (preserves data) |
|
||||
| `yarn twenty server status` | Show server status, URL, and credentials |
|
||||
| `yarn twenty server logs` | Stream server logs |
|
||||
| `yarn twenty server logs --lines 100` | Show the last 100 log lines |
|
||||
| `yarn twenty server reset` | Delete all data and start fresh |
|
||||
| Команда | Описание |
|
||||
| -------------------------------------- | -------------------------------------------------------------- |
|
||||
| `yarn twenty server start` | Запустить локальный сервер (при необходимости скачивает образ) |
|
||||
| `yarn twenty server start --port 3030` | Запустить на пользовательском порту |
|
||||
| `yarn twenty server stop` | Остановить сервер (данные сохраняются) |
|
||||
| `yarn twenty server status` | Показать состояние сервера, URL и учётные данные |
|
||||
| `yarn twenty server logs` | Потоковый вывод журналов сервера |
|
||||
| `yarn twenty server logs --lines 100` | Показать последние 100 строк журнала |
|
||||
| `yarn twenty server reset` | Удалить все данные и начать с чистого листа |
|
||||
|
||||
## CI with GitHub Actions
|
||||
## CI с GitHub Actions
|
||||
|
||||
The scaffolder generates a ready-to-use GitHub Actions workflow at `.github/workflows/ci.yml`. It runs your integration tests automatically on every push to `main` and on pull requests.
|
||||
Скэффолдер генерирует готовый к использованию workflow GitHub Actions в `.github/workflows/ci.yml`. Он автоматически запускает ваши интеграционные тесты при каждом пуше в `main` и в pull request'ах.
|
||||
|
||||
The workflow:
|
||||
Рабочий процесс:
|
||||
|
||||
1. Checks out your code
|
||||
2. Spins up a temporary Twenty server using the `twentyhq/twenty/.github/actions/spawn-twenty-docker-image` action
|
||||
3. Installs dependencies with `yarn install --immutable`
|
||||
4. Runs `yarn test` with `TWENTY_API_URL` and `TWENTY_API_KEY` injected from the action outputs
|
||||
1. Извлекает ваш код
|
||||
2. Поднимает временный сервер Twenty с помощью экшена `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
|
||||
3. Устанавливает зависимости с помощью `yarn install --immutable`
|
||||
4. Запускает `yarn test` с `TWENTY_API_URL` и `TWENTY_API_KEY`, переданными из выходных данных экшена
|
||||
|
||||
```yaml .github/workflows/ci.yml
|
||||
name: CI
|
||||
@@ -369,21 +369,21 @@ jobs:
|
||||
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
|
||||
```
|
||||
|
||||
You don't need to configure any secrets — the `spawn-twenty-docker-image` action starts an ephemeral Twenty server directly in the runner and outputs the connection details. The `GITHUB_TOKEN` secret is provided automatically by GitHub.
|
||||
Вам не нужно настраивать секреты — экшен `spawn-twenty-docker-image` запускает эфемерный сервер Twenty прямо в раннере и выводит данные для подключения. Секрет `GITHUB_TOKEN` предоставляется GitHub автоматически.
|
||||
|
||||
To pin a specific Twenty version instead of `latest`, change the `TWENTY_VERSION` environment variable at the top of the workflow.
|
||||
Чтобы закрепить конкретную версию Twenty вместо `latest`, измените переменную окружения `TWENTY_VERSION` в начале workflow.
|
||||
|
||||
## Ручная настройка (без генератора)
|
||||
|
||||
If you prefer to set things up yourself instead of using `create-twenty-app`, you can do it in two steps.
|
||||
Если вы предпочитаете настроить всё самостоятельно, не используя `create-twenty-app`, это можно сделать в два шага.
|
||||
|
||||
**1. Add `twenty-sdk` and `twenty-client-sdk` as dependencies:**
|
||||
**1. Добавьте `twenty-sdk` и `twenty-client-sdk` в зависимости:**
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn add twenty-sdk twenty-client-sdk
|
||||
```
|
||||
|
||||
**2. Add a `twenty` script to your `package.json`:**
|
||||
**2. Добавьте скрипт `twenty` в ваш `package.json`:**
|
||||
|
||||
```json filename="package.json"
|
||||
{
|
||||
@@ -393,19 +393,19 @@ yarn add twenty-sdk twenty-client-sdk
|
||||
}
|
||||
```
|
||||
|
||||
You can now run `yarn twenty dev`, `yarn twenty help`, and all other commands.
|
||||
Теперь вы можете запускать `yarn twenty dev`, `yarn twenty help` и все остальные команды.
|
||||
|
||||
<Note>
|
||||
Do not install `twenty-sdk` globally. Always use it as a local project dependency so that each project can pin its own version.
|
||||
Не устанавливайте `twenty-sdk` глобально. Всегда используйте его как локальную зависимость проекта, чтобы каждый проект мог закреплять свою версию.
|
||||
</Note>
|
||||
|
||||
## Устранение неполадок
|
||||
|
||||
If you run into issues:
|
||||
Если столкнётесь с проблемами:
|
||||
|
||||
* Make sure **Docker is running** before starting the scaffolder with a local instance.
|
||||
* Make sure you are using **Node.js 24+** (`node -v` to check).
|
||||
* Make sure **Corepack is enabled** (`corepack enable`) so Yarn 4 is available.
|
||||
* Try deleting `node_modules` and running `yarn install` again if dependencies seem broken.
|
||||
* Перед запуском генератора с локальным экземпляром убедитесь, что **Docker запущен**.
|
||||
* Убедитесь, что используете **Node.js 24+** (`node -v` для проверки).
|
||||
* Убедитесь, что **Corepack включён** (`corepack enable`), чтобы Yarn 4 был доступен.
|
||||
* Если зависимости, похоже, повреждены, попробуйте удалить `node_modules` и снова выполнить `yarn install`.
|
||||
|
||||
Still stuck? Ask for help on the [Twenty Discord](https://discord.com/channels/1130383047699738754/1130386664812982322).
|
||||
Все ещё не получается? Попросите помощи на [Discord-сервере Twenty](https://discord.com/channels/1130383047699738754/1130386664812982322).
|
||||
|
||||
@@ -4,24 +4,24 @@ description: Nesneleri, mantık fonksiyonlarını, ön uç bileşenlerini ve dah
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Apps are currently in alpha. The feature works but is still evolving.
|
||||
Uygulamalar şu anda alfa aşamasında. Özellik işlevsel ancak hâlâ gelişmekte.
|
||||
</Warning>
|
||||
|
||||
The `twenty-sdk` package provides typed building blocks to create your app. This page covers every entity type and API client available in the SDK.
|
||||
`twenty-sdk` paketi, uygulamanızı oluşturmak için türlendirilmiş yapı taşları sağlar. Bu sayfa, SDK'da mevcut olan tüm varlık türlerini ve API istemcilerini kapsar.
|
||||
|
||||
## DefineEntity functions
|
||||
## DefineEntity fonksiyonları
|
||||
|
||||
The SDK provides functions to define your app entities. You must use `export default defineEntity({...})` for the SDK to detect your entities. Bu fonksiyonlar, derleme zamanında yapılandırmanızı doğrular ve IDE otomatik tamamlama ile tür güvenliği sağlar.
|
||||
SDK, uygulama varlıklarınızı tanımlamak için fonksiyonlar sağlar. SDK'nin varlıklarınızı algılayabilmesi için `export default defineEntity({...})` kullanmanız gerekir. Bu fonksiyonlar, derleme zamanında yapılandırmanızı doğrular ve IDE otomatik tamamlama ile tür güvenliği sağlar.
|
||||
|
||||
<Note>
|
||||
**File organization is up to you.**
|
||||
Entity detection is AST-based — the SDK finds `export default defineEntity(...)` calls regardless of where the file lives. Grouping files by type (e.g., `logic-functions/`, `roles/`) is just a convention, not a requirement.
|
||||
**Dosya organizasyonu size kalmış.**
|
||||
Varlık algılama AST tabanlıdır — dosyanın nerede bulunduğundan bağımsız olarak SDK `export default defineEntity(...)` çağrılarını bulur. Dosyaları türe göre gruplamak (örn. `logic-functions/`, `roles/`) bir gereklilik değil, yalnızca bir gelenektir.
|
||||
</Note>
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="defineRole" description="Rol izinlerini ve nesne erişimini yapılandırın">
|
||||
|
||||
Roles encapsulate permissions on your workspace's objects and actions.
|
||||
Roller, çalışma alanınızdaki nesneler ve eylemler üzerindeki izinleri kapsar.
|
||||
|
||||
```ts restricted-company-role.ts
|
||||
import {
|
||||
@@ -69,12 +69,12 @@ export default defineRole({
|
||||
</Accordion>
|
||||
<Accordion title="defineApplication" description="Uygulama meta verilerini yapılandırın (zorunlu, uygulama başına bir adet)">
|
||||
|
||||
Every app must have exactly one `defineApplication` call that describes:
|
||||
Her uygulamanın, şunları tanımlayan tam olarak bir adet `defineApplication` çağrısı olmalıdır:
|
||||
|
||||
* **Identity**: identifiers, display name, and description.
|
||||
* **Permissions**: which role its functions and front components use.
|
||||
* **(Optional) Variables**: key–value pairs exposed to your functions as environment variables.
|
||||
* **(Optional) Pre-install / post-install functions**: logic functions that run before or after installation.
|
||||
* **Kimlik**: tanımlayıcılar, görünen ad ve açıklama.
|
||||
* **İzinler**: işlevlerinin ve ön bileşenlerinin hangi rolü kullandığı.
|
||||
* **(İsteğe bağlı) Değişkenler**: fonksiyonlarınıza ortam değişkenleri olarak sunulan anahtar–değer çiftleri.
|
||||
* **(İsteğe bağlı) Kurulum öncesi / kurulum sonrası fonksiyonlar**: kurulumdan önce veya sonra çalışan mantık fonksiyonları.
|
||||
|
||||
```ts src/application-config.ts
|
||||
import { defineApplication } from 'twenty-sdk';
|
||||
@@ -98,21 +98,21 @@ export default defineApplication({
|
||||
```
|
||||
|
||||
Notlar:
|
||||
* `universalIdentifier` fields are deterministic IDs you own. Generate them once and keep them stable across syncs.
|
||||
* `applicationVariables` become environment variables for your functions and front components (e.g., `DEFAULT_RECIPIENT_NAME` is available as `process.env.DEFAULT_RECIPIENT_NAME`).
|
||||
* `defaultRoleUniversalIdentifier` must reference a role defined with `defineRole()` (see above).
|
||||
* Pre-install and post-install functions are detected automatically during the manifest build — you do not need to reference them in `defineApplication()`.
|
||||
* `universalIdentifier` alanları, size ait deterministik kimliklerdir. Bunları bir kez oluşturun ve senkronizasyonlar boyunca kararlı tutun.
|
||||
* `applicationVariables`, fonksiyonlarınız ve ön bileşenleriniz için ortam değişkenlerine dönüşür (örn. `DEFAULT_RECIPIENT_NAME`, `process.env.DEFAULT_RECIPIENT_NAME` olarak kullanılabilir).
|
||||
* `defaultRoleUniversalIdentifier`, `defineRole()` ile tanımlanmış bir role referans vermelidir (yukarıya bakın).
|
||||
* Kurulum öncesi ve kurulum sonrası fonksiyonlar manifest derlemesi sırasında otomatik olarak algılanır — bunlara `defineApplication()` içinde referans vermeniz gerekmez.
|
||||
|
||||
#### Pazaryeri meta verileri
|
||||
|
||||
If you plan to [publish your app](/l/tr/developers/extend/apps/publishing), these optional fields control how it 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` | Yazar veya şirket adı |
|
||||
| `category` | Pazaryerinde filtreleme için uygulama kategorisi |
|
||||
| `logoUrl` | Path to your app logo (e.g., `public/logo.png`) |
|
||||
| `screenshots` | Array of screenshot paths (e.g., `public/screenshot-1.png`) |
|
||||
| `logoUrl` | Uygulamanızın logosuna giden yol (örn. `public/logo.png`) |
|
||||
| `screenshots` | Ekran görüntüsü yollarının dizisi (örn. `public/screenshot-1.png`) |
|
||||
| `aboutDescription` | "Hakkında" sekmesi için daha uzun bir markdown açıklaması. Belirtilmezse, pazaryeri npm'deki paketin `README.md` dosyasını kullanır |
|
||||
| `websiteUrl` | Web sitenize bağlantı |
|
||||
| `termsUrl` | Hizmet Koşulları'na bağlantı |
|
||||
@@ -121,15 +121,15 @@ If you plan to [publish your app](/l/tr/developers/extend/apps/publishing), thes
|
||||
|
||||
#### Roller ve izinler
|
||||
|
||||
The `defaultRoleUniversalIdentifier` in `application-config.ts` designates the default role used by your app's logic functions and front components. See `defineRole` above for details.
|
||||
`application-config.ts` içindeki `defaultRoleUniversalIdentifier`, uygulamanızın mantık fonksiyonları ve ön bileşenleri tarafından kullanılan varsayılan rolü belirtir. Ayrıntılar için yukarıdaki `defineRole` bölümüne bakın.
|
||||
|
||||
* The runtime token injected as `TWENTY_APP_ACCESS_TOKEN` is derived from this role.
|
||||
* The typed client is restricted to the permissions granted to that role.
|
||||
* Follow least-privilege: create a dedicated role with only the permissions your functions need.
|
||||
* `TWENTY_APP_ACCESS_TOKEN` olarak enjekte edilen çalışma zamanı belirteci bu rolden türetilir.
|
||||
* Türlendirilmiş istemci, o role tanınan izinlerle sınırlandırılır.
|
||||
* En az ayrıcalık ilkesini izleyin: Yalnızca fonksiyonlarınızın ihtiyaç duyduğu izinlere sahip özel bir rol oluşturun.
|
||||
|
||||
##### Default function role
|
||||
##### Varsayılan fonksiyon rolü
|
||||
|
||||
When you scaffold a new app, the CLI creates a default role file:
|
||||
Yeni bir uygulama iskeleti oluşturduğunuzda, CLI varsayılan bir rol dosyası oluşturur:
|
||||
|
||||
```ts src/roles/default-role.ts
|
||||
import { defineRole, PermissionFlag } from 'twenty-sdk';
|
||||
@@ -155,16 +155,16 @@ export default defineRole({
|
||||
});
|
||||
```
|
||||
|
||||
This role's `universalIdentifier` is referenced in `application-config.ts` as `defaultRoleUniversalIdentifier`:
|
||||
Bu rolün `universalIdentifier` değeri, `application-config.ts` içinde `defaultRoleUniversalIdentifier` olarak referans verilir:
|
||||
|
||||
* **\*.role.ts** defines what the role can do.
|
||||
* **\*.role.ts**, bir rolün neler yapabileceğini tanımlar.
|
||||
* **application-config.ts**, fonksiyonlarınızın izinlerini devralması için bu role işaret eder.
|
||||
|
||||
Notlar:
|
||||
* Oluşturulan rolden başlayın ve en az ayrıcalık ilkesini izleyerek bunu aşamalı olarak kısıtlayın.
|
||||
* Replace `objectPermissions` and `fieldPermissions` with the objects and fields your functions actually need.
|
||||
* `permissionFlags`, platform düzeyindeki yeteneklere erişimi kontrol eder. Keep them minimal.
|
||||
* See a working example: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
|
||||
* `objectPermissions` ve `fieldPermissions` değerlerini, fonksiyonlarınızın ihtiyaç duyduğu nesneler ve alanlarla değiştirin.
|
||||
* `permissionFlags`, platform düzeyindeki yeteneklere erişimi kontrol eder. Bunları asgari düzeyde tutun.
|
||||
* Çalışan bir örnek için bkz.: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="defineObject" description="Alanlara sahip özel nesneler tanımlayın">
|
||||
@@ -256,7 +256,7 @@ ancak bu önerilmez.
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="defineField — Standard fields" description="Mevcut nesneleri ek alanlarla genişletin">
|
||||
<Accordion title="defineField — Standart alanlar" description="Mevcut nesneleri ek alanlarla genişletin">
|
||||
|
||||
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:
|
||||
|
||||
@@ -284,7 +284,7 @@ export default defineField({
|
||||
* `defineField()`, `defineObject()` ile oluşturmadığınız nesnelere alan eklemenin tek yoludur.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="defineField — Relation fields" description="Connect objects together with bidirectional relations">
|
||||
<Accordion title="defineField — İlişki alanları" description="Nesneleri çift yönlü ilişkilerle birbirine bağlayın">
|
||||
|
||||
İ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.
|
||||
|
||||
@@ -443,7 +443,7 @@ export default defineObject({
|
||||
});
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="defineLogicFunction" description="Define logic functions and their triggers">
|
||||
<Accordion title="defineLogicFunction" description="Mantık fonksiyonlarını ve tetikleyicilerini tanımlayın">
|
||||
|
||||
Her fonksiyon dosyası, bir işleyici ve isteğe bağlı tetikleyiciler içeren bir yapılandırmayı dışa aktarmak için `defineLogicFunction()` kullanır.
|
||||
|
||||
@@ -487,15 +487,15 @@ export default defineLogicFunction({
|
||||
});
|
||||
```
|
||||
|
||||
Available trigger types:
|
||||
* **httpRoute**: Exposes your function on an HTTP path and method **under the `/s/` endpoint**:
|
||||
> e.g. `path: '/post-card/create'` is callable at `https://your-twenty-server.com/s/post-card/create`
|
||||
Kullanılabilir tetikleyici türleri:
|
||||
* **httpRoute**: Fonksiyonunuzu bir HTTP yolu ve yöntemiyle **`/s/` uç noktasının altında** kullanıma sunar:
|
||||
> örn. `path: '/post-card/create'` `https://your-twenty-server.com/s/post-card/create` adresinden çağrılabilir
|
||||
* **cron**: Bir CRON ifadesi kullanarak fonksiyonunuzu bir zamanlamayla çalıştırır.
|
||||
* **databaseEvent**: Çalışma alanı nesnesi yaşam döngüsü olaylarında çalışır. Olay işlemi `updated` olduğunda, dinlenecek belirli alanlar `updatedFields` dizisinde belirtilebilir. Tanımsız veya boş bırakılırsa, herhangi bir güncelleme fonksiyonu tetikler.
|
||||
> e.g. `person.updated`, `*.created`, `company.*`
|
||||
> örn. `person.updated`, `*.created`, `company.*`
|
||||
|
||||
<Note>
|
||||
You can also manually execute a function using the CLI:
|
||||
Bir fonksiyonu CLI kullanarak manuel olarak da çalıştırabilirsiniz:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty exec -n create-new-post-card -p '{"key": "value"}'
|
||||
@@ -505,7 +505,7 @@ yarn twenty exec -n create-new-post-card -p '{"key": "value"}'
|
||||
yarn twenty exec -y e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf
|
||||
```
|
||||
|
||||
You can watch logs with:
|
||||
Günlükleri şu şekilde izleyebilirsiniz:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty logs
|
||||
@@ -514,9 +514,9 @@ yarn twenty logs
|
||||
|
||||
#### Rota tetikleyicisi yükü
|
||||
|
||||
When a route trigger invokes your logic function, it receives a `RoutePayload` object that follows the
|
||||
[AWS HTTP API v2 format](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html).
|
||||
Import the `RoutePayload` type from `twenty-sdk`:
|
||||
Bir rota tetikleyicisi mantık fonksiyonunuzu çağırdığında,
|
||||
[AWS HTTP API v2 formatını](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html) izleyen bir `RoutePayload` nesnesi alır.
|
||||
`RoutePayload` türünü `twenty-sdk` içinden içe aktarın:
|
||||
|
||||
```ts
|
||||
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';
|
||||
@@ -533,9 +533,9 @@ const handler = async (event: RoutePayload) => {
|
||||
|
||||
| Özellik | Tür | Açıklama | Örnek |
|
||||
| ---------------------------- | ------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
||||
| `headers` | `Record<string, string \| undefined>` | HTTP başlıkları (`forwardedRequestHeaders` içinde listelenenlerle sınırlı) | see section below |
|
||||
| `headers` | `Record<string, string \| undefined>` | HTTP başlıkları (`forwardedRequestHeaders` içinde listelenenlerle sınırlı) | aşağıdaki bölüme bakın |
|
||||
| `queryStringParameters` | `Record<string, string \| undefined>` | Sorgu dizesi parametreleri (birden çok değer virgülle birleştirilir) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
|
||||
| `pathParameters` | `Record<string, string \| undefined>` | Path parameters extracted from the route pattern | `/users/:id`, `/users/123` -> `{ id: '123' }` |
|
||||
| `pathParameters` | `Record<string, string \| undefined>` | Rota deseninden çıkarılan yol parametreleri | `/users/:id`, `/users/123` -> `{ id: '123' }` |
|
||||
| `body` | `object \| null` | Ayrıştırılmış istek gövdesi (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
|
||||
| `isBase64Encoded` | `boolean` | Gövdenin base64 ile kodlanıp kodlanmadığı | |
|
||||
| `requestContext.http.method` | `string` | HTTP yöntemi (GET, POST, PUT, PATCH, DELETE) | |
|
||||
@@ -545,7 +545,7 @@ const handler = async (event: RoutePayload) => {
|
||||
#### forwardedRequestHeaders
|
||||
|
||||
Varsayılan olarak, güvenlik nedenleriyle gelen isteklerden HTTP başlıkları mantık fonksiyonunuza **aktarılmaz**.
|
||||
To access specific headers, list them in the `forwardedRequestHeaders` array:
|
||||
Belirli başlıklara erişmek için bunları `forwardedRequestHeaders` dizisinde listeleyin:
|
||||
|
||||
```ts
|
||||
export default defineLogicFunction({
|
||||
@@ -561,7 +561,7 @@ export default defineLogicFunction({
|
||||
});
|
||||
```
|
||||
|
||||
In your handler, access the forwarded headers like this:
|
||||
İşleyicinizde, iletilen başlıklara şu şekilde erişin:
|
||||
|
||||
```ts
|
||||
const handler = async (event: RoutePayload) => {
|
||||
@@ -574,14 +574,14 @@ const handler = async (event: RoutePayload) => {
|
||||
```
|
||||
|
||||
<Note>
|
||||
Başlık adları küçük harfe normalize edilir. Access them using lowercase keys (e.g., `event.headers['content-type']`).
|
||||
Başlık adları küçük harfe normalize edilir. Onlara küçük harfli anahtarlarla erişin (örneğin, `event.headers['content-type']`).
|
||||
</Note>
|
||||
|
||||
#### Exposing a function as a tool
|
||||
#### Bir fonksiyonu araç olarak sunma
|
||||
|
||||
Mantık işlevleri, yapay zeka ajanları ve iş akışları için **araçlar** olarak sunulabilir. When marked as a tool, a function becomes discoverable by Twenty's AI features and can be used in workflow automations.
|
||||
Mantık işlevleri, yapay zeka ajanları ve iş akışları için **araçlar** olarak sunulabilir. Bir fonksiyon bir araç olarak işaretlendiğinde, Twenty'nin yapay zeka özellikleri tarafından keşfedilebilir hâle gelir ve iş akışı otomasyonlarında kullanılabilir.
|
||||
|
||||
To mark a logic function as a tool, set `isTool: true`:
|
||||
Bir mantık fonksiyonunu araç olarak işaretlemek için `isTool: true` olarak ayarlayın:
|
||||
|
||||
```ts src/logic-functions/enrich-company.logic-function.ts
|
||||
import { defineLogicFunction } from 'twenty-sdk';
|
||||
@@ -617,8 +617,8 @@ export default defineLogicFunction({
|
||||
|
||||
Önemli noktalar:
|
||||
|
||||
* You can combine `isTool` with triggers — a function can be both a tool (callable by AI agents) and triggered by events at the same time.
|
||||
* **`toolInputSchema`** (optional): A JSON Schema object describing the parameters your function accepts. The schema is computed automatically from source code static analysis, but you can set it explicitly:
|
||||
* `isTool` özelliğini tetikleyicilerle birleştirebilirsiniz — bir fonksiyon aynı anda hem bir araç (yapay zeka ajanları tarafından çağrılabilir) olabilir hem de olaylar tarafından tetiklenebilir.
|
||||
* **`toolInputSchema`** (isteğe bağlı): Fonksiyonunuzun kabul ettiği parametreleri tanımlayan bir JSON Schema nesnesi. Şema, kaynak kodun statik analizinden otomatik olarak oluşturulur, ancak bunu açıkça belirleyebilirsiniz:
|
||||
|
||||
```ts
|
||||
export default defineLogicFunction({
|
||||
@@ -715,11 +715,11 @@ yarn twenty exec --postInstall
|
||||
</Accordion>
|
||||
<Accordion title="defineFrontComponent" description="Özel kullanıcı arayüzü için ön uç bileşenlerini tanımlayın">
|
||||
|
||||
Front components are React components that render directly inside Twenty's UI. They run in an **isolated Web Worker** using Remote DOM — your code is sandboxed but renders natively in the page, not in an iframe.
|
||||
Ön uç bileşenler, Twenty'nin UI'si içinde doğrudan görüntülenen React bileşenleridir. Remote DOM kullanan izole bir Web Worker içinde çalışırlar — kodunuz izole bir ortamda (sandbox) çalışır ancak bir iframe içinde değil, sayfada yerel olarak işlenir.
|
||||
|
||||
#### Basic example
|
||||
#### Basit örnek
|
||||
|
||||
The quickest way to see a front component in action is to register it as a **command**. Adding a `command` field with `isPinned: true` makes it appear as a quick-action button in the top-right corner of the page — no page layout needed:
|
||||
Bir ön bileşeni çalışırken görmenin en hızlı yolu, onu bir **komut** olarak kaydetmektir. `isPinned: true` ile bir `command` alanı eklemek, sayfanın sağ üst köşesinde hızlı işlem düğmesi olarak görünmesini sağlar — herhangi bir sayfa düzenine gerek yoktur:
|
||||
|
||||
```tsx src/front-components/hello-world.tsx
|
||||
import { defineFrontComponent } from 'twenty-sdk';
|
||||
@@ -749,24 +749,24 @@ export default defineFrontComponent({
|
||||
});
|
||||
```
|
||||
|
||||
After syncing with `yarn twenty dev`, the quick action appears in the top-right corner of the page:
|
||||
`yarn twenty dev` ile senkronize ettikten sonra, hızlı işlem sayfanın sağ üst köşesinde görünür:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Quick action button in the top-right corner" />
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Sağ üst köşedeki hızlı işlem düğmesi" />
|
||||
</div>
|
||||
|
||||
Click it to render the component inline.
|
||||
Bileşeni satır içi işlemek için üzerine tıklayın.
|
||||
|
||||
{/* TODO: add screenshot of the rendered front component */}
|
||||
|
||||
#### Configuration fields
|
||||
#### Yapılandırma alanları
|
||||
|
||||
| Alan | Zorunlu | Açıklama |
|
||||
| --------------------- | ------- | ----------------------------------------------------------------------------------- |
|
||||
| `universalIdentifier` | Evet | Stable unique ID for this component |
|
||||
| `component` | Evet | A React component function |
|
||||
| `name` | Hayır | Display name |
|
||||
| `description` | Hayır | Description of what the component does |
|
||||
| `universalIdentifier` | Evet | Bu bileşen için kararlı benzersiz kimlik |
|
||||
| `component` | Evet | Bir React bileşen fonksiyonu |
|
||||
| `name` | Hayır | Görünen ad |
|
||||
| `description` | Hayır | Bileşenin ne yaptığına dair açıklama |
|
||||
| `isHeadless` | Hayır | Set to `true` if the component has no visible UI (see below) |
|
||||
| `command` | Hayır | Register the component as a command (see [command options](#command-options) below) |
|
||||
|
||||
|
||||
@@ -4,142 +4,142 @@ description: İlk Twenty uygulamanızı dakikalar içinde oluşturun.
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Apps are currently in alpha. The feature works but is still evolving.
|
||||
Uygulamalar şu anda alfa aşamasında. Özellik işlevsel ancak hâlâ gelişmekte.
|
||||
</Warning>
|
||||
|
||||
Uygulamalar, Twenty'yi özel nesneler, alanlar, mantık işlevleri, Yapay Zeka yetenekleri ve UI bileşenleriyle genişletmenizi sağlar — tümü kod olarak yönetilir.
|
||||
|
||||
## Ön Gereksinimler
|
||||
|
||||
Before you begin, make sure the following is installed on your machine:
|
||||
Başlamadan önce, makinenizde aşağıdakilerin kurulu olduğundan emin olun:
|
||||
|
||||
* **Node.js 24+** — [Download here](https://nodejs.org/)
|
||||
* **Yarn 4** — Comes with Node.js via Corepack. Enable it by running `corepack enable`
|
||||
* **Docker** — [Download here](https://www.docker.com/products/docker-desktop/). Required to run a local Twenty instance. Not needed if you already have a Twenty server running.
|
||||
* **Node.js 24+** — [Buradan indirin](https://nodejs.org/)
|
||||
* **Yarn 4** — Corepack aracılığıyla Node.js ile birlikte gelir. `corepack enable` komutunu çalıştırarak etkinleştirin
|
||||
* **Docker** — [Buradan indirin](https://www.docker.com/products/docker-desktop/). Yerel bir Twenty örneğini çalıştırmak için gereklidir. Zaten çalışan bir Twenty sunucunuz varsa gerekmez.
|
||||
|
||||
## Step 1: Scaffold your app
|
||||
## Adım 1: Uygulamanızın iskeletini oluşturun
|
||||
|
||||
Open a terminal and run:
|
||||
Bir terminal açın ve şunu çalıştırın:
|
||||
|
||||
```bash filename="Terminal"
|
||||
npx create-twenty-app@latest my-twenty-app
|
||||
```
|
||||
|
||||
You will be prompted to enter a name and a description for your app. Press **Enter** to accept the defaults.
|
||||
Uygulamanız için bir ad ve açıklama girmeniz istenecektir. Varsayılanları kabul etmek için **Enter** tuşuna basın.
|
||||
|
||||
This creates a new folder called `my-twenty-app` with everything you need.
|
||||
Bu, `my-twenty-app` adlı, ihtiyacınız olan her şeyi içeren yeni bir klasör oluşturur.
|
||||
|
||||
<Note>
|
||||
The scaffolder supports these flags:
|
||||
İskelet oluşturucu şu bayrakları destekler:
|
||||
|
||||
* `--minimal` — scaffold only the essential files, no examples (default)
|
||||
* `--exhaustive` — scaffold all example entities
|
||||
* `--name <name>` — set the app name (skips the prompt)
|
||||
* `--display-name <displayName>` — set the display name (skips the prompt)
|
||||
* `--description <description>` — set the description (skips the prompt)
|
||||
* `--skip-local-instance` — skip the local server setup prompt
|
||||
* `--minimal` — yalnızca temel dosyaların iskeletini oluşturur, örnek yok (varsayılan)
|
||||
* `--exhaustive` — tüm örnek varlıkların iskeletini oluşturur
|
||||
* `--name <name>` — uygulama adını ayarlar (istemi atlar)
|
||||
* `--display-name <displayName>` — görünen adı ayarlar (istemi atlar)
|
||||
* `--description <description>` — açıklamayı ayarlar (istemi atlar)
|
||||
* `--skip-local-instance` — yerel sunucu kurulum istemini atlar
|
||||
</Note>
|
||||
|
||||
## Step 2: Set up a local Twenty instance
|
||||
## Adım 2: Yerel bir Twenty örneği kurun
|
||||
|
||||
The scaffolder will ask:
|
||||
İskelet oluşturucu şunu soracaktır:
|
||||
|
||||
> **Would you like to set up a local Twenty instance?**
|
||||
> **Yerel bir Twenty örneği kurmak ister misiniz?**
|
||||
|
||||
* **Type `yes`** (recommended) — This pulls the `twenty-app-dev` Docker image and starts a local Twenty server on port `2020`. Make sure Docker is running before you continue.
|
||||
* **Type `no`** — Choose this if you already have a Twenty server running locally.
|
||||
* **`yes` yazın** (önerilir) — Bu, `twenty-app-dev` Docker imajını çeker ve `2020` portunda yerel bir Twenty sunucusu başlatır. Devam etmeden önce Docker'ın çalıştığından emin olun.
|
||||
* **`no` yazın** — Yerelde zaten çalışan bir Twenty sunucunuz varsa bunu seçin.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Should start local instance?" />
|
||||
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Yerel örnek başlatılsın mı?" />
|
||||
</div>
|
||||
|
||||
## Step 3: Sign in to your workspace
|
||||
## Adım 3: Çalışma alanınıza giriş yapın
|
||||
|
||||
Next, a browser window will open with the Twenty login page. Sign in with the pre-seeded demo account:
|
||||
Ardından, Twenty oturum açma sayfasıyla bir tarayıcı penceresi açılacaktır. Önceden eklenmiş demo hesabıyla oturum açın:
|
||||
|
||||
* **Email:** `tim@apple.dev`
|
||||
* **Password:** `tim@apple.dev`
|
||||
* **E-posta:** `tim@apple.dev`
|
||||
* **Parola:** `tim@apple.dev`
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/login.png" alt="Twenty login screen" />
|
||||
<img src="/images/docs/developers/extends/apps/login.png" alt="Twenty oturum açma ekranı" />
|
||||
</div>
|
||||
|
||||
## Step 4: Authorize the app
|
||||
## Adım 4: Uygulamayı yetkilendirin
|
||||
|
||||
After you sign in, you will see an authorization screen. This lets your app interact with your workspace.
|
||||
Oturum açtıktan sonra bir yetkilendirme ekranı göreceksiniz. Bu, uygulamanızın çalışma alanınızla etkileşim kurmasını sağlar.
|
||||
|
||||
Click **Authorize** to continue.
|
||||
Devam etmek için **Authorize**'a tıklayın.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/authorize.png" alt="Twenty CLI authorization screen" />
|
||||
<img src="/images/docs/developers/extends/apps/authorize.png" alt="Twenty CLI yetkilendirme ekranı" />
|
||||
</div>
|
||||
|
||||
Once authorized, your terminal will confirm that everything is set up.
|
||||
Yetkilendirildikten sonra terminaliniz her şeyin kurulduğunu onaylayacaktır.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="App scaffolded successfully" />
|
||||
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="Uygulama iskeleti başarıyla oluşturuldu" />
|
||||
</div>
|
||||
|
||||
## Step 5: Start developing
|
||||
## Adım 5: Geliştirmeye başlayın
|
||||
|
||||
Go into your new app folder and start the development server:
|
||||
Yeni uygulama klasörünüze gidin ve geliştirme sunucusunu başlatın:
|
||||
|
||||
```bash filename="Terminal"
|
||||
cd my-twenty-app
|
||||
yarn twenty dev
|
||||
```
|
||||
|
||||
This watches your source files, rebuilds on every change, and syncs your app to the local Twenty server automatically. You should see a live status panel in your terminal.
|
||||
Bu, kaynak dosyalarınızı izler, her değişiklikte yeniden derler ve uygulamanızı yerel Twenty sunucusuyla otomatik olarak eşitler. Terminalinizde canlı bir durum paneli görmelisiniz.
|
||||
|
||||
For more detailed output (build logs, sync requests, error traces), use the `--verbose` flag:
|
||||
Daha ayrıntılı çıktı (derleme günlükleri, eşitleme istekleri, hata izleri) için `--verbose` bayrağını kullanın:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev --verbose
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Dev mode is only available on Twenty instances running in development (`NODE_ENV=development`). Production instances reject dev sync requests. Use `yarn twenty deploy` to deploy to production servers — see [Publishing Apps](/l/tr/developers/extend/apps/publishing) for details.
|
||||
Geliştirme modu yalnızca geliştirme ortamında (`NODE_ENV=development`) çalışan Twenty örneklerinde kullanılabilir. Üretim örnekleri geliştirme eşitleme isteklerini reddeder. Üretim sunucularına dağıtmak için `yarn twenty deploy` komutunu kullanın — ayrıntılar için [Uygulamaları Yayınlama](/l/tr/developers/extend/apps/publishing) bölümüne bakın.
|
||||
</Warning>
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Dev mode terminal output" />
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Geliştirme modu terminal çıktısı" />
|
||||
</div>
|
||||
|
||||
## Step 6: See your app in Twenty
|
||||
## Adım 6: Uygulamanızı Twenty'de görün
|
||||
|
||||
Open [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) in your browser. Navigate to **Settings > Apps** and select the **Developer** tab. You should see your app listed under **Your Apps**:
|
||||
Tarayıcınızda [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) adresini açın. **Settings > Apps** bölümüne gidin ve **Developer** sekmesini seçin. **Your Apps** altında uygulamanızın listelendiğini görmelisiniz:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-1.png" alt="Your Apps list showing My twenty app" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-1.png" alt="Your Apps listesinde My twenty app gösteriliyor" />
|
||||
</div>
|
||||
|
||||
Click on **My twenty app** to open its **application registration**. A registration is a server-level record that describes your app — its name, unique identifier, OAuth credentials, and source (local, npm, or tarball). It lives on the server, not inside any specific workspace. When you install an app into a workspace, Twenty creates a workspace-scoped **application** that points back to this registration. One registration can be installed across multiple workspaces on the same server.
|
||||
**My twenty app** üzerine tıklayarak **uygulama kaydını** açın. Kayıt, uygulamanızı tanımlayan sunucu düzeyinde bir kayıttır — adını, benzersiz tanımlayıcısını, OAuth kimlik bilgilerini ve kaynağını (yerel, npm veya tarball). Belirli bir çalışma alanının içinde değil, sunucuda bulunur. Bir uygulamayı bir çalışma alanına kurduğunuzda, Twenty bu kayda işaret eden, çalışma alanı kapsamında bir **uygulama** oluşturur. Tek bir kayıt, aynı sunucudaki birden çok çalışma alanına kurulabilir.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-2.png" alt="Application registration details" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-2.png" alt="Uygulama kaydı ayrıntıları" />
|
||||
</div>
|
||||
|
||||
Click **View installed app** to see the installed app. The **About** tab shows the current version and management options:
|
||||
Yüklü uygulamayı görmek için **View installed app**'e tıklayın. **About** sekmesi, geçerli sürümü ve yönetim seçeneklerini gösterir:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-3.png" alt="Installed app — About tab" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-3.png" alt="Yüklü uygulama — About sekmesi" />
|
||||
</div>
|
||||
|
||||
Switch to the **Content** tab to see everything your app provides — objects, fields, logic functions, and agents:
|
||||
Uygulamanızın sağladığı her şeyi — nesneler, alanlar, mantık işlevleri ve ajanlar — görmek için **Content** sekmesine geçin:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-4.png" alt="Installed app — Content tab" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-4.png" alt="Yüklü uygulama — Content sekmesi" />
|
||||
</div>
|
||||
|
||||
You are all set! Edit any file in `src/` and the changes will be picked up automatically.
|
||||
Her şey hazır! `src/` içindeki herhangi bir dosyayı düzenleyin; değişiklikler otomatik olarak alınacaktır.
|
||||
|
||||
Head over to [Building Apps](/l/tr/developers/extend/apps/building) for a detailed guide on creating objects, logic functions, front components, skills, and more.
|
||||
Nesneler, mantık işlevleri, ön bileşenler, beceriler ve daha fazlasını oluşturma hakkında ayrıntılı bir kılavuz için [Uygulama Oluşturma](/l/tr/developers/extend/apps/building) bölümüne göz atın.
|
||||
|
||||
---
|
||||
|
||||
## Project structure
|
||||
## Proje yapısı
|
||||
|
||||
The scaffolder generates the following file structure (shown with `--exhaustive` mode, which includes examples for every entity type):
|
||||
İskelet oluşturucu aşağıdaki dosya yapısını üretir (`--exhaustive` modunda gösterilmiştir; her varlık türü için örnekler içerir):
|
||||
|
||||
```text filename="my-twenty-app/"
|
||||
my-twenty-app/
|
||||
@@ -190,30 +190,30 @@ my-twenty-app/
|
||||
└── example-agent.ts # Example AI agent definition
|
||||
```
|
||||
|
||||
By default (`--minimal`), only the core files are created: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`. Use `--exhaustive` to include all the example files shown above.
|
||||
Varsayılan olarak (`--minimal`), yalnızca çekirdek dosyalar oluşturulur: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` ve `logic-functions/post-install.ts`. Yukarıda gösterilen tüm örnek dosyaları dahil etmek için `--exhaustive` kullanın.
|
||||
|
||||
### Key files
|
||||
### Temel dosyalar
|
||||
|
||||
| File / Folder | Amaç |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `package.json` | Declares your app name, version, and dependencies. Includes a `twenty` script so you can run `yarn twenty help` to see all commands. |
|
||||
| `src/application-config.ts` | **Required.** The main configuration file for your app. |
|
||||
| `src/roles/` | Defines roles that control what your logic functions can access. |
|
||||
| `src/logic-functions/` | Server-side functions triggered by routes, cron schedules, or database events. |
|
||||
| `src/front-components/` | React components that render inside Twenty's UI. |
|
||||
| `src/objects/` | Custom object definitions to extend your data model. |
|
||||
| `src/fields/` | Custom fields added to existing objects. |
|
||||
| `src/views/` | Saved view configurations. |
|
||||
| `src/navigation-menu-items/` | Custom links in the sidebar navigation. |
|
||||
| `src/skills/` | Twenty'nin yapay zeka ajanlarının yeteneklerini genişleten beceriler. |
|
||||
| `src/agents/` | AI agents with custom prompts. |
|
||||
| `src/page-layouts/` | Custom page layouts for record views. |
|
||||
| `src/__tests__/` | Integration tests (setup + example test). |
|
||||
| `public/` | Static assets (images, fonts) served with your app. |
|
||||
| Dosya / Klasör | Amaç |
|
||||
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `package.json` | Uygulamanızın adını, sürümünü ve bağımlılıklarını bildirir. Tüm komutları görmek için `yarn twenty help` çalıştırabilmeniz amacıyla bir `twenty` betiği içerir. |
|
||||
| `src/application-config.ts` | **Gerekli.** Uygulamanızın ana yapılandırma dosyası. |
|
||||
| `src/roles/` | Mantık işlevlerinizin neye erişebileceğini kontrol eden rolleri tanımlar. |
|
||||
| `src/logic-functions/` | Rotalar, cron zamanlamaları veya veritabanı olayları tarafından tetiklenen sunucu tarafı işlevler. |
|
||||
| `src/front-components/` | Twenty'nin UI'si içinde görüntülenen React bileşenleri. |
|
||||
| `src/objects/` | Veri modelinizi genişletmek için özel nesne tanımları. |
|
||||
| `src/fields/` | Mevcut nesnelere eklenen özel alanlar. |
|
||||
| `src/views/` | Kaydedilmiş görünüm yapılandırmaları. |
|
||||
| `src/navigation-menu-items/` | Kenar çubuğu gezintisinde özel bağlantılar. |
|
||||
| `src/skills/` | Twenty'nin yapay zeka ajanlarının yeteneklerini genişleten beceriler. |
|
||||
| `src/agents/` | Özel istemlere sahip yapay zekâ ajanları. |
|
||||
| `src/page-layouts/` | Kayıt görünümleri için özel sayfa düzenleri. |
|
||||
| `src/__tests__/` | Entegrasyon testleri (kurulum + örnek test). |
|
||||
| `public/` | Uygulamanızla birlikte sunulan statik varlıklar (görüntüler, yazı tipleri). |
|
||||
|
||||
## Managing remotes
|
||||
## Uzakları yönetme
|
||||
|
||||
A **remote** is a Twenty server that your app connects to. During setup, the scaffolder creates one for you automatically. You can add more remotes or switch between them at any time.
|
||||
Bir **uzak**, uygulamanızın bağlandığı Twenty sunucusudur. Kurulum sırasında iskelet oluşturucu sizin için otomatik olarak bir tane oluşturur. Dilediğiniz zaman daha fazla uzak ekleyebilir veya aralarında geçiş yapabilirsiniz.
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Add a new remote (opens a browser for OAuth login)
|
||||
@@ -232,11 +232,11 @@ yarn twenty remote list
|
||||
yarn twenty remote switch <name>
|
||||
```
|
||||
|
||||
Your credentials are stored in `~/.twenty/config.json`.
|
||||
Kimlik bilgileriniz `~/.twenty/config.json` içinde saklanır.
|
||||
|
||||
## Local development server (`yarn twenty server`)
|
||||
## Yerel geliştirme sunucusu (`yarn twenty server`)
|
||||
|
||||
The CLI can manage a local Twenty server running in Docker. This is the same server started automatically when you scaffold an app with `create-twenty-app`, but you can also manage it manually.
|
||||
CLI, Docker'da çalışan yerel bir Twenty sunucusunu yönetebilir. Bu, `create-twenty-app` ile bir uygulamanın iskeletini oluşturduğunuzda otomatik olarak başlatılan sunucunun aynısıdır; ancak bunu el ile de yönetebilirsiniz.
|
||||
|
||||
### Sunucuyu Başlatma
|
||||
|
||||
@@ -244,85 +244,85 @@ The CLI can manage a local Twenty server running in Docker. This is the same ser
|
||||
yarn twenty server start
|
||||
```
|
||||
|
||||
This pulls the `twentycrm/twenty-app-dev:latest` Docker image (if not already present), creates a container named `twenty-app-dev`, and starts it on port **2020**. The CLI waits until the server passes its health check before returning.
|
||||
Bu, `twentycrm/twenty-app-dev:latest` Docker imajını (zaten mevcut değilse) çeker, `twenty-app-dev` adlı bir konteyner oluşturur ve **2020** portunda başlatır. CLI, dönmeden önce sunucunun sağlık kontrolünü geçmesini bekler.
|
||||
|
||||
Two Docker volumes are created to persist data between restarts:
|
||||
Yeniden başlatmalar arasında verileri kalıcı kılmak için iki Docker birimi oluşturulur:
|
||||
|
||||
* `twenty-app-dev-data` — PostgreSQL database
|
||||
* `twenty-app-dev-storage` — file storage
|
||||
* `twenty-app-dev-data` — PostgreSQL veritabanı
|
||||
* `twenty-app-dev-storage` — dosya depolama
|
||||
|
||||
If port 2020 is already in use, you can start on a different port:
|
||||
2020 portu zaten kullanımda ise farklı bir portta başlatabilirsiniz:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server start --port 3030
|
||||
```
|
||||
|
||||
The CLI automatically configures the container's internal `NODE_PORT` and `SERVER_URL` to match the chosen port, so logic functions, OAuth, and all other internal networking work correctly.
|
||||
CLI, seçilen porta uyacak şekilde konteynerin dahili `NODE_PORT` ve `SERVER_URL` ayarlarını otomatik olarak yapılandırır; böylece mantık işlevleri, OAuth ve diğer tüm dahili ağ işlemleri doğru şekilde çalışır.
|
||||
|
||||
Once started, the server is automatically registered as the `local` remote in your CLI config.
|
||||
Başlatıldığında, sunucu CLI yapılandırmanızda `local` uzak olarak otomatik olarak kaydedilir.
|
||||
|
||||
### Checking server status
|
||||
### Sunucu durumunu kontrol etme
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server status
|
||||
```
|
||||
|
||||
Displays whether the server is running, its URL, and the default login credentials (`tim@apple.dev` / `tim@apple.dev`).
|
||||
Sunucunun çalışıp çalışmadığını, URL'sini ve varsayılan oturum açma kimlik bilgilerini (`tim@apple.dev` / `tim@apple.dev`) gösterir.
|
||||
|
||||
### Viewing server logs
|
||||
### Sunucu günlüklerini görüntüleme
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server logs
|
||||
```
|
||||
|
||||
Streams the container logs. Use `--lines` to control how many recent lines to show:
|
||||
Konteyner günlüklerini akış olarak iletir. Kaç satırın gösterileceğini denetlemek için `--lines` kullanın:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server logs --lines 100
|
||||
```
|
||||
|
||||
### Stopping the server
|
||||
### Sunucuyu durdurma
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server stop
|
||||
```
|
||||
|
||||
Stops the container. Your data is preserved in the Docker volumes — the next `start` picks up where you left off.
|
||||
Konteyneri durdurur. Verileriniz Docker birimlerinde korunur — bir sonraki `start`, kaldığınız yerden devam eder.
|
||||
|
||||
### Resetting the server
|
||||
### Sunucuyu sıfırlama
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server reset
|
||||
```
|
||||
|
||||
Removes the container **and** deletes both Docker volumes, wiping all data. The next `start` creates a fresh instance.
|
||||
Konteyneri kaldırır ve her iki Docker birimini de silerek tüm verileri temizler. Sonraki `start`, yeni bir örnek oluşturur.
|
||||
|
||||
<Note>
|
||||
The server requires **Docker** to be running. If you see a "Docker not running" error, make sure Docker Desktop (or the Docker daemon) is started.
|
||||
Sunucunun çalışması için **Docker**'ın çalışıyor olması gerekir. "Docker not running" hatası görürseniz Docker Desktop'ın (veya Docker daemon'ının) başlatıldığından emin olun.
|
||||
</Note>
|
||||
|
||||
### Command reference
|
||||
### Komut başvurusu
|
||||
|
||||
| Komut | Açıklama |
|
||||
| -------------------------------------- | ---------------------------------------------- |
|
||||
| `yarn twenty server start` | Start the local server (pulls image if needed) |
|
||||
| `yarn twenty server start --port 3030` | Start on a custom port |
|
||||
| `yarn twenty server stop` | Stop the server (preserves data) |
|
||||
| `yarn twenty server status` | Show server status, URL, and credentials |
|
||||
| `yarn twenty server logs` | Stream server logs |
|
||||
| `yarn twenty server logs --lines 100` | Show the last 100 log lines |
|
||||
| `yarn twenty server reset` | Delete all data and start fresh |
|
||||
| Komut | Açıklama |
|
||||
| -------------------------------------- | ------------------------------------------------------ |
|
||||
| `yarn twenty server start` | Yerel sunucuyu başlatır (gerekirse imajı çeker) |
|
||||
| `yarn twenty server start --port 3030` | Özel bir portta başlatır |
|
||||
| `yarn twenty server stop` | Sunucuyu durdurur (verileri korur) |
|
||||
| `yarn twenty server status` | Sunucu durumunu, URL'yi ve kimlik bilgilerini gösterir |
|
||||
| `yarn twenty server logs` | Sunucu günlüklerini akış olarak iletir |
|
||||
| `yarn twenty server logs --lines 100` | Son 100 günlük satırını gösterir |
|
||||
| `yarn twenty server reset` | Tüm verileri siler ve sıfırdan başlatır |
|
||||
|
||||
## CI with GitHub Actions
|
||||
## GitHub Actions ile CI
|
||||
|
||||
The scaffolder generates a ready-to-use GitHub Actions workflow at `.github/workflows/ci.yml`. It runs your integration tests automatically on every push to `main` and on pull requests.
|
||||
İskelet oluşturucu, `.github/workflows/ci.yml` konumunda kullanıma hazır bir GitHub Actions iş akışı üretir. Entegrasyon testlerinizi `main` dalına yapılan her itmede ve çekme isteklerinde otomatik olarak çalıştırır.
|
||||
|
||||
The workflow:
|
||||
İş akışı:
|
||||
|
||||
1. Checks out your code
|
||||
2. Spins up a temporary Twenty server using the `twentyhq/twenty/.github/actions/spawn-twenty-docker-image` action
|
||||
3. Installs dependencies with `yarn install --immutable`
|
||||
4. Runs `yarn test` with `TWENTY_API_URL` and `TWENTY_API_KEY` injected from the action outputs
|
||||
1. Kodunuzu depodan çıkarır
|
||||
2. `twentyhq/twenty/.github/actions/spawn-twenty-docker-image` eylemini kullanarak geçici bir Twenty sunucusu başlatır
|
||||
3. `yarn install --immutable` ile bağımlılıkları kurar
|
||||
4. Eylem çıktılarından enjekte edilen `TWENTY_API_URL` ve `TWENTY_API_KEY` ile `yarn test` çalıştırır
|
||||
|
||||
```yaml .github/workflows/ci.yml
|
||||
name: CI
|
||||
@@ -369,21 +369,21 @@ jobs:
|
||||
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
|
||||
```
|
||||
|
||||
You don't need to configure any secrets — the `spawn-twenty-docker-image` action starts an ephemeral Twenty server directly in the runner and outputs the connection details. The `GITHUB_TOKEN` secret is provided automatically by GitHub.
|
||||
Herhangi bir gizli değişken yapılandırmanız gerekmez — `spawn-twenty-docker-image` eylemi, koşucu içinde doğrudan geçici bir Twenty sunucusu başlatır ve bağlantı ayrıntılarını çıktı olarak verir. `GITHUB_TOKEN` gizli değişkeni GitHub tarafından otomatik olarak sağlanır.
|
||||
|
||||
To pin a specific Twenty version instead of `latest`, change the `TWENTY_VERSION` environment variable at the top of the workflow.
|
||||
`latest` yerine belirli bir Twenty sürümünü sabitlemek için iş akışının başındaki `TWENTY_VERSION` ortam değişkenini değiştirin.
|
||||
|
||||
## Manuel kurulum (iskelet oluşturucu olmadan)
|
||||
|
||||
If you prefer to set things up yourself instead of using `create-twenty-app`, you can do it in two steps.
|
||||
`create-twenty-app` kullanmak yerine her şeyi kendiniz ayarlamayı tercih ederseniz, bunu iki adımda yapabilirsiniz.
|
||||
|
||||
**1. Add `twenty-sdk` and `twenty-client-sdk` as dependencies:**
|
||||
**1. `twenty-sdk` ve `twenty-client-sdk` paketlerini bağımlılık olarak ekleyin:**
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn add twenty-sdk twenty-client-sdk
|
||||
```
|
||||
|
||||
**2. Add a `twenty` script to your `package.json`:**
|
||||
**2. `package.json` dosyanıza bir `twenty` betiği ekleyin:**
|
||||
|
||||
```json filename="package.json"
|
||||
{
|
||||
@@ -393,19 +393,19 @@ yarn add twenty-sdk twenty-client-sdk
|
||||
}
|
||||
```
|
||||
|
||||
You can now run `yarn twenty dev`, `yarn twenty help`, and all other commands.
|
||||
Artık `yarn twenty dev`, `yarn twenty help` ve diğer tüm komutları çalıştırabilirsiniz.
|
||||
|
||||
<Note>
|
||||
Do not install `twenty-sdk` globally. Always use it as a local project dependency so that each project can pin its own version.
|
||||
`twenty-sdk`'yi global olarak kurmayın. Her projenin kendi sürümünü sabitleyebilmesi için onu her zaman yerel bir proje bağımlılığı olarak kullanın.
|
||||
</Note>
|
||||
|
||||
## Sorun Giderme
|
||||
|
||||
If you run into issues:
|
||||
Sorunlarla karşılaşırsanız:
|
||||
|
||||
* Make sure **Docker is running** before starting the scaffolder with a local instance.
|
||||
* Make sure you are using **Node.js 24+** (`node -v` to check).
|
||||
* Make sure **Corepack is enabled** (`corepack enable`) so Yarn 4 is available.
|
||||
* Try deleting `node_modules` and running `yarn install` again if dependencies seem broken.
|
||||
* Yerel bir örnekle scaffolder'ı başlatmadan önce **Docker'ın çalıştığından** emin olun.
|
||||
* **Node.js 24+** kullandığınızdan emin olun (kontrol etmek için `node -v`).
|
||||
* Yarn 4'ün kullanılabilir olması için **Corepack'in etkinleştirildiğinden** emin olun (`corepack enable`).
|
||||
* Bağımlılıklar bozuk görünüyorsa `node_modules` dizinini silip `yarn install` komutunu yeniden çalıştırmayı deneyin.
|
||||
|
||||
Still stuck? Ask for help on the [Twenty Discord](https://discord.com/channels/1130383047699738754/1130386664812982322).
|
||||
Hâlâ takıldınız mı? Yardım için [Twenty Discord](https://discord.com/channels/1130383047699738754/1130386664812982322) üzerinden yardım isteyin.
|
||||
|
||||
@@ -4,24 +4,24 @@ description: 使用 Twenty SDK 定义对象、逻辑函数、前端组件等。
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Apps are currently in alpha. The feature works but is still evolving.
|
||||
应用目前处于 Alpha 阶段。 该功能可用,但仍在演进中。
|
||||
</Warning>
|
||||
|
||||
The `twenty-sdk` package provides typed building blocks to create your app. This page covers every entity type and API client available in the SDK.
|
||||
`twenty-sdk` 包提供类型化的构建块,用于创建你的应用。 本页涵盖 SDK 中可用的所有实体类型和 API 客户端。
|
||||
|
||||
## DefineEntity functions
|
||||
## DefineEntity 函数
|
||||
|
||||
The SDK provides functions to define your app entities. You must use `export default defineEntity({...})` for the SDK to detect your entities. 这些函数会在构建时校验你的配置,并提供 IDE 自动补全和类型安全。
|
||||
SDK 提供用于定义你的应用实体的函数。 你必须使用 `export default defineEntity({...})`,这样 SDK 才能检测到你的实体。 这些函数会在构建时校验你的配置,并提供 IDE 自动补全和类型安全。
|
||||
|
||||
<Note>
|
||||
**File organization is up to you.**
|
||||
Entity detection is AST-based — the SDK finds `export default defineEntity(...)` calls regardless of where the file lives. Grouping files by type (e.g., `logic-functions/`, `roles/`) is just a convention, not a requirement.
|
||||
**文件组织由你决定。**
|
||||
实体检测基于 AST——无论文件位于何处,SDK 都能找到 `export default defineEntity(...)` 的调用。 按类型对文件分组(例如 `logic-functions/`、`roles/`)只是代码组织的一种约定,并非必需。
|
||||
</Note>
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="defineRole" description="配置角色权限和对象访问">
|
||||
|
||||
Roles encapsulate permissions on your workspace's objects and actions.
|
||||
角色封装了对你的工作空间对象与操作的权限。
|
||||
|
||||
```ts restricted-company-role.ts
|
||||
import {
|
||||
@@ -69,12 +69,12 @@ export default defineRole({
|
||||
</Accordion>
|
||||
<Accordion title="defineApplication" description="配置应用元数据(必需,每个应用一个)">
|
||||
|
||||
Every app must have exactly one `defineApplication` call that describes:
|
||||
每个应用必须且只能有一个 `defineApplication` 调用,用于描述:
|
||||
|
||||
* **Identity**: identifiers, display name, and description.
|
||||
* **Permissions**: which role its functions and front components use.
|
||||
* **(Optional) Variables**: key–value pairs exposed to your functions as environment variables.
|
||||
* **(Optional) Pre-install / post-install functions**: logic functions that run before or after installation.
|
||||
* **应用的身份**:标识符、显示名称和描述。
|
||||
* **权限**:其函数和前端组件所使用的角色。
|
||||
* **(可选)变量**:以环境变量形式提供给函数的键值对。
|
||||
* **(可选)安装前/安装后函数**:在安装之前或之后运行的逻辑函数。
|
||||
|
||||
```ts src/application-config.ts
|
||||
import { defineApplication } from 'twenty-sdk';
|
||||
@@ -98,21 +98,21 @@ export default defineApplication({
|
||||
```
|
||||
|
||||
备注:
|
||||
* `universalIdentifier` fields are deterministic IDs you own. Generate them once and keep them stable across syncs.
|
||||
* `applicationVariables` become environment variables for your functions and front components (e.g., `DEFAULT_RECIPIENT_NAME` is available as `process.env.DEFAULT_RECIPIENT_NAME`).
|
||||
* `defaultRoleUniversalIdentifier` must reference a role defined with `defineRole()` (see above).
|
||||
* Pre-install and post-install functions are detected automatically during the manifest build — you do not need to reference them in `defineApplication()`.
|
||||
* `universalIdentifier` 字段是你拥有的确定性 ID。 只需生成一次,并在多次同步过程中保持稳定不变。
|
||||
* `applicationVariables` 会变成你的函数和前端组件可用的环境变量(例如,`DEFAULT_RECIPIENT_NAME` 可作为 `process.env.DEFAULT_RECIPIENT_NAME` 使用)。
|
||||
* `defaultRoleUniversalIdentifier` 必须引用使用 `defineRole()` 定义的角色(见上文)。
|
||||
* 在构建清单时会自动检测安装前/安装后函数——无需在 `defineApplication()` 中引用它们。
|
||||
|
||||
#### 应用市场元数据
|
||||
|
||||
If you plan to [publish your app](/l/zh/developers/extend/apps/publishing), these optional fields control how it appears in the marketplace:
|
||||
如果你计划[发布你的应用](/l/zh/developers/extend/apps/publishing),这些可选字段将控制你的应用在应用市场中的展示:
|
||||
|
||||
| 字段 | 描述 |
|
||||
| ------------------ | -------------------------------------------------------------- |
|
||||
| `作者` | 作者或公司名称 |
|
||||
| `类别` | 用于应用市场筛选的应用类别 |
|
||||
| `logoUrl` | Path to your app logo (e.g., `public/logo.png`) |
|
||||
| `screenshots` | Array of screenshot paths (e.g., `public/screenshot-1.png`) |
|
||||
| `logoUrl` | 应用徽标的路径(例如 `public/logo.png`) |
|
||||
| `screenshots` | 截图路径数组(例如 `public/screenshot-1.png`) |
|
||||
| `aboutDescription` | 用于“关于”选项卡的更长的 Markdown 描述。 如果省略,市场将使用该软件包在 npm 上的 `README.md`。 |
|
||||
| `websiteUrl` | 你的网站链接 |
|
||||
| `termsUrl` | 服务条款链接 |
|
||||
@@ -121,15 +121,15 @@ If you plan to [publish your app](/l/zh/developers/extend/apps/publishing), thes
|
||||
|
||||
#### 角色和权限
|
||||
|
||||
The `defaultRoleUniversalIdentifier` in `application-config.ts` designates the default role used by your app's logic functions and front components. See `defineRole` above for details.
|
||||
`application-config.ts` 中的 `defaultRoleUniversalIdentifier` 字段指定你的应用的逻辑函数和前端组件所使用的默认角色。 详见上文的 `defineRole`。
|
||||
|
||||
* The runtime token injected as `TWENTY_APP_ACCESS_TOKEN` is derived from this role.
|
||||
* The typed client is restricted to the permissions granted to that role.
|
||||
* Follow least-privilege: create a dedicated role with only the permissions your functions need.
|
||||
* 作为 `TWENTY_APP_ACCESS_TOKEN` 注入的运行时令牌来源于该角色。
|
||||
* 类型化客户端将受限于该角色授予的权限。
|
||||
* 遵循最小权限原则:创建一个仅包含你的函数所需权限的专用角色。
|
||||
|
||||
##### Default function role
|
||||
##### 默认函数角色
|
||||
|
||||
When you scaffold a new app, the CLI creates a default role file:
|
||||
当你使用脚手架创建新应用时,CLI 会创建一个默认角色文件:
|
||||
|
||||
```ts src/roles/default-role.ts
|
||||
import { defineRole, PermissionFlag } from 'twenty-sdk';
|
||||
@@ -155,16 +155,16 @@ export default defineRole({
|
||||
});
|
||||
```
|
||||
|
||||
This role's `universalIdentifier` is referenced in `application-config.ts` as `defaultRoleUniversalIdentifier`:
|
||||
该角色的 `universalIdentifier` 会在 `application-config.ts` 中被引用为 `defaultRoleUniversalIdentifier`:
|
||||
|
||||
* **\*.role.ts** defines what the role can do.
|
||||
* **\*.role.ts** 定义该角色可以执行的操作。
|
||||
* **application-config.ts** 指向该角色,使你的函数继承其权限。
|
||||
|
||||
备注:
|
||||
* 从脚手架生成的角色开始,然后按照最小权限原则逐步收紧权限。
|
||||
* Replace `objectPermissions` and `fieldPermissions` with the objects and fields your functions actually need.
|
||||
* `permissionFlags` 控制对平台级能力的访问。 Keep them minimal.
|
||||
* See a working example: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
|
||||
* 将 `objectPermissions` 和 `fieldPermissions` 替换为你的函数所需的对象/字段。
|
||||
* `permissionFlags` 控制对平台级能力的访问。 尽量保持最小化。
|
||||
* 查看一个可运行示例:[`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts)。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="defineObject" description="定义带字段的自定义对象">
|
||||
@@ -256,7 +256,7 @@ export default defineObject({
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="defineField — Standard fields" description="为现有对象扩展额外字段">
|
||||
<Accordion title="defineField — 标准字段" description="为现有对象扩展额外字段">
|
||||
|
||||
使用 `defineField()` 向你不拥有的对象添加字段——例如标准的 Twenty 对象(Person、Company 等)。 或来自其他应用的对象。 与在 `defineObject()` 中的内联字段不同,独立字段需要一个 `objectUniversalIdentifier` 来指定它们要扩展的对象:
|
||||
|
||||
@@ -284,7 +284,7 @@ export default defineField({
|
||||
* `defineField()` 是为非通过 `defineObject()` 创建的对象添加字段的唯一方式。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="defineField — Relation fields" description="Connect objects together with bidirectional relations">
|
||||
<Accordion title="defineField — 关联字段" description="使用双向关系将对象连接在一起">
|
||||
|
||||
关系用于将对象彼此连接。 在 Twenty 中,关系始终是双向的——你需要定义两侧,每一侧都引用另一侧。
|
||||
|
||||
@@ -443,7 +443,7 @@ export default defineObject({
|
||||
});
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="defineLogicFunction" description="Define logic functions and their triggers">
|
||||
<Accordion title="defineLogicFunction" description="定义逻辑函数及其触发器">
|
||||
|
||||
每个函数文件都使用 `defineLogicFunction()` 导出包含处理程序和可选触发器的配置。
|
||||
|
||||
@@ -487,15 +487,15 @@ export default defineLogicFunction({
|
||||
});
|
||||
```
|
||||
|
||||
Available trigger types:
|
||||
* **httpRoute**: Exposes your function on an HTTP path and method **under the `/s/` endpoint**:
|
||||
> e.g. `path: '/post-card/create'` is callable at `https://your-twenty-server.com/s/post-card/create`
|
||||
可用的触发器类型:
|
||||
* **httpRoute**:在 **`/s/` 端点**下通过 HTTP 路径和方法公开你的函数:
|
||||
> 例如 `path: '/post-card/create'` 可在 `https://your-twenty-server.com/s/post-card/create` 调用
|
||||
* **cron**:使用 CRON 表达式按计划运行你的函数。
|
||||
* **databaseEvent**:在工作空间对象生命周期事件上运行。 当事件操作为 `updated` 时,可以在 `updatedFields` 数组中指定要监听的特定字段。 如果未定义或为空,任何更新都会触发该函数。
|
||||
> e.g. `person.updated`, `*.created`, `company.*`
|
||||
> 例如 `person.updated`、`*.created`、`company.*`
|
||||
|
||||
<Note>
|
||||
You can also manually execute a function using the CLI:
|
||||
你也可以使用 CLI 手动执行函数:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty exec -n create-new-post-card -p '{"key": "value"}'
|
||||
@@ -505,7 +505,7 @@ yarn twenty exec -n create-new-post-card -p '{"key": "value"}'
|
||||
yarn twenty exec -y e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf
|
||||
```
|
||||
|
||||
You can watch logs with:
|
||||
你可以通过以下方式查看日志:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty logs
|
||||
@@ -514,9 +514,9 @@ yarn twenty logs
|
||||
|
||||
#### 路由触发器负载
|
||||
|
||||
When a route trigger invokes your logic function, it receives a `RoutePayload` object that follows the
|
||||
[AWS HTTP API v2 format](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html).
|
||||
Import the `RoutePayload` type from `twenty-sdk`:
|
||||
当路由触发器调用你的逻辑函数时,它会接收一个遵循
|
||||
[AWS HTTP API v2 格式](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html)的 `RoutePayload` 对象。
|
||||
从 `twenty-sdk` 导入 `RoutePayload` 类型:
|
||||
|
||||
```ts
|
||||
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';
|
||||
@@ -531,21 +531,21 @@ const handler = async (event: RoutePayload) => {
|
||||
|
||||
`RoutePayload` 类型具有以下结构:
|
||||
|
||||
| 属性 | 类型 | 描述 | 示例 |
|
||||
| ---------------------------- | ------------------------------------- | ------------------------------------------------ | -------------------------------------------------------------------------- |
|
||||
| `headers` | `Record<string, string \| undefined>` | HTTP 请求头(仅限 `forwardedRequestHeaders` 中列出的那些) | see section below |
|
||||
| `queryStringParameters` | `Record<string, string \| undefined>` | 查询字符串参数(多个值以逗号连接) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
|
||||
| `pathParameters` | `Record<string, string \| undefined>` | Path parameters extracted from the route pattern | `/users/:id`, `/users/123` -> `{ id: '123' }` |
|
||||
| `body` | `object \| null` | 已解析的请求体(JSON) | `{ id: 1 }` -> `{ id: 1 }` |
|
||||
| `isBase64Encoded` | `boolean` | 请求体是否为 base64 编码 | |
|
||||
| `requestContext.http.method` | `string` | HTTP 方法(GET、POST、PUT、PATCH、DELETE) | |
|
||||
| `requestContext.http.path` | `string` | 原始请求路径 | |
|
||||
| 属性 | 类型 | 描述 | 示例 |
|
||||
| ---------------------------- | ------------------------------------- | --------------------------------------------- | -------------------------------------------------------------------------- |
|
||||
| `headers` | `Record<string, string \| undefined>` | HTTP 请求头(仅限 `forwardedRequestHeaders` 中列出的那些) | 见下文 |
|
||||
| `queryStringParameters` | `Record<string, string \| undefined>` | 查询字符串参数(多个值以逗号连接) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
|
||||
| `pathParameters` | `Record<string, string \| undefined>` | 从路由模式中提取的路径参数 | `/users/:id`,`/users/123` -> `{ id: '123' }` |
|
||||
| `body` | `object \| null` | 已解析的请求体(JSON) | `{ id: 1 }` -> `{ id: 1 }` |
|
||||
| `isBase64Encoded` | `boolean` | 请求体是否为 base64 编码 | |
|
||||
| `requestContext.http.method` | `string` | HTTP 方法(GET、POST、PUT、PATCH、DELETE) | |
|
||||
| `requestContext.http.path` | `string` | 原始请求路径 | |
|
||||
|
||||
|
||||
#### forwardedRequestHeaders
|
||||
|
||||
出于安全原因,默认**不会**将传入请求的 HTTP 请求头传递给你的逻辑函数。
|
||||
To access specific headers, list them in the `forwardedRequestHeaders` array:
|
||||
如需访问特定请求头,请在 `forwardedRequestHeaders` 数组中显式列出:
|
||||
|
||||
```ts
|
||||
export default defineLogicFunction({
|
||||
@@ -561,7 +561,7 @@ export default defineLogicFunction({
|
||||
});
|
||||
```
|
||||
|
||||
In your handler, access the forwarded headers like this:
|
||||
在你的处理程序中,可以这样访问被转发的请求头:
|
||||
|
||||
```ts
|
||||
const handler = async (event: RoutePayload) => {
|
||||
@@ -574,14 +574,14 @@ const handler = async (event: RoutePayload) => {
|
||||
```
|
||||
|
||||
<Note>
|
||||
请求头名称会被规范化为小写。 Access them using lowercase keys (e.g., `event.headers['content-type']`).
|
||||
请求头名称会被规范化为小写。 请使用小写键访问它们(例如,`event.headers['content-type']`)。
|
||||
</Note>
|
||||
|
||||
#### Exposing a function as a tool
|
||||
#### 将函数作为工具公开
|
||||
|
||||
逻辑函数可以作为供 AI 智能体和工作流使用的**工具**对外提供。 When marked as a tool, a function becomes discoverable by Twenty's AI features and can be used in workflow automations.
|
||||
逻辑函数可以作为供 AI 智能体和工作流使用的**工具**对外提供。 当函数被标记为工具时,Twenty 的 AI 功能即可发现它,并可在工作流自动化中使用。
|
||||
|
||||
To mark a logic function as a tool, set `isTool: true`:
|
||||
要将逻辑函数标记为工具,请设置 `isTool: true`:
|
||||
|
||||
```ts src/logic-functions/enrich-company.logic-function.ts
|
||||
import { defineLogicFunction } from 'twenty-sdk';
|
||||
@@ -617,8 +617,8 @@ export default defineLogicFunction({
|
||||
|
||||
关键点:
|
||||
|
||||
* You can combine `isTool` with triggers — a function can be both a tool (callable by AI agents) and triggered by events at the same time.
|
||||
* **`toolInputSchema`** (optional): A JSON Schema object describing the parameters your function accepts. The schema is computed automatically from source code static analysis, but you can set it explicitly:
|
||||
* 你可以将 `isTool` 与触发器结合使用——一个函数既可以作为工具(由 AI 代理调用),也可以同时由事件触发。
|
||||
* **`toolInputSchema`**(可选):描述函数可接受参数的 JSON Schema 对象。 该模式会通过对源代码的静态分析自动推导,但你也可以显式设置:
|
||||
|
||||
```ts
|
||||
export default defineLogicFunction({
|
||||
@@ -715,11 +715,11 @@ yarn twenty exec --postInstall
|
||||
</Accordion>
|
||||
<Accordion title="defineFrontComponent" description="为自定义 UI 定义前端组件">
|
||||
|
||||
Front components are React components that render directly inside Twenty's UI. They run in an **isolated Web Worker** using Remote DOM — your code is sandboxed but renders natively in the page, not in an iframe.
|
||||
前端组件是直接在 Twenty 的 UI 内渲染的 React 组件。 它们在使用 Remote DOM 的**隔离 Web Worker**中运行——你的代码在沙盒中执行,但会原生渲染到页面中,而非在 iframe 里。
|
||||
|
||||
#### Basic example
|
||||
#### 基础示例
|
||||
|
||||
The quickest way to see a front component in action is to register it as a **command**. Adding a `command` field with `isPinned: true` makes it appear as a quick-action button in the top-right corner of the page — no page layout needed:
|
||||
最快体验前端组件运行方式的方法是将其注册为一个**命令**。 添加一个 `command` 字段并设置 `isPinned: true`,即可让它以快速操作按钮的形式出现在页面右上角——无需页面布局:
|
||||
|
||||
```tsx src/front-components/hello-world.tsx
|
||||
import { defineFrontComponent } from 'twenty-sdk';
|
||||
@@ -749,24 +749,24 @@ export default defineFrontComponent({
|
||||
});
|
||||
```
|
||||
|
||||
After syncing with `yarn twenty dev`, the quick action appears in the top-right corner of the page:
|
||||
使用 `yarn twenty dev` 同步后,快速操作会出现在页面右上角:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Quick action button in the top-right corner" />
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="右上角的快速操作按钮" />
|
||||
</div>
|
||||
|
||||
Click it to render the component inline.
|
||||
点击它以内联方式渲染该组件。
|
||||
|
||||
{/* TODO: add screenshot of the rendered front component */}
|
||||
|
||||
#### Configuration fields
|
||||
#### 配置字段
|
||||
|
||||
| 字段 | 必填 | 描述 |
|
||||
| --------------------- | -- | ----------------------------------------------------------------------------------- |
|
||||
| `universalIdentifier` | 是 | Stable unique ID for this component |
|
||||
| `component` | 是 | A React component function |
|
||||
| `name` | 否 | Display name |
|
||||
| `描述` | 否 | Description of what the component does |
|
||||
| `universalIdentifier` | 是 | 该组件的稳定唯一 ID |
|
||||
| `component` | 是 | 一个 React 组件函数 |
|
||||
| `name` | 否 | 显示名称 |
|
||||
| `描述` | 否 | 组件的功能描述 |
|
||||
| `isHeadless` | 否 | Set to `true` if the component has no visible UI (see below) |
|
||||
| `命令` | 否 | Register the component as a command (see [command options](#command-options) below) |
|
||||
|
||||
|
||||
@@ -4,142 +4,142 @@ description: 几分钟内创建你的第一个 Twenty 应用。
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Apps are currently in alpha. The feature works but is still evolving.
|
||||
应用目前处于 Alpha 阶段。 该功能可用,但仍在演进中。
|
||||
</Warning>
|
||||
|
||||
应用可通过自定义对象、字段、逻辑函数、AI 技能和 UI 组件来扩展 Twenty——全部以代码进行管理。
|
||||
|
||||
## 先决条件
|
||||
|
||||
Before you begin, make sure the following is installed on your machine:
|
||||
在开始之前,请确保你的机器已安装以下内容:
|
||||
|
||||
* **Node.js 24+** — [Download here](https://nodejs.org/)
|
||||
* **Yarn 4** — Comes with Node.js via Corepack. Enable it by running `corepack enable`
|
||||
* **Docker** — [Download here](https://www.docker.com/products/docker-desktop/). Required to run a local Twenty instance. Not needed if you already have a Twenty server running.
|
||||
* **Node.js 24+** — [在此下载](https://nodejs.org/)
|
||||
* **Yarn 4** — 通过 Corepack 随 Node.js 提供。 通过运行 `corepack enable` 启用它
|
||||
* **Docker** — [在此下载](https://www.docker.com/products/docker-desktop/)。 运行本地 Twenty 实例所必需。 如果你已经有一个正在运行的 Twenty 服务器,则不需要。
|
||||
|
||||
## Step 1: Scaffold your app
|
||||
## 步骤 1:为你的应用创建脚手架
|
||||
|
||||
Open a terminal and run:
|
||||
打开终端并运行:
|
||||
|
||||
```bash filename="Terminal"
|
||||
npx create-twenty-app@latest my-twenty-app
|
||||
```
|
||||
|
||||
You will be prompted to enter a name and a description for your app. Press **Enter** to accept the defaults.
|
||||
系统会提示你为应用输入名称和描述。 按下 **Enter** 接受默认值。
|
||||
|
||||
This creates a new folder called `my-twenty-app` with everything you need.
|
||||
这会创建一个名为 `my-twenty-app` 的新文件夹,其中包含你所需的一切。
|
||||
|
||||
<Note>
|
||||
The scaffolder supports these flags:
|
||||
脚手架工具支持以下标志:
|
||||
|
||||
* `--minimal` — scaffold only the essential files, no examples (default)
|
||||
* `--exhaustive` — scaffold all example entities
|
||||
* `--name <name>` — set the app name (skips the prompt)
|
||||
* `--display-name <displayName>` — set the display name (skips the prompt)
|
||||
* `--description <description>` — set the description (skips the prompt)
|
||||
* `--skip-local-instance` — skip the local server setup prompt
|
||||
* `--minimal` — 仅创建必要文件,不包含示例(默认)
|
||||
* `--exhaustive` — 创建所有示例实体
|
||||
* `--name <name>` — 设置应用名称(跳过提示)
|
||||
* `--display-name <displayName>` — 设置显示名称(跳过提示)
|
||||
* `--description <description>` — 设置描述(跳过提示)
|
||||
* `--skip-local-instance` — 跳过本地服务器设置提示
|
||||
</Note>
|
||||
|
||||
## Step 2: Set up a local Twenty instance
|
||||
## 步骤 2:设置本地 Twenty 实例
|
||||
|
||||
The scaffolder will ask:
|
||||
脚手架工具会询问:
|
||||
|
||||
> **Would you like to set up a local Twenty instance?**
|
||||
> **是否要设置本地 Twenty 实例?**
|
||||
|
||||
* **Type `yes`** (recommended) — This pulls the `twenty-app-dev` Docker image and starts a local Twenty server on port `2020`. Make sure Docker is running before you continue.
|
||||
* **Type `no`** — Choose this if you already have a Twenty server running locally.
|
||||
* **输入 `yes`**(推荐)— 这将拉取 `twenty-app-dev` Docker 镜像,并在端口 `2020` 上启动本地 Twenty 服务器。 继续之前,请确保 Docker 正在运行。
|
||||
* **输入 `no`** — 如果你已经有一个在本地运行的 Twenty 服务器,请选择此项。
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Should start local instance?" />
|
||||
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="是否启动本地实例?" />
|
||||
</div>
|
||||
|
||||
## Step 3: Sign in to your workspace
|
||||
## 步骤 3:登录你的工作区
|
||||
|
||||
Next, a browser window will open with the Twenty login page. Sign in with the pre-seeded demo account:
|
||||
接下来,将打开一个浏览器窗口,显示 Twenty 登录页面。 使用预置的演示账户登录:
|
||||
|
||||
* **Email:** `tim@apple.dev`
|
||||
* **Password:** `tim@apple.dev`
|
||||
* **邮箱:** `tim@apple.dev`
|
||||
* **密码:** `tim@apple.dev`
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/login.png" alt="Twenty login screen" />
|
||||
<img src="/images/docs/developers/extends/apps/login.png" alt="Twenty 登录界面" />
|
||||
</div>
|
||||
|
||||
## Step 4: Authorize the app
|
||||
## 步骤 4:授权该应用
|
||||
|
||||
After you sign in, you will see an authorization screen. This lets your app interact with your workspace.
|
||||
登录后,你会看到一个授权界面。 这使你的应用可以与工作区交互。
|
||||
|
||||
Click **Authorize** to continue.
|
||||
点击 **授权** 继续。
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/authorize.png" alt="Twenty CLI authorization screen" />
|
||||
<img src="/images/docs/developers/extends/apps/authorize.png" alt="Twenty CLI 授权界面" />
|
||||
</div>
|
||||
|
||||
Once authorized, your terminal will confirm that everything is set up.
|
||||
授权后,你的终端会确认一切已就绪。
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="App scaffolded successfully" />
|
||||
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="应用脚手架创建成功" />
|
||||
</div>
|
||||
|
||||
## Step 5: Start developing
|
||||
## 步骤 5:开始开发
|
||||
|
||||
Go into your new app folder and start the development server:
|
||||
进入你的新应用文件夹并启动开发服务器:
|
||||
|
||||
```bash filename="Terminal"
|
||||
cd my-twenty-app
|
||||
yarn twenty dev
|
||||
```
|
||||
|
||||
This watches your source files, rebuilds on every change, and syncs your app to the local Twenty server automatically. You should see a live status panel in your terminal.
|
||||
它会监听你的源文件,每次更改都会重建,并自动将你的应用同步到本地 Twenty 服务器。 你应当在终端中看到一个实时状态面板。
|
||||
|
||||
For more detailed output (build logs, sync requests, error traces), use the `--verbose` flag:
|
||||
如需更详细的输出(构建日志、同步请求、错误跟踪),请使用 `--verbose` 标志:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev --verbose
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Dev mode is only available on Twenty instances running in development (`NODE_ENV=development`). Production instances reject dev sync requests. Use `yarn twenty deploy` to deploy to production servers — see [Publishing Apps](/l/zh/developers/extend/apps/publishing) for details.
|
||||
开发模式仅适用于以开发模式运行的 Twenty 实例(`NODE_ENV=development`)。 生产实例会拒绝开发同步请求。 使用 `yarn twenty deploy` 部署到生产服务器——详见[发布应用](/l/zh/developers/extend/apps/publishing)。
|
||||
</Warning>
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Dev mode terminal output" />
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="开发模式终端输出" />
|
||||
</div>
|
||||
|
||||
## Step 6: See your app in Twenty
|
||||
## 步骤 6:在 Twenty 中查看你的应用
|
||||
|
||||
Open [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) in your browser. Navigate to **Settings > Apps** and select the **Developer** tab. You should see your app listed under **Your Apps**:
|
||||
在浏览器中打开 [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer)。 前往 **设置 > 应用**,并选择 **开发者** 选项卡。 你应当在 **你的应用** 下看到你的应用:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-1.png" alt="Your Apps list showing My twenty app" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-1.png" alt="“你的应用”列表显示 My twenty app" />
|
||||
</div>
|
||||
|
||||
Click on **My twenty app** to open its **application registration**. A registration is a server-level record that describes your app — its name, unique identifier, OAuth credentials, and source (local, npm, or tarball). It lives on the server, not inside any specific workspace. When you install an app into a workspace, Twenty creates a workspace-scoped **application** that points back to this registration. One registration can be installed across multiple workspaces on the same server.
|
||||
点击 **My twenty app** 打开其 **应用注册**。 注册项是一个服务器级记录,用于描述你的应用——其名称、唯一标识符、OAuth 凭据以及来源(本地、npm 或 tarball)。 它位于服务器上,而不在任何特定工作区内。 当你将应用安装到工作区时,Twenty 会创建一个工作区范围的 **应用**,指向该注册项。 同一服务器上的多个工作区可以安装同一个注册项。
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-2.png" alt="Application registration details" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-2.png" alt="应用注册详情" />
|
||||
</div>
|
||||
|
||||
Click **View installed app** to see the installed app. The **About** tab shows the current version and management options:
|
||||
点击 **查看已安装的应用** 以查看已安装的应用。 **关于** 选项卡显示当前版本和管理选项:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-3.png" alt="Installed app — About tab" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-3.png" alt="已安装的应用 — “关于”选项卡" />
|
||||
</div>
|
||||
|
||||
Switch to the **Content** tab to see everything your app provides — objects, fields, logic functions, and agents:
|
||||
切换到 **内容** 选项卡,以查看你的应用提供的全部内容——对象、字段、逻辑函数和智能体:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-4.png" alt="Installed app — Content tab" />
|
||||
<img src="/images/docs/developers/extends/apps/app-in-ui-4.png" alt="已安装的应用 — “内容”选项卡" />
|
||||
</div>
|
||||
|
||||
You are all set! Edit any file in `src/` and the changes will be picked up automatically.
|
||||
一切就绪! 编辑 `src/` 中的任意文件,更改会被自动检测到。
|
||||
|
||||
Head over to [Building Apps](/l/zh/developers/extend/apps/building) for a detailed guide on creating objects, logic functions, front components, skills, and more.
|
||||
前往[构建应用](/l/zh/developers/extend/apps/building),查看关于创建对象、逻辑函数、前端组件、技能等的详细指南。
|
||||
|
||||
---
|
||||
|
||||
## Project structure
|
||||
## 项目结构
|
||||
|
||||
The scaffolder generates the following file structure (shown with `--exhaustive` mode, which includes examples for every entity type):
|
||||
脚手架工具会生成以下文件结构(以 `--exhaustive` 模式展示,其中包含每种实体类型的示例):
|
||||
|
||||
```text filename="my-twenty-app/"
|
||||
my-twenty-app/
|
||||
@@ -190,30 +190,30 @@ my-twenty-app/
|
||||
└── example-agent.ts # Example AI agent definition
|
||||
```
|
||||
|
||||
By default (`--minimal`), only the core files are created: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`. Use `--exhaustive` to include all the example files shown above.
|
||||
默认情况下(`--minimal`),仅创建核心文件:`application-config.ts`、`roles/default-role.ts`、`logic-functions/pre-install.ts` 和 `logic-functions/post-install.ts`。 使用 `--exhaustive` 可包含上面展示的所有示例文件。
|
||||
|
||||
### Key files
|
||||
### 关键文件
|
||||
|
||||
| File / Folder | 目的 |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `package.json` | Declares your app name, version, and dependencies. Includes a `twenty` script so you can run `yarn twenty help` to see all commands. |
|
||||
| `src/application-config.ts` | **Required.** The main configuration file for your app. |
|
||||
| `src/roles/` | Defines roles that control what your logic functions can access. |
|
||||
| `src/logic-functions/` | Server-side functions triggered by routes, cron schedules, or database events. |
|
||||
| `src/front-components/` | React components that render inside Twenty's UI. |
|
||||
| `src/objects/` | Custom object definitions to extend your data model. |
|
||||
| `src/fields/` | Custom fields added to existing objects. |
|
||||
| `src/views/` | Saved view configurations. |
|
||||
| `src/navigation-menu-items/` | Custom links in the sidebar navigation. |
|
||||
| `src/skills/` | 用于扩展 Twenty 的 AI 代理的技能. |
|
||||
| `src/agents/` | AI agents with custom prompts. |
|
||||
| `src/page-layouts/` | Custom page layouts for record views. |
|
||||
| `src/__tests__/` | Integration tests (setup + example test). |
|
||||
| `public/` | Static assets (images, fonts) served with your app. |
|
||||
| 文件 / 文件夹 | 目的 |
|
||||
| ---------------------------- | ------------------------------------------------------------------ |
|
||||
| `package.json` | 声明应用的名称、版本和依赖。 包含一个 `twenty` 脚本,因此你可以运行 `yarn twenty help` 查看所有命令。 |
|
||||
| `src/application-config.ts` | **必需。** 应用的主配置文件。 |
|
||||
| `src/roles/` | 定义角色,用于控制逻辑函数的访问权限。 |
|
||||
| `src/logic-functions/` | 由路由、cron 调度或数据库事件触发的服务端函数。 |
|
||||
| `src/front-components/` | 在 Twenty 的 UI 中渲染的 React 组件。 |
|
||||
| `src/objects/` | 用于扩展数据模型的自定义对象定义。 |
|
||||
| `src/fields/` | 添加到现有对象的自定义字段。 |
|
||||
| `src/views/` | 已保存的视图配置。 |
|
||||
| `src/navigation-menu-items/` | 侧边栏导航中的自定义链接。 |
|
||||
| `src/skills/` | 用于扩展 Twenty 的 AI 代理的技能. |
|
||||
| `src/agents/` | 具有自定义提示词的 AI 智能体。 |
|
||||
| `src/page-layouts/` | 记录视图的自定义页面布局。 |
|
||||
| `src/__tests__/` | 集成测试(设置 + 示例测试)。 |
|
||||
| `public/` | 随应用一起提供的静态资源(图像、字体)。 |
|
||||
|
||||
## Managing remotes
|
||||
## 管理远程
|
||||
|
||||
A **remote** is a Twenty server that your app connects to. During setup, the scaffolder creates one for you automatically. You can add more remotes or switch between them at any time.
|
||||
“远程”是指你的应用连接到的 Twenty 服务器。 在设置期间,脚手架工具会为你自动创建一个。 你可以随时添加更多远程或在它们之间切换。
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Add a new remote (opens a browser for OAuth login)
|
||||
@@ -232,11 +232,11 @@ yarn twenty remote list
|
||||
yarn twenty remote switch <name>
|
||||
```
|
||||
|
||||
Your credentials are stored in `~/.twenty/config.json`.
|
||||
你的凭据存储在 `~/.twenty/config.json` 中。
|
||||
|
||||
## Local development server (`yarn twenty server`)
|
||||
## 本地开发服务器(`yarn twenty server`)
|
||||
|
||||
The CLI can manage a local Twenty server running in Docker. This is the same server started automatically when you scaffold an app with `create-twenty-app`, but you can also manage it manually.
|
||||
CLI 可以管理在 Docker 中运行的本地 Twenty 服务器。 这与使用 `create-twenty-app` 搭建应用时自动启动的服务器相同,但你也可以手动管理它。
|
||||
|
||||
### 启动服务器
|
||||
|
||||
@@ -244,85 +244,85 @@ The CLI can manage a local Twenty server running in Docker. This is the same ser
|
||||
yarn twenty server start
|
||||
```
|
||||
|
||||
This pulls the `twentycrm/twenty-app-dev:latest` Docker image (if not already present), creates a container named `twenty-app-dev`, and starts it on port **2020**. The CLI waits until the server passes its health check before returning.
|
||||
这将拉取 `twentycrm/twenty-app-dev:latest` Docker 镜像(如果尚未存在),创建名为 `twenty-app-dev` 的容器,并在端口 **2020** 上启动它。 CLI 会等待服务器通过健康检查后再返回。
|
||||
|
||||
Two Docker volumes are created to persist data between restarts:
|
||||
会创建两个 Docker 卷,以在重启之间持久化数据:
|
||||
|
||||
* `twenty-app-dev-data` — PostgreSQL database
|
||||
* `twenty-app-dev-storage` — file storage
|
||||
* `twenty-app-dev-data` — PostgreSQL 数据库
|
||||
* `twenty-app-dev-storage` — 文件存储
|
||||
|
||||
If port 2020 is already in use, you can start on a different port:
|
||||
如果端口 2020 已被占用,你可以在其他端口上启动:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server start --port 3030
|
||||
```
|
||||
|
||||
The CLI automatically configures the container's internal `NODE_PORT` and `SERVER_URL` to match the chosen port, so logic functions, OAuth, and all other internal networking work correctly.
|
||||
CLI 会自动配置容器内部的 `NODE_PORT` 和 `SERVER_URL` 以匹配所选端口,从而使逻辑函数、OAuth 以及所有其他内部网络正常工作。
|
||||
|
||||
Once started, the server is automatically registered as the `local` remote in your CLI config.
|
||||
启动后,该服务器会在你的 CLI 配置中自动注册为 `local` 远程。
|
||||
|
||||
### Checking server status
|
||||
### 检查服务器状态
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server status
|
||||
```
|
||||
|
||||
Displays whether the server is running, its URL, and the default login credentials (`tim@apple.dev` / `tim@apple.dev`).
|
||||
显示服务器是否在运行、其 URL,以及默认登录凭据(`tim@apple.dev` / `tim@apple.dev`)。
|
||||
|
||||
### Viewing server logs
|
||||
### 查看服务器日志
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server logs
|
||||
```
|
||||
|
||||
Streams the container logs. Use `--lines` to control how many recent lines to show:
|
||||
持续输出容器日志。 使用 `--lines` 控制显示的最近日志行数:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server logs --lines 100
|
||||
```
|
||||
|
||||
### Stopping the server
|
||||
### 停止服务器
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server stop
|
||||
```
|
||||
|
||||
Stops the container. Your data is preserved in the Docker volumes — the next `start` picks up where you left off.
|
||||
停止容器。 你的数据会保存在 Docker 卷中——下次 `start` 会从上次中断处继续。
|
||||
|
||||
### Resetting the server
|
||||
### 重置服务器
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty server reset
|
||||
```
|
||||
|
||||
Removes the container **and** deletes both Docker volumes, wiping all data. The next `start` creates a fresh instance.
|
||||
移除容器并删除这两个 Docker 卷,清除所有数据。 下一次 `start` 会创建一个全新实例。
|
||||
|
||||
<Note>
|
||||
The server requires **Docker** to be running. If you see a "Docker not running" error, make sure Docker Desktop (or the Docker daemon) is started.
|
||||
服务器需要 Docker 处于运行状态。 如果看到 "Docker not running" 错误,请确保 Docker Desktop(或 Docker 守护进程)已启动。
|
||||
</Note>
|
||||
|
||||
### Command reference
|
||||
### 命令参考
|
||||
|
||||
| 命令 | 描述 |
|
||||
| -------------------------------------- | ---------------------------------------------- |
|
||||
| `yarn twenty server start` | Start the local server (pulls image if needed) |
|
||||
| `yarn twenty server start --port 3030` | Start on a custom port |
|
||||
| `yarn twenty server stop` | Stop the server (preserves data) |
|
||||
| `yarn twenty server status` | Show server status, URL, and credentials |
|
||||
| `yarn twenty server logs` | Stream server logs |
|
||||
| `yarn twenty server logs --lines 100` | Show the last 100 log lines |
|
||||
| `yarn twenty server reset` | Delete all data and start fresh |
|
||||
| 命令 | 描述 |
|
||||
| -------------------------------------- | --------------- |
|
||||
| `yarn twenty server start` | 启动本地服务器(按需拉取镜像) |
|
||||
| `yarn twenty server start --port 3030` | 在自定义端口启动 |
|
||||
| `yarn twenty server stop` | 停止服务器(保留数据) |
|
||||
| `yarn twenty server status` | 显示服务器状态、URL 和凭据 |
|
||||
| `yarn twenty server logs` | 流式输出服务器日志 |
|
||||
| `yarn twenty server logs --lines 100` | 显示最近 100 行日志 |
|
||||
| `yarn twenty server reset` | 删除所有数据并全新开始 |
|
||||
|
||||
## CI with GitHub Actions
|
||||
## 使用 GitHub Actions 进行 CI
|
||||
|
||||
The scaffolder generates a ready-to-use GitHub Actions workflow at `.github/workflows/ci.yml`. It runs your integration tests automatically on every push to `main` and on pull requests.
|
||||
脚手架工具会在 `.github/workflows/ci.yml` 生成一个开箱即用的 GitHub Actions 工作流。 它会在每次向 `main` 推送以及拉取请求上自动运行你的集成测试。
|
||||
|
||||
The workflow:
|
||||
工作流:
|
||||
|
||||
1. Checks out your code
|
||||
2. Spins up a temporary Twenty server using the `twentyhq/twenty/.github/actions/spawn-twenty-docker-image` action
|
||||
3. Installs dependencies with `yarn install --immutable`
|
||||
4. Runs `yarn test` with `TWENTY_API_URL` and `TWENTY_API_KEY` injected from the action outputs
|
||||
1. 检出你的代码
|
||||
2. 使用 `twentyhq/twenty/.github/actions/spawn-twenty-docker-image` 动作启动一个临时的 Twenty 服务器
|
||||
3. 使用 `yarn install --immutable` 安装依赖
|
||||
4. 运行 `yarn test`,并从该动作的输出中注入 `TWENTY_API_URL` 和 `TWENTY_API_KEY`
|
||||
|
||||
```yaml .github/workflows/ci.yml
|
||||
name: CI
|
||||
@@ -369,21 +369,21 @@ jobs:
|
||||
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
|
||||
```
|
||||
|
||||
You don't need to configure any secrets — the `spawn-twenty-docker-image` action starts an ephemeral Twenty server directly in the runner and outputs the connection details. The `GITHUB_TOKEN` secret is provided automatically by GitHub.
|
||||
你无需配置任何机密——`spawn-twenty-docker-image` 动作会在运行器中直接启动一个临时的 Twenty 服务器,并输出连接详情。 GitHub 会自动提供 `GITHUB_TOKEN` 机密。
|
||||
|
||||
To pin a specific Twenty version instead of `latest`, change the `TWENTY_VERSION` environment variable at the top of the workflow.
|
||||
若要固定为特定的 Twenty 版本而不是 `latest`,请在工作流顶部修改 `TWENTY_VERSION` 环境变量。
|
||||
|
||||
## 手动设置(不使用脚手架)
|
||||
|
||||
If you prefer to set things up yourself instead of using `create-twenty-app`, you can do it in two steps.
|
||||
如果你不想使用 `create-twenty-app`,而是自行完成设置,可以分两步进行。
|
||||
|
||||
**1. Add `twenty-sdk` and `twenty-client-sdk` as dependencies:**
|
||||
\*\*1. 将 `twenty-sdk` 和 `twenty-client-sdk` 添加为依赖项:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn add twenty-sdk twenty-client-sdk
|
||||
```
|
||||
|
||||
**2. Add a `twenty` script to your `package.json`:**
|
||||
\*\*2. 在你的 `package.json` 中添加一个 `twenty` 脚本:
|
||||
|
||||
```json filename="package.json"
|
||||
{
|
||||
@@ -393,19 +393,19 @@ yarn add twenty-sdk twenty-client-sdk
|
||||
}
|
||||
```
|
||||
|
||||
You can now run `yarn twenty dev`, `yarn twenty help`, and all other commands.
|
||||
现在你可以运行 `yarn twenty dev`、`yarn twenty help` 以及所有其他命令。
|
||||
|
||||
<Note>
|
||||
Do not install `twenty-sdk` globally. Always use it as a local project dependency so that each project can pin its own version.
|
||||
不要全局安装 `twenty-sdk`。 始终将其作为本地项目依赖使用,以便每个项目都能固定其自己的版本。
|
||||
</Note>
|
||||
|
||||
## 故障排除
|
||||
|
||||
If you run into issues:
|
||||
如果遇到问题:
|
||||
|
||||
* Make sure **Docker is running** before starting the scaffolder with a local instance.
|
||||
* Make sure you are using **Node.js 24+** (`node -v` to check).
|
||||
* Make sure **Corepack is enabled** (`corepack enable`) so Yarn 4 is available.
|
||||
* Try deleting `node_modules` and running `yarn install` again if dependencies seem broken.
|
||||
* 在使用本地实例启动脚手架工具之前,请确保**Docker 已在运行**。
|
||||
* 请确保使用 **Node.js 24+**(运行 `node -v` 进行检查)。
|
||||
* 请确保**已启用 Corepack**(`corepack enable`),以便可使用 Yarn 4。
|
||||
* 如果依赖似乎有问题,尝试删除 `node_modules` 并重新运行 `yarn install`。
|
||||
|
||||
Still stuck? Ask for help on the [Twenty Discord](https://discord.com/channels/1130383047699738754/1130386664812982322).
|
||||
仍然遇到问题? 在 [Twenty 的 Discord](https://discord.com/channels/1130383047699738754/1130386664812982322) 上寻求帮助。
|
||||
|
||||
Reference in New Issue
Block a user