c0cb0676a3
Created by Github action <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22723?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: Hooks d'installation
|
|
description: Exécutez de la logique avant ou après l'installation — initialisez des données, sauvegardez des enregistrements, validez la mise à niveau.
|
|
icon: wrench
|
|
---
|
|
|
|
Les hooks d'installation sont des fonctions logiques spéciales qui s'exécutent pendant le cycle de vie d'installation ou de mise à niveau. Ils partagent le même environnement d'exécution que les [fonctions logiques](/l/fr/developers/extend/apps/logic/logic-functions) classiques et reçoivent un `InstallPayload` (`{ previousVersion?: string; newVersion: string }` — `previousVersion` est `undefined` lors d'une nouvelle installation), mais ils sont déclarés avec leurs propres fonctions de définition et ne relèvent pas du modèle de déclencheur habituel (HTTP, cron, événements de base de données).
|
|
|
|
Chaque application peut définir **au maximum une pré-installation** et **au maximum une post-installation**. La génération du manifeste renvoie une erreur si plus d'une fonction de l'un ou l'autre type est détectée.
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ install flow │
|
|
│ │
|
|
│ upload package → [pre-install] → metadata migration → │
|
|
│ generate SDK → [post-install] │
|
|
│ │
|
|
│ old schema visible new schema visible │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## En un coup d'œil
|
|
|
|
| | `definePreInstallLogicFunction` | `definePostInstallLogicFunction` |
|
|
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
| Exécutions | Avant la migration des métadonnées — le schéma et les données **précédents** sont toujours intacts | Après la migration et la génération du SDK — le **nouveau** schéma est en place |
|
|
| Exécution | Toujours synchrone ; bloque l'installation | Asynchrone par défaut (mis en file d'attente, 3 nouvelles tentatives) ; mode synchrone en option via `shouldRunSynchronously: true` |
|
|
| En cas d'échec | L'installation est **abandonnée** avant toute modification du schéma | Asynchrone : jusqu'à 3 réessais. Synchrone : l'appelant reçoit `POST_INSTALL_ERROR` (les modifications de schéma **ne** sont pas annulées) |
|
|
| Utilisation typique | Sauvegarder ou corriger les données qu'une migration ferait perdre ; refuser une mise à niveau risquée en levant une exception | Initialiser des données par défaut, configurer l'espace de travail, enregistrer des ressources externes |
|
|
|
|
**Règle empirique :** privilégiez post-install par défaut. Ne recourez à la pré-installation que lorsque la migration elle-même est destructive et que vous devez intercepter l'état précédent avant qu'il ne disparaisse.
|
|
|
|
| Vous souhaitez... | Utiliser |
|
|
| -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
| Initialiser des données, configurer l'espace de travail, enregistrer des ressources externes | `post-install` |
|
|
| Travail de longue durée qui ne doit pas bloquer la réponse d'installation | `post-install` (mode asynchrone par défaut, avec nouvelles tentatives du worker) |
|
|
| Configuration rapide dont l'appelant dépend immédiatement après le retour de l'installation | `post-install` avec `shouldRunSynchronously: true` |
|
|
| Lire ou sauvegarder des données que la migration à venir ferait perdre | `pre-install` |
|
|
| Rejeter une mise à niveau qui corromprait des données existantes | `pre-install` (lancer une exception depuis le gestionnaire) |
|
|
| Réconciliation à chaque mise à niveau | N'importe quel hook avec `shouldRunOnVersionUpgrade: true` |
|
|
|
|
## Comportement partagé par les deux hooks
|
|
|
|
* La configuration est une configuration `defineLogicFunction` moins les paramètres de déclencheur, plus `shouldRunOnVersionUpgrade`.
|
|
* **Quand il s'exécute** : uniquement lors des nouvelles installations, par défaut. Définissez `shouldRunOnVersionUpgrade: true` pour qu'il s'exécute également lors des mises à niveau. Utilisez `previousVersion` / `newVersion` pour bifurquer selon le chemin de mise à niveau.
|
|
* **L'idempotence est importante** : le post-install asynchrone peut être relancé, et chaque hook est réexécuté lors des mises à niveau lorsque `shouldRunOnVersionUpgrade` est activé.
|
|
* L'environnement habituel des fonctions logiques (`APPLICATION_ID`, `APP_ACCESS_TOKEN`, `API_URL`) est injecté, ce qui vous permet d'appeler l'API Twenty avec le jeton de votre application.
|
|
* Le hook est rattaché automatiquement au manifeste de l'application au moment de la compilation (`preInstallLogicFunction` / `postInstallLogicFunction`) — rien à référencer dans [`defineApplication()`](/l/fr/developers/extend/apps/config/application).
|
|
* La valeur par défaut de `timeoutSeconds` est 300 pour permettre des tâches de configuration plus longues comme l'initialisation des données.
|
|
* **Non exécuté en mode dev** : `yarn twenty dev` ignore le flux d'installation et synchronise directement les fichiers, donc les hooks ne s'exécutent jamais dans ce cas. Déclenchez-les manuellement à la place :
|
|
|
|
```bash filename="Terminal"
|
|
yarn twenty dev:function:exec --postInstall
|
|
yarn twenty dev:function:exec --preInstall
|
|
```
|
|
|
|
<AccordionGroup>
|
|
<Accordion title="definePostInstallLogicFunction" description="S'exécute après l'application de la migration des métadonnées de l'espace de travail">
|
|
|
|
S'exécute une fois que votre application a terminé son installation : métadonnées synchronisées, client SDK généré, nouveau schéma interrogeable. Exemple — initialiser un enregistrement par défaut lors des nouvelles installations :
|
|
|
|
```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,
|
|
});
|
|
```
|
|
|
|
Le drapeau `shouldRunSynchronously` contrôle le modèle d'exécution :
|
|
|
|
* `false` *(par défaut)* — mis en file d'attente dans la file de messages (`retryLimit: 3`) et exécuté par un worker. La réponse d'installation est renvoyée dès que la tâche est mise en file d'attente. **À utiliser pour les travaux de longue durée** — initialisation de grands ensembles de données, API tierces lentes.
|
|
* `true` — exécuté en ligne pendant le flux d'installation. La requête d'installation est bloquée jusqu'à ce que le gestionnaire ait terminé ; une erreur levée apparaît comme `POST_INSTALL_ERROR` pour l'appelant (aucune nouvelle tentative). **À utiliser pour les travaux rapides qui doivent être terminés avant la réponse.** La migration a déjà été appliquée à ce stade, donc un échec n'annule pas les modifications du schéma — il ne fait que remonter l'erreur.
|
|
|
|
</Accordion>
|
|
<Accordion title="definePreInstallLogicFunction" description="S'exécute avant l'application de la migration des métadonnées de l'espace de travail">
|
|
|
|
S'exécute avant la migration des métadonnées, sur le schéma **précédent** — l'endroit idéal pour sauvegarder des données qu'une migration ferait perdre, ou pour refuser une mise à niveau risquée. Avant l'exécution, le serveur effectue une « synchronisation réduite » purement additive qui enregistre uniquement la fonction de pré-installation de la nouvelle version ; tout le reste — les objets, champs et données de la version précédente — reste intact lorsque votre gestionnaire s'exécute.
|
|
|
|
La pré-installation est toujours **synchrone** et bloque l'installation. Si le gestionnaire lève une exception, l'installation est abandonnée avant toute modification du schéma — l'espace de travail reste sur la version précédente dans un état cohérent. C'est intentionnel : la pré-installation est votre dernière chance de refuser une mise à niveau risquée.
|
|
|
|
Exemple — copier les valeurs d'un champ hérité avant que la migration ne le supprime :
|
|
|
|
```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>
|