ebee7d71b9
Created by Github action <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22715?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> Co-authored-by: github-actions <github-actions@twenty.com>
145 lines
11 KiB
Plaintext
145 lines
11 KiB
Plaintext
---
|
|
title: Hook di installazione
|
|
description: Esegui logica prima o dopo l'installazione — popola i dati, esegui il backup dei record, convalida l'aggiornamento.
|
|
icon: wrench
|
|
---
|
|
|
|
Gli hook di installazione sono funzioni logiche speciali che vengono eseguite durante il ciclo di vita di installazione o aggiornamento. Condividono lo stesso runtime del gestore delle [logic functions](/l/it/developers/extend/apps/logic/logic-functions) normali e ricevono un `InstallPayload` (`{ previousVersion?: string; newVersion: string }` — `previousVersion` è `undefined` in una nuova installazione), ma sono dichiarati con le proprie funzioni di definizione e vivono al di fuori del normale modello di trigger (HTTP, eventi cron, eventi del database).
|
|
|
|
Ogni app può definire **al massimo una funzione di pre-installazione** e **al massimo una funzione di post-installazione**. La build del manifesto genera un errore se ne viene rilevata più di una per ciascun tipo.
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ install flow │
|
|
│ │
|
|
│ upload package → [pre-install] → metadata migration → │
|
|
│ generate SDK → [post-install] │
|
|
│ │
|
|
│ old schema visible new schema visible │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## A colpo d'occhio
|
|
|
|
| | `definePreInstallLogicFunction` | `definePostInstallLogicFunction` |
|
|
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
| Esecuzioni | Prima della migrazione dei metadati — lo schema e i dati **precedenti** sono ancora intatti | Dopo la migrazione e la generazione dell'SDK — il **nuovo** schema è in vigore |
|
|
| Esecuzione | Sempre sincrona; blocca l'installazione | Async per impostazione predefinita (in coda, 3 tentativi); modalità sync tramite opt-in con `shouldRunSynchronously: true` |
|
|
| In caso di errore | L'installazione viene **annullata** prima di qualsiasi modifica allo schema | Async: ritentato fino a 3 volte. Sync: il chiamante riceve `POST_INSTALL_ERROR` (le modifiche allo schema **non** vengono annullate) |
|
|
| Uso tipico | Eseguire il backup o correggere dati che una migrazione perderebbe; rifiutare un aggiornamento rischioso lanciando un'eccezione | Popolare dati predefiniti, configurare il workspace, registrare risorse esterne |
|
|
|
|
**Regola generale:** usa post-install come impostazione predefinita. Ricorri al pre-install solo quando la migrazione stessa è distruttiva e devi intercettare lo stato precedente prima che vada perso.
|
|
|
|
| Vuoi... | Usa |
|
|
| ------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------- |
|
|
| Popolare i dati, configurare il workspace, registrare risorse esterne | `post-install` |
|
|
| Lavoro di lunga durata che non dovrebbe bloccare la risposta dell'installazione | `post-install` (modalità async predefinita, con retry del worker) |
|
|
| Eseguire un setup rapido da cui il chiamante dipende immediatamente dopo il completamento dell'installazione | `post-install` con `shouldRunSynchronously: true` |
|
|
| Leggere o eseguire il backup dei dati che la prossima migrazione perderebbe | `pre-install` |
|
|
| Rifiutare un aggiornamento che corromperebbe i dati esistenti | `pre-install` (genera un'eccezione dall'handler) |
|
|
| Riconciliazione a ogni aggiornamento | Uno qualsiasi dei due hook con `shouldRunOnVersionUpgrade: true` |
|
|
|
|
## Comportamento condiviso da entrambi gli hook
|
|
|
|
* La config è una config di `defineLogicFunction` meno le impostazioni di trigger, più `shouldRunOnVersionUpgrade`.
|
|
* **Quando viene eseguito**: solo sulle nuove installazioni, per impostazione predefinita. Imposta `shouldRunOnVersionUpgrade: true` per eseguirlo anche sugli upgrade. Usa `previousVersion` / `newVersion` per ramificare in base al percorso di upgrade.
|
|
* **L'idempotenza è importante**: il post-install async può essere ritentato e qualsiasi hook viene rieseguito sugli upgrade quando `shouldRunOnVersionUpgrade` è attivo.
|
|
* Il consueto ambiente delle logic-function (`APPLICATION_ID`, `APP_ACCESS_TOKEN`, `API_URL`) viene iniettato, così puoi chiamare le API di Twenty con il token della tua app.
|
|
* L'hook viene collegato automaticamente al manifesto dell'applicazione in fase di build (`preInstallLogicFunction` / `postInstallLogicFunction`) — non c'è nulla da referenziare in [`defineApplication()`](/l/it/developers/extend/apps/config/application).
|
|
* Il `timeoutSeconds` predefinito è 300 per consentire attività di setup più lunghe, come il seeding dei dati.
|
|
* **Non eseguito in modalità dev**: `yarn twenty dev` salta il flusso di installazione e sincronizza direttamente i file, quindi gli hook non vengono mai eseguiti in quell'ambiente. Attivali invece manualmente:
|
|
|
|
```bash filename="Terminal"
|
|
yarn twenty dev:function:exec --postInstall
|
|
yarn twenty dev:function:exec --preInstall
|
|
```
|
|
|
|
<AccordionGroup>
|
|
<Accordion title="definePostInstallLogicFunction" description="Viene eseguita dopo che la migrazione dei metadati dello spazio di lavoro è stata applicata">
|
|
|
|
Viene eseguito una volta che l'installazione della tua app è terminata: metadati sincronizzati, client SDK generato, nuovo schema interrogabile. Esempio — eseguire il seeding di un record predefinito nelle nuove installazioni:
|
|
|
|
```ts src/logic-functions/post-install.ts
|
|
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
|
|
import { CoreApiClient } from 'twenty-client-sdk/core';
|
|
|
|
const handler = async ({ previousVersion }: InstallPayload): Promise<void> => {
|
|
if (previousVersion) return; // fresh installs only
|
|
|
|
const client = new CoreApiClient();
|
|
await client.mutation({
|
|
createPostCard: {
|
|
__args: { data: { name: 'Welcome to Postcard', content: 'Your first card!' } },
|
|
id: true,
|
|
},
|
|
});
|
|
};
|
|
|
|
export default definePostInstallLogicFunction({
|
|
universalIdentifier: 'f7a2b9c1-3d4e-5678-abcd-ef9876543210',
|
|
name: 'post-install',
|
|
description: 'Seeds a welcome post card after install.',
|
|
timeoutSeconds: 300,
|
|
shouldRunOnVersionUpgrade: false,
|
|
shouldRunSynchronously: false,
|
|
handler,
|
|
});
|
|
```
|
|
|
|
Il flag `shouldRunSynchronously` controlla il modello di esecuzione:
|
|
|
|
* `false` *(predefinito)* — messo in coda nella message queue (`retryLimit: 3`) ed eseguito da un worker. La risposta dell'installazione ritorna non appena il job viene messo in coda. **Da usare per lavoro di lunga durata** — seeding di grandi dataset, API di terze parti lente.
|
|
* `true` — eseguito inline durante il flusso di installazione. La richiesta di installazione rimane bloccata finché l'handler non termina; un errore lanciato viene esposto al chiamante come `POST_INSTALL_ERROR` (nessun retry). **Da usare per lavoro rapido che deve completarsi prima della risposta.** La migrazione è già stata applicata a questo punto, quindi un errore non annulla le modifiche allo schema — si limita a esporre l'errore.
|
|
|
|
</Accordion>
|
|
<Accordion title="definePreInstallLogicFunction" description="Viene eseguita prima che la migrazione dei metadati dello spazio di lavoro sia applicata">
|
|
|
|
Viene eseguito prima della migrazione dei metadati, contro lo schema **precedente** — il posto giusto per eseguire il backup di dati che una migrazione perderebbe o per rifiutare un upgrade rischioso. Prima dell'esecuzione, il server esegue una "sincronizzazione ridotta" puramente additiva che registra solo la funzione di pre-install della versione nuova; tutto il resto — oggetti, campi e dati della versione precedente — rimane intatto quando il tuo handler viene eseguito.
|
|
|
|
Il pre-install è sempre **sincrono** e blocca l'installazione. Se l'handler genera un'eccezione, l'installazione viene interrotta prima che venga applicata qualsiasi modifica allo schema — il workspace rimane sulla versione precedente in uno stato coerente. Questo è intenzionale: il pre-install è la tua ultima possibilità per rifiutare un aggiornamento rischioso.
|
|
|
|
Esempio — copiare i valori di un campo legacy prima che la migrazione lo elimini:
|
|
|
|
```ts src/logic-functions/pre-install.ts
|
|
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
|
|
import { CoreApiClient } from 'twenty-client-sdk/core';
|
|
|
|
const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise<void> => {
|
|
// Only the 1.x → 2.x upgrade drops the legacy `notes` field.
|
|
if (!previousVersion?.startsWith('1.') || !newVersion.startsWith('2.')) {
|
|
return;
|
|
}
|
|
|
|
const client = new CoreApiClient();
|
|
const { postCards } = await client.query({
|
|
postCards: {
|
|
__args: { filter: { notes: { isNot: null } } },
|
|
edges: { node: { id: true, notes: true } },
|
|
},
|
|
});
|
|
|
|
// Copy legacy `notes` into `description` before the migration drops the
|
|
// column. If this fails, the upgrade aborts and the workspace stays on v1.
|
|
for (const { node } of postCards.edges) {
|
|
await client.mutation({
|
|
updatePostCard: {
|
|
__args: { id: node.id, data: { description: node.notes } },
|
|
id: true,
|
|
},
|
|
});
|
|
}
|
|
};
|
|
|
|
export default definePreInstallLogicFunction({
|
|
universalIdentifier: 'a1b2c3d4-5678-90ab-cdef-1234567890ab',
|
|
name: 'pre-install',
|
|
description: 'Backs up legacy notes into description before the v2 migration.',
|
|
timeoutSeconds: 300,
|
|
shouldRunOnVersionUpgrade: true,
|
|
handler,
|
|
});
|
|
```
|
|
|
|
</Accordion>
|
|
</AccordionGroup>
|