Vai al contenuto principale

Panoramica

Ogni app deve avere esattamente una chiamata a defineApplication. Dichiara:
  • Identità — identificatore universale, nome visualizzato, descrizione.
  • Autorizzazioni — il ruolo sotto il quale vengono eseguite le sue funzioni logiche e i componenti front-end.
  • Funzionalità multimediali (facoltativo): accesso al microfono o alla fotocamera richiesto dai componenti front, approvato separatamente dalle autorizzazioni del ruolo.
  • Variabili (opzionali) — coppie chiave–valore esposte al tuo codice come variabili d’ambiente.
  • Hook di pre-installazione / post-installazione / disinstallazione (opzionali) — vedi Funzioni logiche.
  • Fatturazione (facoltativa) — billing.recurring per le tariffe di abbonamento che la piattaforma addebita automaticamente, billing.operations per ciò per cui l’app addebita crediti e billing.description per il marketplace; vedi Addebito di crediti.
src/application-config.ts
Note:
  • I campi universalIdentifier sono UUID che generi una sola volta e possiedi. Mantienili stabili tra le sincronizzazioni. Il universalIdentifier dell’applicazione deve essere un UUID valido: il server rifiuta un manifesto il cui identificatore non lo è. È univoco nell’intera istanza ed è associato allo spazio di lavoro proprietario della sua registrazione, quindi solo quello spazio di lavoro può sincronizzare l’app — consulta Proprietà della registrazione.
  • applicationVariables accetta un elemento facoltativo label — un nome intuitivo visualizzato nella pagina delle impostazioni dell’app invece della chiave della variabile non elaborata.
  • applicationVariables diventano variabili d’ambiente per le tue funzioni e i componenti front-end. Nelle funzioni di logica (lato server), sono disponibili come process.env.VARIABLE_NAME. Nei componenti front-end, usa getApplicationVariable('VARIABLE_NAME') da twenty-sdk/front-component. Le variabili contrassegnate con isSecret: true vengono iniettate solo nelle funzioni di logica. I componenti front-end ricevono solo variabili non segrete. Una variabile con scope: 'USER' contiene il valore del membro per cui viene eseguito il codice: consulta Variabili dell’area di lavoro e dell’utente.
  • La tua app può anche leggere e aggiornare i propri valori delle variabili in fase di esecuzione, ed è così che un componente di impostazioni personalizzato salva ciò che l’utente ha digitato: consulta Lettura e aggiornamento delle variabili in fase di esecuzione. Un’applicazione può accedere solo alle proprie variabili, nel proprio spazio di lavoro.
  • Il ruolo predefinito viene rilevato automaticamente dal file di ruolo contrassegnato con defineApplicationRole(): non è necessario farvi riferimento da defineApplication().
  • Le funzioni di pre-installazione, post-installazione e disinstallazione, nonché i controlli di integrità, vengono rilevate automaticamente durante il build del manifest — non è necessario farvi riferimento in defineApplication().
  • Il passaggio esplicito di defaultRoleUniversalIdentifier è ancora supportato per garantire la compatibilità con le versioni precedenti, ma è deprecato a favore di defineApplicationRole().
  • serverVariables sono configurazioni e segreti con ambito di istanza (ad esempio chiavi API). A differenza di applicationVariables, non dichiarano alcun valore nel manifest — l’operatore dello spazio di lavoro li compila dalle impostazioni dell’app e vengono iniettati nelle funzioni di logica solo una volta impostati.
  • Un’app può segnalare il proprio stato di configurazione con defineHealthCheck(), per ciò che solo l’app può sapere — una chiave presente ma revocata, un account di terze parti con il piano errato. isRequired copre ciò che Twenty può vedere autonomamente; il controllo di integrità copre il resto. Imposta runOnUserPreferences: true per controllare la configurazione di ogni membro nella pagina delle preferenze delle app anziché nelle impostazioni dell’app dello spazio di lavoro. Omettere l’opzione o impostarla su false mantiene il controllo esistente dello spazio di lavoro.
  • Entrambi i tipi di variabile accettano isRequired: true. Una variabile obbligatoria che lo spazio di lavoro non ha ancora compilato lascia l’app non configurata: la relativa pagina delle impostazioni mostra un banner che indica le variabili mancanti, con un pulsante che porta alla scheda in cui sono impostate. Contrassegna come obbligatorio solo ciò senza cui l’app non può effettivamente funzionare: una variabile facoltativa con un valore predefinito sensato dovrebbe rimanere facoltativa.
  • Entrambi i tipi di variabile accettano isDeprecated: true. Usala per ritirare una variabile invece di eliminarla: mantenere la chiave dichiarata preserva il valore memorizzato (eliminandola si distrugge il valore inserito dall’operatore) e la variabile è ancora iniettata, così il tuo codice può ripiegare su di essa — process.env.NEW_API_KEY ?? process.env.API_KEY. Una variabile deprecata scompare dalle impostazioni dell’app non appena non ha più un valore e non viene mai conteggiata nel controllo di configurazione dell’app, quindi isDeprecated prevale su isRequired.
  • Twenty imposta questi nomi per ogni esecuzione di funzioni logiche, pertanto sono riservati: TWENTY_API_URL, TWENTY_APP_ACCESS_TOKEN, TWENTY_APP_APPLICATION_ACCESS_TOKEN, TWENTY_API_KEY, TWENTY_FUNCTIONS_URL, TWENTY_SERVER_ROUTES_URL e APPLICATION_ID. Anche ogni altro nome che inizia con TWENTY_ è riservato, per le variabili che Twenty aggiunge in seguito. Un manifesto che dichiara un nome riservato come variabile dell’applicazione o del server viene rifiutato quando l’app viene sincronizzata o pubblicata.
  • Per aggiungere le tue voci al menu delle impostazioni dell’app (al posto della pagina Variables generata), dichiara un front component e configura un defineSettingsMenuItem() affinché punti a esso, in un proprio file. Dichiarane quanti te ne servono e ordinali con position; scope colloca un elemento nelle impostazioni del workspace o nelle impostazioni personali di ciascun membro. L’elemento Generale gestito dal sistema (aggiornamento automatico, URL dell’app, connessioni) è sempre il primo e l’URL dell’app viene visualizzato solo quando l’app dispone di funzioni attivate da HTTP.

Funzionalità multimediali richieste

Imposta requestedCapabilities quando un componente front usa navigator.mediaDevices.getUserMedia(). L’array facoltativo accetta 'microphone', 'camera' o entrambi. Omettilo o usa un array vuoto quando l’app non necessita di acquisizione multimediale.
Le funzionalità dichiarate vengono visualizzate durante l’installazione. L’approvazione richiede un membro dello spazio di lavoro che possa gestire le app e si applica all’intero spazio di lavoro. Queste autorizzazioni sono separate dalle autorizzazioni del ruolo dell’app e non sostituiscono le autorizzazioni del browser o del sistema operativo. Un’app installata senza l’autorizzazione richiesta mette in pausa l’acquisizione e visualizza una finestra di dialogo di approvazione al primo utilizzo, incluse le app meno recenti senza dichiarazioni di funzionalità. Il rifiuto mantiene l’acquisizione bloccata prima che vengano richieste le autorizzazioni del browser. Gli aggiornamenti del pacchetto non concedono automaticamente accessi aggiuntivi. Le app di sviluppo sincronizzate localmente ricevono le funzionalità dichiarate nel relativo manifesto. Consulta Acquisizione multimediale per il comportamento dell’acquisizione e gli indicatori di registrazione.

Accesso ai contenuti multimediali di siti web incorporati

Imposta requestedIframeMediaPermissions quando un componente front o un widget di layout della pagina IFRAME incorpora un sito web che necessita del microfono o della fotocamera, ad esempio uno strumento telefonico o video. Elenca fino a 20 siti web, ciascuno come origine HTTPS esatta, con l’accesso al microfono e alla fotocamera impostato separatamente. Le origini devono essere univoche, non contenere percorsi o caratteri jolly e richiedere l’accesso ad almeno uno tra microfono e fotocamera.
I siti web dichiarati vengono visualizzati durante l’installazione. L’approvazione richiede un membro dello spazio di lavoro in grado di gestire le app e si applica all’intero spazio di lavoro, per i componenti front e i widget iframe dell’app stessa. Le approvazioni di sicurezza dello spazio di lavoro si applicano solo ai widget creati nello spazio di lavoro. Le app di sviluppo sincronizzate localmente ricevono i siti web dichiarati nel relativo manifest. Queste autorizzazioni non sostituiscono le autorizzazioni del browser o del sistema operativo. Le intestazioni del browser hanno un limite di dimensione, quindi se i siti web di uno spazio di lavoro lo superano, i siti web approvati dallo spazio di lavoro hanno la precedenza e i siti web rimanenti non ricevono l’accesso ai contenuti multimediali. Gli aggiornamenti alle app pubblicate mantengono le autorizzazioni esistenti e non concedono automaticamente ulteriore accesso ai contenuti multimediali. Per approvare nuove richieste, un membro in grado di gestire le app apre la scheda Generali dell’app installata e seleziona Esamina l’accesso ai contenuti multimediali in Accesso ai contenuti multimediali di siti web incorporati. Questa approvazione utilizza una conferma nativa del browser che mostra l’app, le origini dei siti web e l’accesso richiesto al microfono o alla fotocamera. Dopo l’approvazione, ricarica le schede Twenty aperte per applicare le autorizzazioni aggiornate. Consulta Siti web incorporati con accesso ai contenuti multimediali per i requisiti dell’iframe.

Tipi di variabili

Sia applicationVariables che serverVariables accettano un type opzionale (e, per SELECT / MULTI_SELECT, un elenco di options). Tipi supportati: TEXT (predefinito), BOOLEAN, NUMBER, NUMERIC, DATE, DATE_TIME, SELECT, MULTI_SELECT, ARRAY, RAW_JSON, RICH_TEXT.
src/application-config.ts
Il type influisce solo su presentazione e convalida: seleziona l’input corrispondente nell’interfaccia delle impostazioni dell’area di lavoro (un interruttore, campo numerico, menu a discesa, selettore di data, editor JSON, …) e consente alla build di convalidare la tua configurazione (ad esempio, SELECT / MULTI_SELECT devono dichiarare options non vuote). Non cambia il modo in cui il valore arriva al tuo codice. I valori sono sempre inseriti come stringhe: ciò è intrinseco alle variabili di ambiente (process.env.* accetta solo stringhe). Quando la tua funzione di logica viene eseguita, l’executor serializza ogni valore in base al type dichiarato mentre costruisce process.env, quindi il formato della stringa è coerente indipendentemente da come è stato impostato il valore (valore predefinito del manifest, interfaccia delle impostazioni o una versione precedente): Analizza nuovamente la stringa nel tipo che ti aspetti:
Lo stesso vale per i componenti front-end che leggono i valori tramite getApplicationVariable('VARIABLE_NAME'): il valore restituito è una stringa; analizzalo secondo le necessità.

Variabili dello spazio di lavoro e dell’utente

Ogni variabile dell’applicazione ha un scope:
  • WORKSPACE (predefinito): un valore per l’intero spazio di lavoro, impostato da un membro che può gestire le app.
  • USER: ogni membro mantiene il proprio valore.
src/application-config.ts
Il value di una variabile utente è il relativo valore predefinito: un membro che non ha impostato il proprio lo legge e una nuova versione della tua app può modificarlo. Una variabile segreta non può avere un valore predefinito. Senza un valore predefinito, un membro che non ha impostato il proprio legge una stringa vuota, quindi la tua app decide cosa significa un valore non impostato. Un amministratore dello spazio di lavoro non può impostare un valore per una variabile utente: i suoi valori appartengono a ciascun membro. L’ambito di una variabile viene impostato al momento della creazione e non può cambiare. Per modificarla, dichiara la variabile con un nuovo universalIdentifier: la sincronizzazione elimina la vecchia variabile, con i valori dei relativi membri, e crea quella nuova. Le variabili utente possono essere isSecret, isRequired o entrambe. Ad esempio, una chiave API personale può dichiarare scope: 'USER', isSecret: true, isRequired: true. I valori sono crittografati a riposo. Per le variabili utente, isRequired descrive un requisito per membro. Un membro che non dispone di un valore per essa, né proprio né predefinito, vede la tua app contrassegnata come Configurazione mancante nelle preferenze App, con un banner che indica le variabili. Non influisce sull’avviso di configurazione dell’area di lavoro e nulla lo impone in fase di esecuzione: il tuo codice decide comunque cosa significa un valore non impostato. Una variabile utente viene inserita con il valore del membro per cui viene eseguito il codice oppure con il relativo valore predefinito, finché il membro non imposta il proprio:
  • In una funzione logica, process.env contiene i valori del membro che ha attivato l’esecuzione, lo stesso membro di cui agisce TWENTY_APP_ACCESS_TOKEN. Un’esecuzione senza alcun membro associato, come un processo cron o un hook di installazione, non riceve alcuna variabile utente.
  • In un componente front-end, getApplicationVariable restituisce i valori del membro che lo visualizza. Le variabili utente segrete vengono omesse, come le variabili segrete dell’area di lavoro.
Il membro che ha attivato un’esecuzione non è sempre il membro a cui si riferisce: un evento del database viene eseguito come chiunque abbia modificato il record. Quando un’esecuzione riguarda qualcun altro o ogni membro, leggi i valori con myUserApplicationVariables tramite MetadataApiClient. Elenca ogni membro con i valori delle variabili utente della tua app e funziona in ogni esecuzione di funzione logica, inclusi processi cron e webhook. Ogni voce contiene userWorkspaceId, workspaceMemberId e variables del membro: la dichiarazione di ogni variabile utente (label, description, type, options, isSecret, isRequired, isDeprecated) e il valore del membro, oppure il valore predefinito finché non imposta il proprio. Esegui la query come applicazione per ottenere i valori effettivi: con un token associato a una persona, restituisce solo la voce di quella persona, con i segreti mascherati.
I valori sono stringhe, nello stesso formato di process.env (consulta Tipi di variabili). updateMyUserApplicationVariable salva il valore personale di un membro. Prende l’applicationUniversalIdentifier della tua app e scrive il valore della persona dietro al token: la sessione del membro stesso oppure il token della tua app quando dietro c’è un membro, ad esempio in un componente front-end o in una funzione logica eseguita per un membro. Il token della tua app può identificare solo la tua app e un token senza nessuna persona associata, ad esempio in un processo cron o in un hook di installazione, viene rifiutato. Un valore vuoto rimuove il valore proprio del membro, quindi viene letto nuovamente il valore predefinito oppure una stringa vuota per una variabile senza valore predefinito. Non richiede l’autorizzazione Workspace Apps, ma richiede User Apps: nel ruolo del membro e, quando il token dell’app effettua la chiamata, anche nel ruolo predefinito dell’app, se ne dichiara uno. Se l’app salva variabili utente, aggiungi SystemPermissionFlag.USER_APPS a permissionFlagUniversalIdentifiers nel suo ruolo.

Ruolo funzione predefinito

Il ruolo dichiarato con defineApplicationRole() controlla a cosa possono accedere le funzioni di logica e i componenti di interfaccia dell’app:
  • I token di runtime iniettati nelle funzioni logiche sono derivati da questo ruolo. Una chiamata che agisce come una persona è ulteriormente limitata a ciò che tale persona può fare, quindi non può mai superare nessuno dei due. Vedi L’accesso utilizzato da una chiamata.
  • Il client API tipizzato è limitato alle autorizzazioni concesse a quel ruolo.
  • Segui il principio del privilegio minimo: dichiara solo le autorizzazioni necessarie alle tue funzioni.
Quando esegui lo scaffolding di una nuova app, la CLI crea un file di ruolo iniziale in src/roles/default-role.ts. Per la documentazione completa, vedi Ruoli e autorizzazioni.

Metadati del marketplace

Se prevedi di pubblicare la tua app, questi campi opzionali controllano come appare nel marketplace:
logoUrl e screenshots sono alias deprecati di logo e galleryImages. Gli URL assoluti esterni (http:// o https://) non sono supportati per questi campi: vengono eliminati con un avviso al momento della generazione. Raccogli invece le immagini nella cartella public/ della tua app.