twenty-sdk package provides defineEntity functions to declare your app’s data model. 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.
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.defineRole
Configurar permissões de papéis e acesso a objetos
defineRole
Configurar permissões de papéis e acesso a objetos
Papéis encapsulam permissões sobre os objetos e ações do seu espaço de trabalho.
restricted-company-role.ts
defineApplication
Configurar metadados do aplicativo (obrigatório, um por app)
defineApplication
Configurar metadados do aplicativo (obrigatório, um por app)
Todo app deve ter exatamente uma chamada a Notas:
O
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.
src/application-config.ts
- 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 |
|---|---|
author | Nome do autor ou da empresa |
category | 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:src/roles/default-role.ts
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
Objetos personalizados descrevem tanto o esquema quanto o comportamento de registros no seu espaço de trabalho. Use Pontos-chave:
defineObject() para definir objetos com validação integrada:postCard.object.ts
- 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.
Os campos base são criados automaticamente. Quando você define um objeto personalizado, o Twenty adiciona automaticamente campos padrão
como
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
Use Pontos-chave:
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:src/fields/company-loyalty-tier.field.ts
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
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.Existem dois tipos de relação:
Etapa 2: Defina o lado MANY_TO_ONE em PostCardRecipient (o lado “muitos” — contém a chave estrangeira):
| 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”):src/fields/post-card-recipients-on-post-card.field.ts
src/fields/post-card-on-post-card-recipient.field.ts
Importações circulares: Ambos os campos de relação referenciam o
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:src/fields/person-on-self-hosting-user.field.ts
Propriedades de campos de relação
| Propriedade | Obrigatório | Descrição |
|---|---|---|
type | 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: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 |
| Papel | 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: