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.
Funções DefineEntity
O SDK fornece funções para definir as entidades do seu app. Você deve usarexport 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.
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.defineRole
Configura permissões de papéis e acesso a objetos
defineRole
Configura permissões de papéis e acesso a objetos
defineApplication
Configurar metadados do aplicativo (obrigatório, um por app)
defineApplication
Configurar metadados do aplicativo (obrigatório, um por app)
defineApplication que descreve:- 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.
- Os campos
universalIdentifiersão IDs determinísticos que você controla. Gere-os uma vez e mantenha-os estáveis entre sincronizações. applicationVariablestornam-se variáveis de ambiente para suas funções e componentes de front-end (por exemplo,DEFAULT_RECIPIENT_NAMEfica disponível comoprocess.env.DEFAULT_RECIPIENT_NAME).defaultRoleUniversalIdentifierdeve fazer referência a um papel definido comdefineRole()(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
Se você planeja publicar seu app, 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 | 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 |
emailSupport | Endereço de e-mail de suporte |
issueReportUrl | Link para o rastreador de problemas |
Papéis e permissões
O campodefaultRoleUniversalIdentifier 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.- 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.
Papel de função padrão
Ao criar um novo app com o scaffold, a CLI cria um arquivo de papel padrão:universalIdentifier desse papel é referenciado em application-config.ts como defaultRoleUniversalIdentifier:- *.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.
- Comece pelo papel gerado pelo scaffold e depois restrinja-o progressivamente seguindo o princípio do menor privilégio.
- Substitua
objectPermissionsefieldPermissionspelos objetos e campos de que suas funções realmente precisam. permissionFlagscontrolam 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.
defineObject
Define objetos personalizados com campos
defineObject
Define objetos personalizados com campos
defineObject() para definir objetos com validação integrada:- Use
defineObject()para validação integrada e melhor suporte na IDE. - O
universalIdentifierdeve ser exclusivo e estável entre implantações. - Cada campo requer
name,type,labele seu própriouniversalIdentifierestável. - O array
fieldsé opcional — você pode definir objetos sem campos personalizados. - Você pode criar novos objetos usando
yarn twenty add, que orienta você sobre nomeação, campos e relacionamentos.
id, name, createdAt, updatedAt, createdBy, updatedBy e deletedAt.
Você não precisa definir esses no seu array fields — adicione apenas seus campos personalizados.
Você pode substituir os campos padrão definindo um campo com o mesmo nome no seu array fields,
mas isso não é recomendado.defineField — Campos padrão
Estender objetos existentes com campos adicionais
defineField — Campos padrão
Estender objetos existentes com campos adicionais
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:objectUniversalIdentifieridentifica o objeto de destino. Para objetos padrão, useSTANDARD_OBJECT_UNIVERSAL_IDENTIFIERSexportado detwenty-sdk.- Ao definir campos inline em
defineObject(), você não precisa deobjectUniversalIdentifier— ele é herdado do objeto pai. defineField()é a única forma de adicionar campos a objetos que você não criou comdefineObject().
defineField — Campos de relação
Conecte objetos com relações bidirecionais
defineField — Campos de relação
Conecte objetos com relações bidirecionais
| Tipo de relação | Descrição | Tem chave estrangeira? |
|---|---|---|
MANY_TO_ONE | Muitos registros deste objeto apontam para um registro do destino | Sim (joinColumnName) |
ONE_TO_MANY | Um registro deste objeto possui muitos registros do destino | Não (lado inverso) |
Como as relações funcionam
Toda relação requer dois campos que façam referência um ao outro:- O lado MANY_TO_ONE — fica no objeto que contém a chave estrangeira
- O lado ONE_TO_MANY — fica no objeto que possui a coleção
FieldType.RELATION e fazem referência cruzada um ao outro via relationTargetFieldMetadataUniversalIdentifier.Exemplo: Um cartão postal tem muitos destinatários
Suponha que umPostCard possa ser enviado para muitos registros PostCardRecipient. Cada destinatário pertence a exatamente um cartão postal.Etapa 1: Defina o lado ONE_TO_MANY em PostCard (o lado “um”):universalIdentifier um do outro. Para evitar problemas de importação circular, exporte os IDs dos seus campos como constantes nomeadas de cada arquivo e importe-os no outro arquivo. O sistema de build resolve isso em tempo de compilação.Relacionando a objetos padrão
Para criar uma relação com um objeto integrado do Twenty (Person, Company, etc.), useSTANDARD_OBJECT_UNIVERSAL_IDENTIFIERS:Propriedades de campos de relação
| Propriedade | Obrigatório | Descrição |
|---|---|---|
tipo | Sim | Deve ser FieldType.RELATION |
relationTargetObjectMetadataUniversalIdentifier | Sim | O universalIdentifier do objeto de destino |
relationTargetFieldMetadataUniversalIdentifier | Sim | O universalIdentifier do campo correspondente no objeto de destino |
universalSettings.relationType | Sim | RelationType.MANY_TO_ONE ou RelationType.ONE_TO_MANY |
universalSettings.onDelete | Apenas para MANY_TO_ONE | O que acontece quando o registro referenciado é excluído: CASCADE, SET_NULL, RESTRICT ou NO_ACTION |
universalSettings.joinColumnName | Apenas para MANY_TO_ONE | Nome da coluna no banco de dados para a chave estrangeira (por exemplo, postCardId) |
Campos de relação inline em defineObject
Você também pode definir campos de relação diretamente dentro dedefineObject(). Nesse caso, omita objectUniversalIdentifier — ele é herdado do objeto pai:defineLogicFunction
Defina funções de lógica e seus gatilhos
defineLogicFunction
Defina funções de lógica e seus gatilhos
defineLogicFunction() para exportar uma configuração com um handler e gatilhos opcionais.- httpRoute: Expõe sua função em um caminho e método HTTP no endpoint
/s/:
por exemplo,path: '/post-card/create'é acessível emhttps://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 arrayupdatedFields. Se deixar indefinido ou vazio, qualquer atualização acionará a função.
por exemplo,person.updated,*.created,company.*
Payload de gatilho de rota
Quando um gatilho de rota invoca sua função de lógica, ela recebe um objetoRoutePayload que segue o formato HTTP API v2 da AWS.
Importe o tipo RoutePayload de twenty-sdk:RoutePayload tem a seguinte estrutura:| Propriedade | Tipo | Descrição | Exemplo |
|---|---|---|---|
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> | 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) | |
requestContext.http.path | string | Caminho bruto da requisição |
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. Para acessar cabeçalhos específicos, liste-os explicitamente no arrayforwardedRequestHeaders:event.headers['content-type']).Expor uma função como ferramenta
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.Para marcar uma função de lógica como ferramenta, definaisTool: true:- Você pode combinar
isToolcom 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:
description. Os agentes de IA dependem do campo description da função para decidir quando usar a ferramenta. Seja específico sobre o que a ferramenta faz e quando ela deve ser chamada.definePreInstallLogicFunction
Defina uma função de lógica de pré-instalação (uma por aplicativo)
definePreInstallLogicFunction
Defina uma função de lógica de pré-instalação (uma por aplicativo)
- As funções de pré-instalação usam
definePreInstallLogicFunction()— uma variante especializada que omite as configurações de gatilho (cronTriggerSettings,databaseEventTriggerSettings,httpRouteTriggerSettings,isTool). - O manipulador recebe um
InstallLogicFunctionPayloadcom{ previousVersion: string }— a versão do app que foi instalada anteriormente (ou uma string vazia para instalações novas). - É permitida apenas uma função de pré-instalação por app. A geração do manifesto apresentará erro se mais de uma for detectada.
- O
universalIdentifierda função é definido automaticamente comopreInstallLogicFunctionUniversalIdentifierno manifesto do aplicativo durante a geração — você não precisa referenciá-lo emdefineApplication(). - O tempo limite padrão é definido como 300 segundos (5 minutos) para permitir tarefas de preparação mais longas.
definePostInstallLogicFunction
Defina uma função de lógica de pós-instalação (uma por aplicativo)
definePostInstallLogicFunction
Defina uma função de lógica de pós-instalação (uma por aplicativo)
- As funções de pós-instalação usam
definePostInstallLogicFunction()— uma variante especializada que omite as configurações de gatilho (cronTriggerSettings,databaseEventTriggerSettings,httpRouteTriggerSettings,isTool). - O manipulador recebe um
InstallLogicFunctionPayloadcom{ previousVersion: string }— a versão do app que foi instalada anteriormente (ou uma string vazia para instalações novas). - É permitida apenas uma função de pós-instalação por app. A geração do manifesto apresentará erro se mais de uma for detectada.
- O
universalIdentifierda função é definido automaticamente comopostInstallLogicFunctionUniversalIdentifierno manifesto do aplicativo durante a geração — você não precisa referenciá-lo emdefineApplication(). - O tempo limite padrão é definido como 300 segundos (5 minutos) para permitir tarefas de configuração mais longas, como o pré-carregamento de dados.
defineFrontComponent
Definir componentes de front-end para UI personalizada
defineFrontComponent
Definir componentes de front-end para UI personalizada
Onde os componentes de front-end podem ser usados
Os componentes de front-end podem ser renderizados em dois locais dentro do Twenty:- Painel lateral — Componentes de front-end não headless abrem no painel lateral direito. Este é o comportamento padrão quando um componente de front-end é acionado pelo menu de comandos.
- Widgets (painéis e páginas de registro) — Componentes de front-end podem ser incorporados como widgets nos layouts de página. Ao configurar um painel ou o layout de uma página de registro, os usuários podem adicionar um widget de componente de front-end.
Exemplo básico
A maneira mais rápida de ver um componente de front-end em ação é registrá-lo como um comando. Adicionar um campocommand 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:yarn twenty dev, a ação rápida aparece no canto superior direito da página:
Campos de configuração
| Campo | Obrigatório | Descrição |
|---|---|---|
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 | Defina como true se o componente não tiver interface visível (veja abaixo) |
command | Não | Registre o componente como um comando (veja opções de comando abaixo) |
Colocando um componente de front-end em uma página
Além de comandos, você pode incorporar um componente de front-end diretamente em uma página de registro adicionando-o como um widget em um layout de página. Veja a seção definePageLayout para obter detalhes.Headless vs não headless
Os componentes de front-end têm dois modos de renderização controlados pela opçãoisHeadless:Não headless (padrão) — O componente renderiza uma interface visível. Quando acionado pelo menu de comandos, ele é aberto no painel lateral. Este é o comportamento padrão quando isHeadless é false ou omitido.Headless (isHeadless: true) — The component mounts invisibly in the background. Ele não abre o painel lateral. Componentes headless são projetados para ações que executam lógica e, em seguida, se desmontam — por exemplo, executar uma tarefa assíncrona, navegar para uma página ou exibir um modal de confirmação. Eles se combinam naturalmente com os componentes Command do SDK descritos abaixo.null, o Twenty ignora renderizar um contêiner para ele — nenhum espaço vazio aparece no layout. O componente ainda tem acesso a todos os hooks e à API de comunicação do host.Componentes Command do SDK
O pacotetwenty-sdk fornece quatro componentes auxiliares Command projetados para componentes de front-end headless. Cada componente executa uma ação ao montar, trata erros exibindo uma notificação de snackbar e desmonta automaticamente o componente de front-end ao concluir.Importe-os de twenty-sdk/command:Command— Executa um callback assíncrono via a propexecute.CommandLink— Navega para um caminho do app. Props:to,params,queryParams,options.CommandModal— Abre um modal de confirmação. Se o usuário confirmar, executa o callbackexecute. Props:title,subtitle,execute,confirmButtonText,confirmButtonAccent.CommandOpenSidePanelPage— Abre uma página específica do painel lateral. Props:page,pageTitle,pageIcon.
Command para executar uma ação a partir do menu de comandos:CommandModal para solicitar confirmação antes de executar:Acessando o contexto de execução
Dentro do seu componente, use hooks do SDK para acessar o usuário atual, o registro e a instância do componente:| Hook | Retorna | Descrição |
|---|---|---|
useUserId() | string ou null | O ID do usuário atual |
useRecordId() | string ou null | O ID do registro atual (quando colocado em uma página de registro) |
useFrontComponentId() | string | O ID desta instância do componente |
useFrontComponentExecutionContext(selector) | varia | Acesse o contexto de execução completo com uma função seletora |
API de comunicação do host
Componentes de front-end podem acionar navegação, modais e notificações usando funções detwenty-sdk:| Função | Descrição |
|---|---|
navigate(to, params?, queryParams?, options?) | Navegar para uma página no app |
openSidePanelPage(params) | Abrir um painel lateral |
closeSidePanel() | Fecha o painel lateral |
openCommandConfirmationModal(params) | Mostrar um diálogo de confirmação |
enqueueSnackbar(params) | Mostrar uma notificação do tipo toast |
unmountFrontComponent() | Desmontar o componente |
updateProgress(progress) | Atualizar um indicador de progresso |
Opções de comando
Adicionar um campocommand a defineFrontComponent registra o componente no menu de comandos (Cmd+K). Se isPinned for true, ele também aparece como um botão de ação rápida no canto superior direito da página.| Campo | Obrigatório | Descrição |
|---|---|---|
universalIdentifier | Sim | ID exclusivo e estável para o comando |
label | Sim | Rótulo completo exibido no menu de comandos (Cmd+K) |
shortLabel | Não | Rótulo mais curto exibido no botão fixado de ação rápida |
icon | Não | Nome do ícone exibido ao lado do rótulo (por exemplo, 'IconBolt', 'IconSend') |
isPinned | Não | Quando true, mostra o comando como um botão de ação rápida no canto superior direito da página |
availabilityType | Não | Controla onde o comando aparece: 'GLOBAL' (sempre disponível), 'RECORD_SELECTION' (apenas quando registros estão selecionados) ou 'FALLBACK' (exibido quando nenhum outro comando corresponde) |
availabilityObjectUniversalIdentifier | Não | Restringe o comando a páginas de um tipo específico de objeto (por exemplo, somente em registros de Company) |
conditionalAvailabilityExpression | Não | Uma expressão booleana para controlar dinamicamente se o comando é visível (veja abaixo) |
Expressões de disponibilidade condicional
O campoconditionalAvailabilityExpression permite controlar quando um comando é visível com base no contexto da página atual. Importe variáveis tipadas e operadores de twenty-sdk para construir expressões:| Variável | Tipo | Descrição |
|---|---|---|
pageType | string | Tipo de página atual (por exemplo, 'RecordIndexPage', 'RecordShowPage') |
isInSidePanel | boolean | Se o componente é renderizado em um painel lateral |
numberOfSelectedRecords | number | Número de registros atualmente selecionados |
isSelectAll | boolean | Se “selecionar tudo” está ativo |
selectedRecords | array | Os objetos de registro selecionados |
favoriteRecordIds | array | IDs dos registros marcados como favoritos |
objectPermissions | object | Permissões para o tipo de objeto atual |
targetObjectReadPermissions | object | Permissões de leitura para o objeto alvo |
targetObjectWritePermissions | object | Permissões de escrita para o objeto alvo |
featureFlags | object | Flags de recurso ativas |
objectMetadataItem | object | Metadados do tipo de objeto atual |
hasAnySoftDeleteFilterOnView | boolean | Se a visualização atual tem um filtro de soft-delete |
| Operador | Descrição |
|---|---|
isDefined(value) | true se o valor não for null/undefined |
isNonEmptyString(value) | true se o valor for uma string não vazia |
includes(array, value) | true se o array contiver o valor |
includesEvery(array, prop, value) | true se a propriedade de cada item incluir o valor |
every(array, prop) | true se a propriedade for truthy em cada item |
everyDefined(array, prop) | true se a propriedade estiver definida em cada item |
everyEquals(array, prop, value) | true se a propriedade for igual ao valor em cada item |
some(array, prop) | true se a propriedade for truthy em pelo menos um item |
someDefined(array, prop) | true se a propriedade estiver definida em pelo menos um item |
someEquals(array, prop, value) | true se a propriedade for igual ao valor em pelo menos um item |
someNonEmptyString(array, prop) | true se a propriedade for uma string não vazia em pelo menos um item |
none(array, prop) | true se a propriedade for falsy em cada item |
noneDefined(array, prop) | true se a propriedade for undefined em cada item |
noneEquals(array, prop, value) | true se a propriedade não for igual ao valor em nenhum item |
Recursos públicos
Componentes de front-end podem acessar arquivos do diretóriopublic/ do app usando getPublicAssetUrl:Estilização
Componentes de front-end suportam várias abordagens de estilização. Você pode usar:- Estilos inline —
style={{ color: 'red' }} - Componentes de UI do Twenty — importe de
twenty-sdk/ui(Button, Tag, Status, Chip, Avatar e mais) - Emotion — CSS-in-JS com
@emotion/react - Styled-components — padrões
styled.div - Tailwind CSS — classes utilitárias
- Qualquer biblioteca CSS-in-JS compatível com React
defineSkill
Define habilidades de agente de IA
defineSkill
Define habilidades de agente de IA
defineSkill() para definir habilidades com validação integrada:nameé uma string de identificador exclusivo para a habilidade (recomenda-se kebab-case).labelé o nome de exibição legível por humanos mostrado na UI.contentcontém as instruções da habilidade — este é o texto que o agente de IA usa.icon(opcional) define o ícone exibido na UI.description(opcional) fornece contexto adicional sobre a finalidade da habilidade.
defineAgent
Defina agentes de IA com prompts personalizados
defineAgent
Defina agentes de IA com prompts personalizados
defineAgent() para criar agentes com um prompt de sistema personalizado:nameé a string de identificador exclusiva do agente (recomenda-se kebab-case).labelé o nome de exibição mostrado na UI.prompté o prompt do sistema que define o comportamento do agente.description(opcional) fornece contexto sobre o que o agente faz.icon(opcional) define o ícone exibido na UI.modelId(opcional) substitui o modelo de IA padrão usado pelo agente.
defineView
Define visualizações salvas para objetos
defineView
Define visualizações salvas para objetos
defineView() para enviar visualizações pré-configuradas com seu app:objectUniversalIdentifierespecifica a qual objeto esta visualização se aplica.keydetermina o tipo de visualização (por exemplo,ViewKey.INDEXpara a visualização de lista principal).fieldscontrola quais colunas aparecem e sua ordem. Cada campo referencia umfieldMetadataUniversalIdentifier.- Você também pode definir
filters,filterGroups,groupsefieldGroupspara configurações mais avançadas. positioncontrola a ordenação quando existem várias visualizações para o mesmo objeto.
defineNavigationMenuItem
Define links de navegação da barra lateral
defineNavigationMenuItem
Define links de navegação da barra lateral
definePageLayout
Defina layouts de página personalizados para visualizações de registro
definePageLayout
Defina layouts de página personalizados para visualizações de registro
definePageLayout() para enviar layouts personalizados com seu app:typegeralmente é'RECORD_PAGE'para personalizar a visualização de detalhes de um objeto específico.objectUniversalIdentifierespecifica a qual objeto este layout se aplica.- Cada
tabdefine uma seção da página com umtitle,positionelayoutMode(CANVASpara layout livre). - Cada
widgetdentro de uma aba pode renderizar um componente de front-end, uma lista de relações ou outros tipos de widget incorporados. positionnas abas controla sua ordem. Use valores mais altos (por exemplo, 50) para colocar abas personalizadas após as nativas.
Recursos públicos (pasta public/)
A pasta public/ na raiz do seu app contém arquivos estáticos — imagens, ícones, fontes ou quaisquer outros recursos de que seu app precisa em tempo de execução. Esses arquivos são incluídos automaticamente nas compilações, sincronizados durante o modo de desenvolvimento e enviados para o servidor.
Arquivos colocados em public/ são:
- Publicamente acessíveis — depois de sincronizados com o servidor, os recursos são servidos em uma URL pública. Não é necessária autenticação para acessá-los.
- Disponíveis em componentes de front-end — use URLs de recursos para exibir imagens, ícones ou qualquer mídia dentro de seus componentes React.
- Disponíveis em funções lógicas — referencie URLs de recursos em e-mails, respostas de API ou qualquer lógica no lado do servidor.
- Usados para metadados do marketplace — os campos
logoUrlescreenshotsemdefineApplication()referenciam arquivos desta pasta (por exemplo,public/logo.png). Eles são exibidos no marketplace quando seu app é publicado. - Sincronizados automaticamente no modo de desenvolvimento — quando você adiciona, atualiza ou exclui um arquivo em
public/, ele é sincronizado automaticamente com o servidor. Não é necessário reiniciar. - Incluídos nas compilações —
yarn twenty buildagrupa todos os recursos públicos na saída de distribuição.
Acessando recursos públicos com getPublicAssetUrl
Use o helper getPublicAssetUrl de twenty-sdk para obter a URL completa de um arquivo no seu diretório public/. Funciona tanto em funções lógicas quanto em componentes de front-end.
Em uma função lógica:
path é relativo à pasta public/ do seu app. Tanto getPublicAssetUrl('logo.png') quanto getPublicAssetUrl('public/logo.png') resolvem para a mesma URL — o prefixo public/ é removido automaticamente, se presente.
Usando pacotes npm
Você pode instalar e usar qualquer pacote npm no seu app. Tanto funções lógicas quanto componentes de front-end são empacotados com esbuild, que incorpora todas as dependências na saída — nenhumnode_modules é necessário em tempo de execução.
Instalando um pacote
Como o empacotamento funciona
A etapa de build (yarn twenty dev ou yarn twenty build) usa o esbuild para produzir um único arquivo independente por função lógica e por componente de front-end. Todos os pacotes importados são incorporados ao bundle.
Funções lógicas são executadas em um ambiente Node.js. Módulos nativos do Node (fs, path, crypto, http, etc.) estão disponíveis e não precisam ser instalados.
Componentes de front-end são executados em um Web Worker. Módulos nativos do Node não estão disponíveis — apenas APIs do navegador e pacotes npm que funcionam em um ambiente de navegador.
Ambos os ambientes têm twenty-client-sdk/core e twenty-client-sdk/metadata disponíveis como módulos pré-fornecidos — eles não são empacotados, mas resolvidos em tempo de execução pelo servidor.
Gerando entidades com yarn twenty add
Em vez de criar arquivos de entidade manualmente, você pode usar o scaffolder interativo:
universalIdentifier estável e a chamada correta de defineEntity().
Você também pode passar o tipo de entidade diretamente para pular o primeiro prompt:
Tipos de entidade disponíveis
| Tipo de entidade | Comando | Arquivo gerado |
|---|---|---|
| Objeto | yarn twenty add object | src/objects/<name>.ts |
| Campo | yarn twenty add field | src/fields/<name>.ts |
| Função lógica | yarn twenty add logicFunction | src/logic-functions/<name>.ts |
| Componente de front-end | yarn twenty add frontComponent | src/front-components/<name>.tsx |
| Função | yarn twenty add role | src/roles/<name>.ts |
| Habilidade | yarn twenty add skill | src/skills/<name>.ts |
| Agente | yarn twenty add agent | src/agents/<name>.ts |
| Vista | yarn twenty add view | src/views/<name>.ts |
| Item do menu de navegação | yarn twenty add navigationMenuItem | src/navigation-menu-items/<name>.ts |
| Layout da página | yarn twenty add pageLayout | src/page-layouts/<name>.ts |
O que o scaffolder gera
Cada tipo de entidade tem seu próprio modelo. Por exemplo,yarn twenty add object solicita:
- Nome (singular) — por exemplo,
invoice - Nome (plural) — por exemplo,
invoices - Rótulo (singular) — preenchido automaticamente a partir do nome (por exemplo,
Invoice) - Rótulo (plural) — preenchido automaticamente (por exemplo,
Invoices) - Criar uma view e um item de navegação? — se você responder sim, o scaffolder também gera uma view correspondente e um link na barra lateral para o novo objeto.
field é mais detalhado: ele solicita o nome do campo, rótulo, tipo (a partir de uma lista de todos os tipos de campo disponíveis como TEXT, NUMBER, SELECT, RELATION, etc.) e o universalIdentifier do objeto de destino.
Caminho de saída personalizado
Use a opção--path para colocar o arquivo gerado em um local personalizado:
Clientes de API tipados (twenty-client-sdk)
O pacotetwenty-client-sdk fornece dois clientes GraphQL tipados para interagir com a API do Twenty a partir das suas funções de lógica e componentes de front-end.
| Cliente | Importar | Endpoint | Gerado? |
|---|---|---|---|
CoreApiClient | twenty-client-sdk/core | /graphql — dados do espaço de trabalho (registros, objetos) | Sim, em tempo de dev/build |
MetadataApiClient | twenty-client-sdk/metadata | /metadata — configuração do espaço de trabalho, upload de arquivos | Não, vem pré-compilado |
CoreApiClient
Consultar e modificar dados do espaço de trabalho (registros, objetos)
CoreApiClient
Consultar e modificar dados do espaço de trabalho (registros, objetos)
CoreApiClient é o cliente principal para consultar e mutar dados do espaço de trabalho. Ele é gerado a partir do schema do seu espaço de trabalho durante yarn twenty dev ou yarn twenty build, então é totalmente tipado para corresponder aos seus objetos e campos.true para incluir um campo, use __args para argumentos e aninhe objetos para relações. Você tem preenchimento automático e verificação de tipos completos com base no schema do seu espaço de trabalho.yarn twenty dev ou yarn twenty build, ele lançará um erro. A geração ocorre automaticamente — a CLI analisa o schema GraphQL do seu espaço de trabalho e gera um cliente tipado usando @genql/cli.Usando CoreSchema para anotações de tipo
CoreSchema fornece tipos TypeScript que correspondem aos objetos do seu espaço de trabalho — útil para tipar o estado de componentes ou parâmetros de função:MetadataApiClient
Configuração do espaço de trabalho, aplicativos e upload de arquivos
MetadataApiClient
Configuração do espaço de trabalho, aplicativos e upload de arquivos
MetadataApiClient é fornecido pré-compilado com o SDK (não é necessário gerar). Ele consulta o endpoint /metadata para configuração do espaço de trabalho, aplicativos e upload de arquivos.Carregamento de arquivos
MetadataApiClient inclui um método uploadFile para anexar arquivos a campos do tipo arquivo:| Parâmetro | Tipo | Descrição |
|---|---|---|
fileBuffer | Buffer | O conteúdo bruto do arquivo |
filename | string | O nome do arquivo (usado para armazenamento e exibição) |
contentType | string | Tipo MIME (padrão para application/octet-stream se omitido) |
fieldMetadataUniversalIdentifier | string | O universalIdentifier do campo do tipo arquivo no seu objeto |
- Usa o
universalIdentifierdo campo (não o ID específico do espaço de trabalho), de modo que seu código de upload funcione em qualquer espaço de trabalho onde seu app esteja instalado. - A
urlretornada é um URL assinado que você pode usar para acessar o arquivo enviado.
TWENTY_API_URL— URL base da API do TwentyTWENTY_APP_ACCESS_TOKEN— Chave de curta duração com escopo para o papel de função padrão do seu aplicativo
process.env automaticamente. As permissões da chave de API são determinadas pelo papel referenciado em defaultRoleUniversalIdentifier no seu application-config.ts.Testando seu aplicativo
O SDK fornece APIs programáticas que permitem compilar, implantar, instalar e desinstalar seu aplicativo a partir de código de teste. Em conjunto com Vitest e os clientes de API tipados, você pode escrever testes de integração que verificam que seu aplicativo funciona de ponta a ponta em um servidor Twenty real.Configuração
O aplicativo gerado pelo scaffolder já inclui o Vitest. Se você configurá-lo manualmente, instale as dependências:vitest.config.ts na raiz do seu aplicativo:
APIs programáticas do SDK
O subcaminhotwenty-sdk/cli exporta funções que você pode chamar diretamente a partir do código de teste:
| Função | Descrição |
|---|---|
appBuild | Compilar o aplicativo e, opcionalmente, empacotar um tarball |
appDeploy | Enviar um tarball para o servidor |
appInstall | Instalar o aplicativo no espaço de trabalho ativo |
appUninstall | Desinstalar o aplicativo do espaço de trabalho ativo |
success: boolean e data ou error.
Escrevendo um teste de integração
Aqui está um exemplo completo que compila, implanta e instala o aplicativo e, em seguida, verifica se ele aparece no espaço de trabalho:Executando testes
Certifique-se de que seu servidor Twenty local esteja em execução e, em seguida:Verificação de tipos
Você também pode executar a verificação de tipos no seu aplicativo sem executar os testes:tsc --noEmit e informa quaisquer erros de tipo.
Referência da CLI
Além dedev, build, add e typecheck, a CLI fornece comandos para executar funções, visualizar logs e gerenciar instalações de aplicativos.
Executando funções (yarn twenty exec)
Execute manualmente uma função de lógica sem acioná-la via HTTP, cron ou evento de banco de dados:
Visualizando logs de funções (yarn twenty logs)
Transmita os logs de execução das funções de lógica do seu aplicativo:
yarn twenty server logs, que mostra os logs do contêiner Docker. yarn twenty logs mostra os logs de execução de funções do seu aplicativo a partir do servidor Twenty.Desinstalando um aplicativo (yarn twenty uninstall)
Remova seu aplicativo do espaço de trabalho ativo:
Gerenciando remotos
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.~/.twenty/config.json.
CI com GitHub Actions
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.
O workflow:
- Faz checkout do seu código
- Inicializa um servidor Twenty temporário usando a ação
twentyhq/twenty/.github/actions/spawn-twenty-docker-image - Instala as dependências com
yarn install --immutable - Executa
yarn testcomTWENTY_API_URLeTWENTY_API_KEYinjetados a partir das saídas da 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.
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.