twenty-sdk oferă blocuri de construcție tipizate pentru a crea aplicația. Această pagină acoperă toate tipurile de entități și clienții API disponibili în SDK.
Funcții DefineEntity
SDK-ul oferă funcții pentru definirea entităților aplicației. Trebuie să folosițiexport default defineEntity({...}) pentru ca SDK-ul să detecteze entitățile. Aceste funcții validează configurația în timpul build-ului și oferă completare automată în IDE și siguranța tipurilor.
export default defineEntity(...) indiferent unde se află fișierul. Gruparea fișierelor după tip (de exemplu, logic-functions/, roles/) este doar o convenție pentru organizarea codului, nu o cerință.defineRole
Configurați permisiunile rolurilor și accesul la obiecte
defineRole
Configurați permisiunile rolurilor și accesul la obiecte
defineApplication
Configurați metadatele aplicației (obligatoriu, una per aplicație)
defineApplication
Configurați metadatele aplicației (obligatoriu, una per aplicație)
defineApplication care descrie:- Identitate: identificatori, nume de afișare și descriere.
- Permisiuni: ce rol folosesc funcțiile și componentele front-end ale acesteia.
- (Opțional) Variabile: perechi cheie–valoare expuse funcțiilor ca variabile de mediu.
- (Opțional) funcții de pre-instalare / post-instalare: funcții logice care rulează înainte sau după instalare.
- Câmpurile
universalIdentifiersunt ID-uri deterministe pe care le dețineți. Generați-le o singură dată și mențineți-le stabile între sincronizări. applicationVariablesdevin variabile de mediu pentru funcțiile și componentele front-end (de exemplu,DEFAULT_RECIPIENT_NAMEeste disponibil caprocess.env.DEFAULT_RECIPIENT_NAME).defaultRoleUniversalIdentifiertrebuie să facă referire la un rol definit cudefineRole()(vezi mai sus).- Funcțiile de pre-instalare și post-instalare sunt detectate automat în timpul construirii manifestului — nu trebuie să le referiți în
defineApplication().
Metadate pentru marketplace
Dacă intenționați să publicați aplicația, aceste câmpuri opționale controlează modul în care apare în marketplace:| Câmp | Descriere |
|---|---|
autor | Numele autorului sau al companiei |
categorie | Categoria aplicației pentru filtrarea în marketplace |
logoUrl | Calea către logo-ul aplicației (de ex., public/logo.png) |
screenshots | Array de căi către capturi de ecran (de ex., public/screenshot-1.png) |
aboutDescription | Descriere markdown mai lungă pentru fila “About”. Dacă este omis, marketplace-ul folosește README.md al pachetului de pe npm |
websiteUrl | Link către site-ul dvs. |
termsUrl | Link către termenii de serviciu |
emailSupport | Adresă de e-mail pentru suport |
issueReportUrl | Link către sistemul de urmărire a problemelor |
Roluri și permisiuni
CâmpuldefaultRoleUniversalIdentifier din application-config.ts desemnează rolul implicit utilizat de funcțiile logice și componentele front-end ale aplicației. Consultați defineRole mai sus pentru detalii.- Tokenul de runtime injectat ca
TWENTY_APP_ACCESS_TOKENeste derivat din acest rol. - Clientul tipizat este restricționat la permisiunile acordate acelui rol.
- Respectați principiul celui mai mic privilegiu: creați un rol dedicat doar cu permisiunile de care au nevoie funcțiile.
Rol implicit pentru funcții
Când generați o aplicație nouă, CLI creează un fișier de rol implicit:universalIdentifier al acestui rol este apoi referențiat în application-config.ts ca defaultRoleUniversalIdentifier.- *.role.ts definește ce poate face rolul.
- application-config.ts indică acel rol, astfel încât funcțiile moștenesc permisiunile lui.
- Porniți de la rolul generat, apoi restrângeți-l progresiv urmând principiul celui mai mic privilegiu.
- Înlocuiți
objectPermissionsșifieldPermissionscu obiectele și câmpurile de care au nevoie efectiv funcțiile. permissionFlagscontrolează accesul la capabilități la nivelul platformei. Mențineți-le la minimum.- Vedeți un exemplu funcțional:
hello-world/src/roles/function-role.ts.
defineObject
Definiți obiecte personalizate cu câmpuri
defineObject
Definiți obiecte personalizate cu câmpuri
defineObject() pentru a defini obiecte cu validare încorporată:- Folosiți
defineObject()pentru validare încorporată și suport mai bun în IDE. universalIdentifiertrebuie să fie unic și stabil între implementări.- Fiecare câmp necesită un
name, untype, unlabelși propriuluniversalIdentifierstabil. - Matricea
fieldseste opțională — puteți defini obiecte fără câmpuri personalizate. - Puteți genera obiecte noi folosind
yarn twenty add, care vă ghidează prin denumire, câmpuri și relații.
id, name, createdAt, updatedAt, createdBy, updatedBy și deletedAt.
Nu trebuie să le definiți în tabloul fields — adăugați doar câmpurile personalizate proprii.
Puteți suprascrie câmpurile implicite definind un câmp cu același nume în tabloul fields,
dar acest lucru nu este recomandat.defineField — Câmpuri standard
Extindeți obiectele existente cu câmpuri suplimentare
defineField — Câmpuri standard
Extindeți obiectele existente cu câmpuri suplimentare
defineField() pentru a adăuga câmpuri la obiecte pe care nu le dețineți — cum ar fi obiectele standard Twenty (Person, Company etc.). sau obiecte din alte aplicații. Spre deosebire de câmpurile inline din defineObject(), câmpurile independente necesită un objectUniversalIdentifier pentru a specifica obiectul pe care îl extind:objectUniversalIdentifieridentifică obiectul țintă. Pentru obiectele standard, utilizațiSTANDARD_OBJECT_UNIVERSAL_IDENTIFIERSexportați dintwenty-sdk.- Atunci când definiți câmpuri inline în
defineObject(), nu aveți nevoie deobjectUniversalIdentifier— este moștenit de la obiectul părinte. defineField()este singura modalitate de a adăuga câmpuri la obiecte pe care nu le-ați creat cudefineObject().
defineField — Câmpuri de relație
Conectați obiectele între ele cu relații bidirecționale
defineField — Câmpuri de relație
Conectați obiectele între ele cu relații bidirecționale
| Tip relație | Descriere | Are cheie străină? |
|---|---|---|
MANY_TO_ONE | Multe înregistrări ale acestui obiect indică către o singură înregistrare a țintei | Da (joinColumnName) |
ONE_TO_MANY | O înregistrare a acestui obiect are multe înregistrări ale țintei | Nu (partea inversă) |
Cum funcționează relațiile
Fiecare relație necesită două câmpuri care se referențiază reciproc:- Partea MANY_TO_ONE — se află pe obiectul care deține cheia străină
- Partea ONE_TO_MANY — se află pe obiectul care deține colecția
FieldType.RELATION și se referențiază încrucișat prin relationTargetFieldMetadataUniversalIdentifier.Exemplu: Post Card are mulți destinatari
Presupuneți că unPostCard poate fi trimis către multe înregistrări PostCardRecipient. Fiecare destinatar aparține exact unui Post Card.Pasul 1: Definiți partea ONE_TO_MANY pe PostCard (partea “one”):universalIdentifier. Pentru a evita problemele de import circular, exportați ID-urile câmpurilor ca constante denumite din fiecare fișier și importați-le în celălalt fișier. Sistemul de build le rezolvă în timpul compilării.Relaționarea cu obiectele standard
Pentru a crea o relație cu un obiect Twenty încorporat (Person, Company etc.), utilizațiSTANDARD_OBJECT_UNIVERSAL_IDENTIFIERS:Proprietăți ale câmpului de relație
| Proprietate | Obligatoriu | Descriere |
|---|---|---|
tip | Da | Trebuie să fie FieldType.RELATION |
relationTargetObjectMetadataUniversalIdentifier | Da | universalIdentifier al obiectului țintă |
relationTargetFieldMetadataUniversalIdentifier | Da | universalIdentifier al câmpului corespunzător de pe obiectul țintă |
universalSettings.relationType | Da | RelationType.MANY_TO_ONE sau RelationType.ONE_TO_MANY |
universalSettings.onDelete | Doar MANY_TO_ONE | Ce se întâmplă atunci când înregistrarea referențiată este ștearsă: CASCADE, SET_NULL, RESTRICT sau NO_ACTION |
universalSettings.joinColumnName | Doar MANY_TO_ONE | Numele coloanei din baza de date pentru cheia străină (de ex., postCardId) |
Câmpuri de relație inline în defineObject
Puteți defini, de asemenea, câmpuri de relație direct îndefineObject(). În acest caz, omiteți objectUniversalIdentifier — este moștenit de la obiectul părinte:defineLogicFunction
Definiți funcții logice și declanșatoarele acestora
defineLogicFunction
Definiți funcții logice și declanșatoarele acestora
defineLogicFunction() pentru a exporta o configurație cu un handler și declanșatoare opționale.- httpRoute: Expune funcția pe o cale și metodă HTTP sub endpoint-ul
/s/:
de ex.path: '/post-card/create'este apelabil lahttps://your-twenty-server.com/s/post-card/create
- cron: Rulează funcția pe un program folosind o expresie CRON.
- databaseEvent: Rulează la evenimentele ciclului de viață ale obiectelor din spațiul de lucru. Când operațiunea evenimentului este
updated, câmpurile specifice de urmărit pot fi specificate în array-ulupdatedFields. Dacă este lăsat nedefinit sau gol, orice actualizare va declanșa funcția.
de ex.person.updated,*.created,company.*
Payload-ul declanșatorului de rută
Când un declanșator de rută invocă funcția logică, aceasta primește un obiectRoutePayload care urmează
AWS HTTP API v2 format.
Importați tipul RoutePayload din twenty-sdk:RoutePayload are următoarea structură:| Proprietate | Tip | Descriere | Exemplu |
|---|---|---|---|
headers | Record<string, string | undefined> | Anteturi HTTP (doar cele listate în forwardedRequestHeaders) | consultați secțiunea de mai jos |
queryStringParameters | Record<string, string | undefined> | Parametri query string (valorile multiple unite cu virgule) | /users?ids=1&ids=2&ids=3&name=Alice -> { ids: '1,2,3', name: 'Alice' } |
pathParameters | Record<string, string | undefined> | Parametri de cale extrași din modelul rutei | /users/:id, /users/123 -> { id: '123' } |
body | object | null | Corpul cererii analizat (JSON) | { id: 1 } -> { id: 1 } |
isBase64Encoded | boolean | Indică dacă corpul este codificat în base64 | |
requestContext.http.method | string | Metoda HTTP (GET, POST, PUT, PATCH, DELETE) | |
requestContext.http.path | string | Calea brută a cererii |
forwardedRequestHeaders
În mod implicit, anteturile HTTP din cererile de intrare nu sunt transmise funcției dvs. de logică din motive de securitate. Pentru a accesa anumite anteturi, listează-le explicit în array-ulforwardedRequestHeaders:event.headers['content-type']).Expunerea unei funcții ca instrument
Funcțiile logice pot fi expuse ca instrumente pentru agenți de IA și fluxuri de lucru. Când este marcată ca instrument, o funcție poate fi descoperită de funcționalitățile de IA ale Twenty și poate fi utilizată în automatizări ale fluxurilor de lucru.Pentru a marca o funcție logică drept instrument, setațiisTool: true:- Puteți combina
isToolcu declanșatoare — o funcție poate fi atât un instrument (apelabilă de agenții AI), cât și declanșată de evenimente în același timp. toolInputSchema(opțional): Un obiect JSON Schema care descrie parametrii pe care îi acceptă funcția dvs. Schema este calculată automat prin analiză statică a codului sursă, dar o puteți seta explicit:
description bună. Agenții AI se bazează pe câmpul description al funcției pentru a decide când să folosească instrumentul. Fiți specifici cu privire la ceea ce face instrumentul și când ar trebui apelat.definePreInstallLogicFunction
Definește o funcție logică de pre-instalare (una per aplicație)
definePreInstallLogicFunction
Definește o funcție logică de pre-instalare (una per aplicație)
- Funcțiile de pre-instalare folosesc
definePreInstallLogicFunction()— o variantă specializată care omite setările de declanșare (cronTriggerSettings,databaseEventTriggerSettings,httpRouteTriggerSettings,isTool). - Handlerul primește un
InstallLogicFunctionPayloadcu{ previousVersion: string }— versiunea aplicației care a fost instalată anterior (sau un șir gol pentru instalări noi). - Este permisă o singură funcție de pre-instalare per aplicație. Construirea manifestului va genera o eroare dacă este detectată mai mult de una.
- Proprietatea
universalIdentifiera funcției este setată automat capreInstallLogicFunctionUniversalIdentifierîn manifestul aplicației în timpul build-ului — nu este nevoie să o referi îndefineApplication(). - Timpul de expirare implicit este setat la 300 de secunde (5 minute) pentru a permite sarcini de pregătire mai lungi.
definePostInstallLogicFunction
Definește o funcție logică post-instalare (una per aplicație)
definePostInstallLogicFunction
Definește o funcție logică post-instalare (una per aplicație)
- Funcțiile de post-instalare folosesc
definePostInstallLogicFunction()— o variantă specializată care omite setările de declanșare (cronTriggerSettings,databaseEventTriggerSettings,httpRouteTriggerSettings,isTool). - Handlerul primește un
InstallLogicFunctionPayloadcu{ previousVersion: string }— versiunea aplicației care a fost instalată anterior (sau un șir gol pentru instalări noi). - Este permisă o singură funcție de post-instalare per aplicație. Construirea manifestului va genera o eroare dacă este detectată mai mult de una.
- Proprietatea
universalIdentifiera funcției este setată automat capostInstallLogicFunctionUniversalIdentifierîn manifestul aplicației în timpul build-ului — nu este nevoie să o referi îndefineApplication(). - Timpul de expirare implicit este setat la 300 de secunde (5 minute) pentru a permite sarcini de configurare mai lungi, cum ar fi popularea datelor.
defineFrontComponent
Definiți componente Front pentru interfața de utilizator personalizată
defineFrontComponent
Definiți componente Front pentru interfața de utilizator personalizată
Unde pot fi utilizate componentele frontale
Componentele frontale pot fi afișate în două locații în cadrul Twenty:- Panou lateral — Componentele frontale care nu sunt headless se deschid în panoul lateral din dreapta. Acesta este comportamentul implicit atunci când o componentă frontală este declanșată din meniul de comenzi.
- Widgeturi (tablouri de bord și pagini de înregistrare) — Componentele frontale pot fi încorporate ca widgeturi în machetele de pagină. La configurarea unui tablou de bord sau a machetei unei pagini de înregistrare, utilizatorii pot adăuga un widget de componentă frontală.
Exemplu de bază
Cel mai rapid mod de a vedea o componentă front-end în acțiune este să o înregistrați ca o comandă. Adăugarea unui câmpcommand cu isPinned: true o face să apară ca un buton de acțiune rapidă în colțul din dreapta sus al paginii — nu este nevoie de layout de pagină:yarn twenty dev (sau prin rularea o singură dată a comenzii yarn twenty dev --once), acțiunea rapidă apare în colțul din dreapta sus al paginii:
Câmpuri de configurare
| Câmp | Obligatoriu | Descriere |
|---|---|---|
universalIdentifier | Da | ID unic stabil pentru această componentă |
component | Da | O funcție de componentă React |
name | Nu | Nume afișat |
description | Nu | Descriere a ceea ce face componenta |
isHeadless | Nu | Setați la true dacă componenta nu are UI vizibilă (vezi mai jos) |
command | Nu | Înregistrați componenta ca o comandă (consultați opțiunile comenzii mai jos) |
Plasarea unei componente front-end pe o pagină
Dincolo de comenzi, puteți încorpora o componentă front-end direct într-o pagină de înregistrare adăugând-o ca widget într-un layout de pagină. Consultați secțiunea definePageLayout pentru detalii.Headless vs non-headless
Componentele frontale au două moduri de randare controlate de opțiuneaisHeadless:Non-headless (implicit) — Componenta afișează o interfață vizibilă. Când este declanșat din meniul de comenzi, se deschide în panoul lateral. Acesta este comportamentul implicit când isHeadless este false sau omis.Headless (isHeadless: true) — Componenta se montează invizibil în fundal. Nu deschide panoul lateral. Componentele headless sunt concepute pentru acțiuni care execută logică și apoi se demontează — de exemplu, rularea unei sarcini asincrone, navigarea la o pagină sau afișarea unui modal de confirmare. Se potrivesc în mod natural cu componentele Command din SDK descrise mai jos.null, Twenty omite redarea unui container pentru ea — nu apare spațiu gol în layout. Componenta are în continuare acces la toate hook-urile și la API-ul de comunicare cu gazda.Componentele Command din SDK
Pachetultwenty-sdk oferă patru componente ajutătoare Command, concepute pentru componente front-end headless. Fiecare componentă execută o acțiune la montare, gestionează erorile afișând o notificare snackbar și demontează automat componenta de interfață la final.Importă-le din twenty-sdk/command:Command— Rulează un callback asincron prin prop-ulexecute.CommandLink— Navighează către o rută a aplicației. Props:to,params,queryParams,options.CommandModal— Deschide un modal de confirmare. Dacă utilizatorul confirmă, execută callback-ulexecute. Props:title,subtitle,execute,confirmButtonText,confirmButtonAccent.CommandOpenSidePanelPage— Deschide o anumită pagină din panoul lateral. Props:page,pageTitle,pageIcon.
Command pentru a rula o acțiune din meniul de comenzi:CommandModal pentru a cere confirmarea înainte de execuție:Accesarea contextului de rulare
În interiorul componentei, folosiți hook-urile SDK pentru a accesa utilizatorul curent, înregistrarea curentă și instanța componentei:| Hook | Returnează | Descriere |
|---|---|---|
useUserId() | string sau null | ID-ul utilizatorului curent |
useRecordId() | string sau null | ID-ul înregistrării curente (când este plasată pe o pagină de înregistrare) |
useFrontComponentId() | string | ID-ul acestei instanțe de componentă |
useFrontComponentExecutionContext(selector) | variază | Accesați întregul context de execuție cu o funcție selector |
API-ul de comunicare cu gazda
Componentele front-end pot declanșa navigare, ferestre modale și notificări folosind funcții dintwenty-sdk:| Funcție | Descriere |
|---|---|
navigate(to, params?, queryParams?, options?) | Navigați la o pagină din aplicație |
openSidePanelPage(params) | Deschideți un panou lateral |
closeSidePanel() | Închideți panoul lateral |
openCommandConfirmationModal(params) | Afișați un dialog de confirmare |
enqueueSnackbar(params) | Afișați o notificare tip toast |
unmountFrontComponent() | Demontați componenta |
updateProgress(progress) | Actualizați un indicator de progres |
Opțiuni pentru comandă
Adăugarea unui câmpcommand la defineFrontComponent înregistrează componenta în meniul de comenzi (Cmd+K). Dacă isPinned este true, apare și ca buton de acțiune rapidă în colțul din dreapta sus al paginii.| Câmp | Obligatoriu | Descriere |
|---|---|---|
universalIdentifier | Da | ID unic stabil pentru comandă |
label | Da | Etichetă completă afișată în meniul de comenzi (Cmd+K) |
shortLabel | Nu | Etichetă mai scurtă afișată pe butonul de acțiune rapidă fixat |
icon | Nu | Numele pictogramei afișat lângă etichetă (de ex. 'IconBolt', 'IconSend') |
isPinned | Nu | Când este true, afișează comanda ca buton de acțiune rapidă în colțul din dreapta sus al paginii |
availabilityType | Nu | Controlează unde apare comanda: 'GLOBAL' (mereu disponibilă), 'RECORD_SELECTION' (doar când sunt selectate înregistrări) sau 'FALLBACK' (afișată când nicio altă comandă nu se potrivește) |
availabilityObjectUniversalIdentifier | Nu | Restricționați comanda la paginile unui anumit tip de obiect (de ex., doar pe înregistrările Company) |
conditionalAvailabilityExpression | Nu | O expresie booleană pentru a controla dinamic dacă comanda este vizibilă (vezi mai jos) |
Expresii de disponibilitate condițională
CâmpulconditionalAvailabilityExpression vă permite să controlați când este vizibilă o comandă în funcție de contextul paginii curente. Importați variabile tipizate și operatori din twenty-sdk pentru a construi expresii:| Variabilă | Tip | Descriere |
|---|---|---|
pageType | string | Tipul paginii curente (de ex. 'RecordIndexPage', 'RecordShowPage') |
isInSidePanel | boolean | Dacă componenta este redată într-un panou lateral |
numberOfSelectedRecords | number | Numărul de înregistrări selectate în prezent |
isSelectAll | boolean | Dacă “select all” este activ |
selectedRecords | array | Obiectele înregistrărilor selectate |
favoriteRecordIds | array | ID-urile înregistrărilor marcate ca favorite |
objectPermissions | object | Permisiuni pentru tipul de obiect curent |
targetObjectReadPermissions | object | Permisiuni de citire pentru obiectul țintă |
targetObjectWritePermissions | object | Permisiuni de scriere pentru obiectul țintă |
featureFlags | object | Steaguri de caracteristici active |
objectMetadataItem | object | Metadatele tipului de obiect curent |
hasAnySoftDeleteFilterOnView | boolean | Dacă vizualizarea curentă are un filtru soft-delete |
| Operator | Descriere |
|---|---|
isDefined(value) | true dacă valoarea nu este null/undefined |
isNonEmptyString(value) | true dacă valoarea este un șir nevid |
includes(array, value) | true dacă array-ul conține valoarea |
includesEvery(array, prop, value) | true dacă proprietatea fiecărui element include valoarea |
every(array, prop) | true dacă proprietatea este truthy pentru fiecare element |
everyDefined(array, prop) | true dacă proprietatea este definită pentru fiecare element |
everyEquals(array, prop, value) | true dacă proprietatea este egală cu valoarea pentru fiecare element |
some(array, prop) | true dacă proprietatea este truthy pe cel puțin un element |
someDefined(array, prop) | true dacă proprietatea este definită pe cel puțin un element |
someEquals(array, prop, value) | true dacă proprietatea este egală cu valoarea pe cel puțin un element |
someNonEmptyString(array, prop) | true dacă proprietatea este un șir nevid pe cel puțin un element |
none(array, prop) | true dacă proprietatea este falsy pentru fiecare element |
noneDefined(array, prop) | true dacă proprietatea este nedefinită pentru fiecare element |
noneEquals(array, prop, value) | true dacă proprietatea nu este egală cu valoarea pe niciun element |
Resurse publice
Componentele front-end pot accesa fișiere din directorulpublic/ al aplicației folosind getPublicAssetUrl:Stilizare
Componentele front-end acceptă mai multe abordări de stilizare. Puteți folosi:- Stiluri inline —
style={{ color: 'red' }} - Componente Twenty UI — import din
twenty-sdk/ui(Button, Tag, Status, Chip, Avatar și altele) - Emotion — CSS-in-JS cu
@emotion/react - Styled-components — pattern-uri
styled.div - Tailwind CSS — clase utilitare
- Orice bibliotecă CSS-in-JS compatibilă cu React
defineSkill
Definiți abilități pentru agentul AI
defineSkill
Definiți abilități pentru agentul AI
defineSkill() pentru a defini abilități cu validare încorporată:nameeste un șir identificator unic pentru abilitate (se recomandă kebab-case).labeleste numele lizibil afișat în interfața cu utilizatorul (UI).contentconține instrucțiunile abilității — acesta este textul pe care agentul AI îl folosește.icon(opțional) setează pictograma afișată în UI.description(opțional) oferă context suplimentar despre scopul abilității.
defineAgent
Definiți agenți AI cu prompturi personalizate
defineAgent
Definiți agenți AI cu prompturi personalizate
defineAgent() pentru a crea agenți cu un prompt de sistem personalizat:nameeste un șir identificator unic pentru agent (se recomandă kebab-case).labeleste numele de afișare din interfața cu utilizatorul (UI).promptconține promptul de sistem — acesta este textul de instrucțiuni care definește comportamentul agentului.description(opțional) oferă context suplimentar despre scopul agentului.icon(opțional) setează pictograma afișată în UI.modelId(opțional) suprascrie modelul AI implicit utilizat de agent.
defineView
Definește vizualizări salvate pentru obiecte
defineView
Definește vizualizări salvate pentru obiecte
defineView() pentru a livra vizualizări preconfigurate împreună cu aplicația:objectUniversalIdentifierspecifică la ce obiect se aplică această vizualizare.keydetermină tipul vizualizării (de ex.,ViewKey.INDEXpentru vizualizarea principală de listă).fieldscontrolează ce coloane apar și ordinea acestora. Fiecare câmp face referire la unfieldMetadataUniversalIdentifier.- Puteți defini, de asemenea,
filters,filterGroups,groupsșifieldGroupspentru configurații mai avansate. positioncontrolează ordonarea atunci când există mai multe vizualizări pentru același obiect.
defineNavigationMenuItem
Definește linkuri de navigare în bara laterală
defineNavigationMenuItem
Definește linkuri de navigare în bara laterală
definePageLayout
Definiți machete de pagină personalizate pentru vizualizările de înregistrare
definePageLayout
Definiți machete de pagină personalizate pentru vizualizările de înregistrare
definePageLayout() pentru a livra machete personalizate împreună cu aplicația:typeeste de obicei'RECORD_PAGE'pentru a personaliza vizualizarea de detaliu a unui obiect specific.objectUniversalIdentifierspecifică la ce obiect se aplică această machetă.- Fiecare
tabdefinește o secțiune a paginii cu untitle,positionșilayoutMode(CANVASpentru layout liber). - Fiecare
widgetdintr-o filă poate reda o componentă frontend, o listă de relații sau alte tipuri de widgeturi integrate. positionpe file le controlează ordinea. Folosiți valori mai mari (de ex., 50) pentru a plasa filele personalizate după cele integrate.
Resurse publice (folderul public/)
Folderul public/ din rădăcina aplicației conține fișiere statice — imagini, pictograme, fonturi sau orice alte resurse de care are nevoie aplicația la rulare. Aceste fișiere sunt incluse automat în build-uri, sincronizate în timpul modului de dezvoltare și încărcate pe server.
Fișierele plasate în public/ sunt:
- Accesibile public — odată sincronizate pe server, resursele sunt servite la un URL public. Nu este necesară autentificarea pentru a le accesa.
- Disponibile în componentele frontend — folosiți URL-urile resurselor pentru a afișa imagini, pictograme sau orice media în componentele React.
- Disponibile în funcțiile logice — referiți URL-urile resurselor în e-mailuri, răspunsuri API sau orice logică pe server.
- Utilizate pentru metadatele marketplace-ului — câmpurile
logoUrlșiscreenshotsdindefineApplication()fac referire la fișiere din acest folder (de ex.,public/logo.png). Acestea sunt afișate în marketplace când aplicația este publicată. - Sincronizate automat în modul de dezvoltare — când adăugați, actualizați sau ștergeți un fișier în
public/, acesta este sincronizat automat cu serverul. Nu este nevoie de repornire. - Incluse în build-uri —
yarn twenty buildîmpachetează toate resursele publice în outputul de distribuție.
Accesarea resurselor publice cu getPublicAssetUrl
Utilizați helperul getPublicAssetUrl din twenty-sdk pentru a obține URL-ul complet al unui fișier din directorul public/. Funcționează atât în funcții logice, cât și în componente frontend.
Într-o funcție logică:
path este relativ la folderul public/ al aplicației. Atât getPublicAssetUrl('logo.png'), cât și getPublicAssetUrl('public/logo.png') se rezolvă la același URL — prefixul public/ este eliminat automat dacă este prezent.
Utilizarea pachetelor npm
Puteți instala și utiliza orice pachet npm în aplicația dvs. Atât funcțiile logice, cât și componentele frontend sunt împachetate cu esbuild, care integrează toate dependențele în output — nu sunt necesarenode_modules la rulare.
Instalarea unui pachet
Cum funcționează împachetarea
Pasul de build folosește esbuild pentru a produce un singur fișier autonom pentru fiecare funcție logică și pentru fiecare componentă frontend. Toate pachetele importate sunt integrate în bundle. Funcțiile logice rulează într-un mediu Node.js. Modulele built-in Node (fs, path, crypto, http etc.) sunt disponibile și nu trebuie instalate.
Componentele frontend rulează într-un Web Worker. Modulele built-in Node nu sunt disponibile — doar API-urile de browser și pachetele npm care funcționează într-un mediu de browser.
Ambele medii au twenty-client-sdk/core și twenty-client-sdk/metadata disponibile ca module pre-furnizate — acestea nu sunt incluse în bundle, ci sunt rezolvate la rulare de către server.
Generarea scheletului entităților cu yarn twenty add
În loc să creați manual fișiere de entități, puteți folosi generatorul interactiv (scaffolder):
universalIdentifier stabil și apelul corect defineEntity().
Puteți de asemenea să transmiteți direct tipul de entitate pentru a sări peste primul prompt:
Tipuri de entități disponibile
| Tipul entității | Comandă | Fișier generat |
|---|---|---|
| Obiect | yarn twenty add object | src/objects/<name>.ts |
| Câmp | yarn twenty add field | src/fields/<name>.ts |
| Funcție logică | yarn twenty add logicFunction | src/logic-functions/<name>.ts |
| Componentă frontend | yarn twenty add frontComponent | src/front-components/<name>.tsx |
| Rol | yarn twenty add role | src/roles/<name>.ts |
| Abilitate | yarn twenty add skill | src/skills/<name>.ts |
| Agent | yarn twenty add agent | src/agents/<name>.ts |
| Vizualizare | yarn twenty add view | src/views/<name>.ts |
| Element de meniu de navigare | yarn twenty add navigationMenuItem | src/navigation-menu-items/<name>.ts |
| Machetă de pagină | yarn twenty add pageLayout | src/page-layouts/<name>.ts |
Ce generează scaffolder-ul
Fiecare tip de entitate are propriul său șablon. De exemplu,yarn twenty add object solicită:
- Nume (singular) — de ex.,
invoice - Nume (plural) — de ex.,
invoices - Etichetă (singular) — completată automat din nume (de ex.,
Invoice) - Etichetă (plural) — completată automat (de ex.,
Invoices) - Creați o vizualizare și un element de navigare? — dacă răspundeți afirmativ, scaffolder-ul generează, de asemenea, o vizualizare corespunzătoare și un link în bara laterală pentru noul obiect.
field este mai detaliat: solicită numele câmpului, eticheta, tipul (dintr-o listă cu toate tipurile de câmp disponibile precum TEXT, NUMBER, SELECT, RELATION etc.) și universalIdentifier al obiectului țintă.
Cale de output personalizată
Utilizați opțiunea--path pentru a plasa fișierul generat într-o locație personalizată:
Clienți API tipizați (twenty-client-sdk)
Pachetultwenty-client-sdk oferă doi clienți GraphQL tipați pentru a interacționa cu API-ul Twenty din funcțiile de logică și componentele Front.
| Client | Importați | Endpoint | Generat? |
|---|---|---|---|
CoreApiClient | twenty-client-sdk/core | /graphql — date ale spațiului de lucru (înregistrări, obiecte) | Da, în timpul dev/build |
MetadataApiClient | twenty-client-sdk/metadata | /metadata — configurarea spațiului de lucru, încărcări de fișiere | Nu, este livrat preconstruit |
CoreApiClient
Interogați și modificați datele spațiului de lucru (înregistrări, obiecte)
CoreApiClient
Interogați și modificați datele spațiului de lucru (înregistrări, obiecte)
CoreApiClient este clientul principal pentru interogarea și modificarea datelor din spațiul de lucru. Este generat din schema spațiului de lucru în timpul yarn twenty dev sau yarn twenty build, astfel încât este complet tipizat pentru a corespunde obiectelor și câmpurilor dvs.true pentru a include un câmp, folosiți __args pentru argumente și imbricați obiecte pentru relații. Obțineți autocompletare și verificare a tipurilor complete, pe baza schemei spațiului dvs. de lucru.yarn twenty dev sau yarn twenty build, va arunca o eroare. Generarea are loc automat — CLI inspectează schema GraphQL a spațiului dvs. de lucru și generează un client tipizat folosind @genql/cli.Folosirea CoreSchema pentru adnotări de tip
CoreSchema oferă tipuri TypeScript care corespund obiectelor din spațiul dvs. de lucru — utile pentru tiparea stării componentelor sau a parametrilor funcțiilor:MetadataApiClient
Configurația spațiului de lucru, aplicații și încărcări de fișiere
MetadataApiClient
Configurația spațiului de lucru, aplicații și încărcări de fișiere
MetadataApiClient este livrat preconstruit împreună cu SDK-ul (nu este necesară generarea). Interoghează endpointul /metadata pentru configurarea spațiului de lucru, aplicații și încărcări de fișiere.Încărcarea fișierelor
MetadataApiClient include o metodă uploadFile pentru atașarea fișierelor la câmpuri de tip fișier:| Parametru | Tip | Descriere |
|---|---|---|
fileBuffer | Buffer | Conținutul brut al fișierului |
filename | string | Numele fișierului (folosit pentru stocare și afișare) |
contentType | string | Tipul MIME (implicit application/octet-stream dacă este omis) |
fieldMetadataUniversalIdentifier | string | universalIdentifier al câmpului de tip fișier de pe obiectul tău |
- Folosește
universalIdentifieral câmpului (nu ID-ul specific spațiului de lucru), astfel încât codul dvs. de încărcare funcționează în orice spațiu de lucru în care aplicația dvs. este instalată. urlreturnat este un URL semnat pe care îl poți folosi pentru a accesa fișierul încărcat.
TWENTY_API_URL— URL-ul de bază al API-ului TwentyTWENTY_APP_ACCESS_TOKEN— Cheie cu durată scurtă, limitată la rolul implicit de funcție al aplicației
process.env. Permisiunile cheii API sunt determinate de rolul referențiat în defaultRoleUniversalIdentifier din application-config.ts.Testarea aplicației
SDK-ul oferă API-uri programatice care vă permit să construiți, să distribuiți, să instalați și să dezinstalați aplicația din codul de test. Combinat cu Vitest și clienții API tipizați, puteți scrie teste de integrare care verifică faptul că aplicația funcționează cap-coadă împotriva unui server Twenty real.Configurare
Aplicația generată (scaffolded) include deja Vitest. Dacă o configurați manual, instalați dependențele:vitest.config.ts în rădăcina aplicației:
API-uri SDK programatice
Subrutatwenty-sdk/cli exportă funcții pe care le puteți apela direct din codul de test:
| Funcție | Descriere |
|---|---|
appBuild | Construiți aplicația și, opțional, împachetați un tarball |
appDeploy | Încărcați un tarball pe server |
appInstall | Instalați aplicația în spațiul de lucru activ |
appUninstall | Dezinstalați aplicația din spațiul de lucru activ |
success: boolean și fie data, fie error.
Scrierea unui test de integrare
Iată un exemplu complet care construiește, distribuie și instalează aplicația, apoi verifică faptul că aceasta apare în spațiul de lucru:Rularea testelor
Asigurați-vă că serverul Twenty local rulează, apoi:Verificarea tipurilor
Puteți rula și verificarea tipurilor pe aplicație fără a rula testele:tsc --noEmit și raportează orice erori de tip.
Referință CLI
Dincolo dedev, build, add și typecheck, CLI oferă comenzi pentru executarea funcțiilor, vizualizarea jurnalelor și gestionarea instalărilor de aplicații.
Executarea funcțiilor (yarn twenty exec)
Rulați manual o funcție logică fără a o declanșa prin HTTP, cron sau eveniment de bază de date:
Vizualizarea jurnalelor funcțiilor (yarn twenty logs)
Transmiteți în flux jurnalele de execuție pentru funcțiile logice ale aplicației:
yarn twenty server logs, care afișează jurnalele containerului Docker. yarn twenty logs afișează jurnalele de execuție ale funcțiilor aplicației de pe serverul Twenty.Dezinstalarea unei aplicații (yarn twenty uninstall)
Eliminați aplicația din spațiul de lucru activ:
Gestionarea remote-urilor
Un „remote” este un server Twenty la care se conectează aplicația. În timpul configurării, generatorul de schelet creează automat unul pentru dvs. Puteți adăuga mai multe remote-uri sau comuta între ele oricând.~/.twenty/config.json.
CI cu GitHub Actions
Scaffolderul generează un workflow GitHub Actions gata de utilizare în.github/workflows/ci.yml. Rulează automat testele de integrare la fiecare push pe main și la pull request-uri.
Workflow-ul:
- Preia codul
- Pornește un server Twenty temporar folosind acțiunea
twentyhq/twenty/.github/actions/spawn-twenty-docker-image - Instalează dependențele cu
yarn install --immutable - Rulează
yarn testcuTWENTY_API_URLșiTWENTY_API_KEYinjectate din rezultatele acțiunii
spawn-twenty-docker-image pornește un server Twenty efemer direct în runner și oferă detaliile de conectare. Secretul GITHUB_TOKEN este furnizat automat de GitHub.
Pentru a fixa o versiune Twenty specifică în loc de latest, modificați variabila de mediu TWENTY_VERSION din partea de sus a workflow-ului.