Catalogue des statements
Dernière mise à jour : 23 juillet 2026
Chaque élément du tableau statements est un statement. Ce document catalogue les champs, le comportement et le résultat des 17 types de statement. Chaque emplacement de valeur suit les règles des Expressions de valeur (référence, littéral, JsonLogic, mappage de locale).
Résumé des statements
| Catégorie | type | Résumé en une ligne |
|---|---|---|
| Écritures de ressource | ResourceCreate | Créer un Content/Media (publication facultative) |
ResourceUpdate | Remplacement intégral des champs de Content/Media (tout champ/locale non fourni est supprimé) | |
ResourcePatch | Fusion partielle des champs de Content/Media (uniquement les champs/locales spécifiés ; un null littéral supprime) | |
ResourceDelete | Supprimer (Draft/Archived uniquement ; si Published, dépublier d'abord) | |
ResourcePublish / ResourceUnpublish | Publier / dépublier | |
ResourceArchive / ResourceUnarchive | Archiver / désarchiver | |
| Lectures de ressource | ResourceRead | Lecture d'un seul élément par id |
ResourceFind | Premier élément correspondant via filtre (null si aucun) | |
ResourcePageRead | Lecture avec filtre/tri/pagination ({ items, next }) | |
| Externe | Http | Appel HTTP externe ({ status, body }). Async uniquement |
| Variables | SetVar | Déclarer/mettre à jour une variable à portée script |
| Flux de contrôle | If | Branchement conditionnel |
Loop | Itération (foreach / while / counted) | |
Parallel | Exécution simultanée de branches | |
Return | Renvoyer un résultat et terminer prématurément | |
Try | Gestion des exceptions (catch/finally) |
Les appels cycliques sont limités à 3. Les instructions d'écriture de ressources ci-dessus (
ResourceCreate,ResourceUpdate,ResourcePublish, etc.) déclenchent des événements de modification, et ces événements peuvent exécuter à nouveau un Script via un Webhook. Une telle chaîne (Script → événement → Webhook → Script → …) se poursuit au maximum 3 fois. Au-delà, la plateforme l'interrompt automatiquement pour éviter les boucles infinies.
Champs communs
{ "type": "<StatementType>", "name": "<facultatif, unique dans le script>", /* ...champs spécifiques au type... */ }type: le discriminant. L'une des valeurs du tableau ci-dessus (obligatoire).name: facultatif. Lorsqu'il est défini, le résultat est lié au contexte à/<name>, de sorte que les statements suivants peuvent le référencer via{ /<name>/... }. On l'omet si l'on n'utilise pas le résultat.- Règles de nom de liaison :
name(ainsi que leasd'unLoop) est une clé posée telle quelle à la racine du contexte ; elle est donc validée à l'enregistrement. Elle ne doit pas être une chaîne vide, ne doit pas contenir/ni~(afin de pouvoir servir de clé JSON Pointer), ne peut pas coïncider avec une racine réservée (payload,vars,error), et doit être unique au sein d'un même Script. En cas de violation, l'enregistrement est refusé avec respectivementWGL400033(format),WGL400032(mot réservé) etWGL400034(doublon).
Forme des références d'entité
Les références d'entité comme contentType et target sont unifiées en une seule forme : { "sys": { "id": <expression de valeur> } }. Seul sys.id est nécessaire ; le type cible est déduit de resource (sys.type et sys.targetType sont omis).
contentType.sys.idest généralement un littéral (par ex."ct_post").target.sys.idest généralement une expression de valeur{ /ptr }(résolue à l'exécution ; par ex.{ /payload/sys/id }).
resource
Les statements de la famille ressource indiquent le type de cible avec resource: "Content" | "Media".
Écritures de ressource
Chaque statement d'écriture possède propagateEvents (par défaut false). Le mettre à true fait que cette écriture émet son propre EntityEvent (déclenchant des traitements en aval comme l'indexation de recherche ou les Webhook). Par défaut, il n'émet rien (une écriture système silencieuse).
ResourceCreate
Crée un Content ou un Media. Content et Media partagent le modèle fields, et les valeurs sont des mappages de locale.
| Champ | S'applique à | Description |
|---|---|---|
resource | Commun | "Content" ou "Media" (obligatoire) |
contentType | Content | Le Content Type à créer ({ sys: { id } }). Obligatoire pour Content |
fields | Commun | Le mappage de champs { "<field>": { "<locale>": valeur } }. Chaque champ renseigné requiert le bucket de la locale par défaut. Les clés de Content suivent la définition du Content Type ; les clés de Media sont fixes (title, description, file) |
locale | Commun | (Commodité) Si fourni, enveloppe automatiquement chaque valeur de fields en { <locale>: valeur } |
publish | Commun | Publie après l'écriture (exposé sur CDA/ACDA). Par défaut true |
Mediafile: la valeurfields.file.{locale}est une instruction d'ingestion{ "source": <expression de valeur>, "encoding": "url"|"base64" }(les deux sont obligatoires). Une écriture de Media qui inclut un fichier est Async uniquement (le moteur le traite en ligne en arrière-plan, puis le publie ; cela vaut pour url et base64). On peut aussi créer un Media sans fichier (fileless). Sipublish:truemais qu'il n'y a pas de fichier ou que le traitement est incomplet, l'étape de publication échoue ; sipublish:false, il resteDraft.- Résultat (liaison de
name) : la ressource créée.{ /<name>/sys/id },{ /<name>/fields/<field>/<locale> }.
// Content
{ "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_post" } },
"fields": { "title": { "en-US": "{ /payload/fields/title }" } }, "publish": true, "name": "post" }
// Media. file est une instruction d'ingestion (Async uniquement)
{ "type": "ResourceCreate", "resource": "Media",
"fields": {
"title": { "en-US": "{ /payload/fields/prompt }" },
"file": { "en-US": { "source": "{ /gen/body/data/0/url }", "encoding": "url" } }
}, "name": "img" }ResourceUpdate
Remplace intégralement les champs du Content ou Media cible (PUT). Ce que l'on passe dans fields devient le nouvel ensemble de champs, et tout champ et locale absent ici est supprimé. Pour n'en changer qu'une partie, on utilise ResourcePatch.
| Champ | Description |
|---|---|
resource | "Content" ou "Media" |
target | La cible ({ sys: { id } }, obligatoire). L'id est généralement { /ptr } |
fields | L'ensemble complet des champs à écrire. Les valeurs sont des mappages de locale. Comme il s'agit d'un remplacement intégral, tout champ et locale absent ici est supprimé. Pour un Media, file est une instruction d'ingestion (voir ResourceCreate ci-dessus) ; les fichiers listés sont toujours réingérés, et les fichiers des locales non fournies sont supprimés |
locale | (Commodité) Enveloppe automatiquement fields |
version | (Facultatif) Une expression de valeur (Int). Verrouillage optimiste. Si fournie, la mise à jour ne s'effectue que si elle correspond au sys.version actuel de la cible ; en cas de non-correspondance, elle abandonne avec une erreur de conflit de version (interceptable avec Try). Si omise, aucune vérification (last-write-wins) |
publish | Republie après la mise à jour. Par défaut true |
Si l'on utilise Update pour ne modifier que les métadonnées d'un Media, le file étant absent, tous les fichiers sont supprimés (puisqu'il s'agit d'un remplacement intégral). Pour une modification partielle, on utilise impérativement ResourcePatch. Un Update qui inclut un fichier est Async uniquement.
{ "type": "ResourceUpdate", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } },
"fields": { "title": { "en-US": "Hello", "ko-KR": "안녕" }, "status": { "en-US": "published" } } }ResourcePatch
Fusionne partiellement les champs du Content ou Media cible (PATCH). Écrase uniquement les champs (et les locales qu'ils contiennent) passés dans fields, et laisse intacts les champs et locales non mentionnés. La forme des valeurs, locale, version et publish sont identiques à ResourceUpdate.
| Champ | Description |
|---|---|
resource | "Content" ou "Media" |
target | La cible ({ sys: { id } }, obligatoire). L'id est généralement { /ptr } |
fields | Les champs à écraser. Les valeurs sont des mappages de locale. Met à jour uniquement les champs et buckets de locale spécifiés (le reste est conservé). Si une valeur est un null littéral, ce couple (champ, locale) est supprimé. Pour un Media, file est une instruction d'ingestion (voir ResourceCreate ci-dessus) |
locale | (Commodité) Enveloppe automatiquement fields |
version | (Facultatif) Identique à ResourceUpdate (verrouillage optimiste) |
publish | Republie après la mise à jour. Par défaut true |
- Supprimer une locale ou un fichier spécifique : on donne un
nulllittéral comme valeur. Par ex. :"title": { "fr-FR": null }(supprime le titre fr-FR),"file": { "en-US": null }(supprime le fichier en-US). Une expression de valeur qui s'évalue à null au moment de l'exécution n'est pas une suppression mais une erreur (seul un null littéral supprime). - Donner une instruction d'ingestion au
filed'un Media remplace le fichier de cette locale (Async uniquement). Si l'on ne fournit pas de fichier, il est conservé.
// +1 sur viewCount(en-US) uniquement. title, les autres locales, etc. sont conservés tels quels
{ "type": "ResourcePatch", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } },
"fields": { "viewCount": { "en-US": { "+": [ "{ /payload/fields/viewCount }", 1 ] } } } }ResourceDelete
Supprime la cible. Seuls les statuts Draft et Archived peuvent être supprimés. Si l'élément est Published ou Changed, la suppression est refusée : il faut donc d'abord ResourceUnpublish (pour un Media, elle est aussi refusée pendant que le fichier est en cours de traitement (busy)). Il ne dépublie pas automatiquement (comme CMA/ACMA).
| Champ | Description |
|---|---|
resource | "Content" ou "Media" |
target | La cible ({ sys: { id } }, obligatoire) |
{ "type": "ResourceDelete", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } } }ResourcePublish, ResourceUnpublish, ResourceArchive, ResourceUnarchive
Contrôle indépendamment l'état de publication et d'archivage de la cible. Les quatre partagent les mêmes champs. La précondition de statut de chaque opération est identique à CMA/ACMA (publish impossible depuis Archived et nécessite que le traitement du fichier soit terminé ; unpublish uniquement depuis Published/Changed ; archive uniquement depuis Draft ; unarchive uniquement depuis Archived).
| Champ | Description |
|---|---|
resource | "Content" ou "Media" |
target | La cible ({ sys: { id } }, obligatoire) |
version | (Facultatif) Une expression de valeur (Int). Verrouillage optimiste. Si fournie, l'opération ne s'effectue que si elle correspond au sys.version actuel |
{ "type": "ResourcePublish", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } } }
{ "type": "ResourceUnpublish", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } } }
{ "type": "ResourceArchive", "resource": "Media", "target": { "sys": { "id": "{ /m/sys/id }" } } }Lectures de ressource
Les statements de lecture ne modifient pas l'état (pas de propagateEvents).
Les trois statements de lecture déterminent tous, via from (facultatif, Current par défaut), quelle copie stockée lire. Current est le dernier brouillon que voit le studio de contenu (la valeur que lisent CMA/ACMA), et Published est l'instantané publié (celui que distribuent CDA/ACDA, la valeur au moment de la dernière publication).
ResourceFind et ResourcePageRead peuvent en outre activer la Recherche avancée (Advanced Search) via advanced (facultatif, par défaut false). Réservée au Content, elle est ignorée pour les lectures de Media. Lorsqu'elle est activée, where peut utiliser les opérateurs regex, near et within ainsi que la recherche en texte intégral (sur un champ LongText dont la recherche en texte intégral est activée, eq trouve aussi les éléments qui contiennent la valeur, par correspondance partielle et approchée), et order peut trier par fields.*. Lorsqu'elle est désactivée, ces trois opérateurs sont rejetés, eq sur du texte est une correspondance exacte, et prefix ainsi que les opérateurs de comparaison et de liste fonctionnent indépendamment de la recherche avancée. Un élément qui vient d'être créé ou modifié met un court instant (environ 1 seconde) à apparaître dans la recherche avancée, si bien que la requête de recherche avancée qui suit immédiatement peut ne pas le renvoyer. Pour lire sans attendre un élément qui vient d'être écrit, utilisez ResourceRead par id (le stockage principal, sans délai d'apparition) ou interrogez par le sys.id renvoyé par l'écriture.
Dans where et order, un champ de contenu s'écrit fields.<field> (le nom seul n'est pas reconnu). À fields.<field>, le moteur applique automatiquement la locale par défaut du Space, si bien qu'on n'y ajoute pas de locale directement. Les fields.status et fields.slug des exemples ci-dessous interrogent donc directement la locale par défaut. Ce n'est que pour viser une locale précise (non par défaut) qu'on la spécifie avec fields.<field>.<locale> (par ex. fields.title.ko-KR). sys.* (comme sys.createdAt) et createdBy (:self) s'écrivent tels quels, sans fields.. Les règles détaillées figurent dans La locale dans where et order des Expressions de valeur.
ResourceRead
Une lecture d'un seul élément par id (get-by-id). Le résultat lie la ressource entière au nom.
| Champ | Description |
|---|---|
resource | "Content" ou "Media" |
target | La cible ({ sys: { id } }). L'id est une expression de valeur |
from | (Facultatif) Current (par défaut, dernier brouillon) ou Published (instantané publié) |
- Résultat : référencer directement
{ /<name>/sys/id }et{ /<name>/fields/<field>/<locale> }(pas besoin deitems/0). - Si la cible n'existe pas, cela génère une erreur. On peut l'envelopper dans un
Trypour la gérer.
{ "type": "ResourceRead", "resource": "Content",
"target": { "sys": { "id": "{ /payload/fields/orderId }" } }, "name": "order" }ResourceFind
Lit le premier élément correspondant, via un filtre. S'il n'y en a aucun, c'est null. À utiliser pour trouver un enregistrement par une clé métier unique (slug, email, sku).
| Champ | Description |
|---|---|
resource | "Content" ou "Media" |
contentType | (Content) Le Content Type dans lequel chercher ({ sys: { id } }) |
where | Le filtre ({ "<field>": { "<op>": <valeur> } }). Les opérateurs sont ceux de la liste des opérateurs (regex/near/within nécessitent advanced). createdBy: ":self" pris en charge |
order | Le tri qui détermine le « premier » lorsque plusieurs correspondent (par ex. "-sys.createdAt") |
from | (Facultatif) Current (par défaut, dernier brouillon) ou Published (instantané publié) |
advanced | (Facultatif) Exécuter via la recherche avancée. Content uniquement (Media est ignoré). Par défaut false. Voir la note Lectures de ressource ci-dessus. |
- Résultat : lie la première ressource correspondante au nom. On la référence directement via
{ /<name>/fields/<field>/<locale> }. Comme elle vautnullen l'absence de résultat, on branche selon l'existence avec{ "==": [ "{ /<name> }", null ] }(le schéma classique du find-then-upsert).
{ "type": "ResourceFind", "resource": "Content", "contentType": { "sys": { "id": "ct_article" } },
"where": { "fields.slug": { "eq": "{ /payload/fields/slug }" } }, "name": "found" }ResourcePageRead
Une lecture avec filtre, tri et pagination.
| Champ | Description |
|---|---|
resource | "Content" ou "Media" |
contentType | (Content) Le Content Type dans lequel chercher |
where | Le filtre ({ "<field>": { "<op>": <valeur> } }). Les opérateurs sont ceux de la liste des opérateurs (regex/near/within nécessitent advanced). createdBy: ":self" pris en charge |
order | Le tri (par ex. "-sys.createdAt") |
limit | La taille de page (100 ou moins) |
cursor | Pour la page suivante, le next du résultat précédent |
from | (Facultatif) Current (par défaut, dernier brouillon) ou Published (instantané publié) |
advanced | (Facultatif) Exécuter via la recherche avancée. Content uniquement (Media est ignoré). Par défaut false. Voir la note Lectures de ressource ci-dessus. |
- Résultat :
{ items, next }.{ /<name>/items/0/... }, et la page suivante est{ /<name>/next }. - Pour parcourir l'ensemble, on utilise
Loop while "{ /vars/hasMore }"aveccursoret l'accumulation parSetVar(voir le Cookbook).
{ "type": "ResourcePageRead", "resource": "Content", "contentType": { "sys": { "id": "ct_post" } },
"where": { "fields.status": { "eq": "draft" } }, "order": "-sys.createdAt", "limit": 100, "name": "page" }Externe
Http
Appelle un endpoint HTTP externe. Lorsque Http est présent, executionMode doit valoir Async (ExternalIo).
| Champ | Description |
|---|---|
method | "GET", "POST", "PUT", "PATCH", "DELETE" |
url | L'URL cible (une expression de valeur ; { /ptr } peut y être inséré) |
headers | [{ "key", "value", "secret"? }]. value est une expression de valeur. Un en-tête secret:true est traité comme réservé à CMA (administrateur) : il n'est pas exposé aux utilisateurs finaux et n'est déchiffré que juste avant l'envoi de la requête |
body | Le corps de la requête (une expression de valeur ou du JSON) |
timeoutMs | Le délai d'expiration de cet appel (ms) |
retry | Le nombre de nouvelles tentatives lorsque le statut de la réponse est supérieur ou égal à 400. Par défaut 0 ; le plafond est maxHttpRetry (2 par défaut) |
ignoreStatusCode | Indique s'il faut traiter cet appel comme un échec lorsque le statut final (après les nouvelles tentatives) est supérieur ou égal à 400. Lorsque false (par défaut), il est traité comme un échec et devient une cible de Try/catch. Lorsque true, il n'est pas traité comme un échec et { status, body } est lié tel quel (l'appelant branche lui-même sur status) |
- Résultat :
{ status, body }.{ /<name>/status },{ /<name>/body/... }. - Limite de taille de réponse : le corps de la réponse est de 10MiB au maximum. S'il dépasse cette taille, cet appel échoue avec une exception et peut être géré comme n'importe quel autre échec d'exécution avec
Try/catch(il s'agit d'un échec basé sur la taille, il n'est donc pas ignoré parignoreStatusCode).
{ "type": "Http", "method": "POST", "url": "https://api.llm.com/v1/gen",
"headers": [ { "key": "Authorization", "value": "Bearer sk-...", "secret": true } ],
"body": { "prompt": "{ /payload/fields/prompt }" }, "timeoutMs": 15000, "retry": 1, "name": "resp" }Variables
SetVar
Déclare ou met à jour une variable mutable à portée du script. On la référence via { /vars/<var> } (JsonLogic n'a pas de déclaration de variable, c'est donc fourni sous forme de statement).
| Champ | Description |
|---|---|
var | Le nom de la variable. Référencée via { /vars/<var> } |
value | Une expression de valeur. Elle peut se référencer elle-même pour accumuler |
{ "type": "SetVar", "var": "total", "value": 0 }
{ "type": "SetVar", "var": "total", "value": { "+": [ "{ /vars/total }", "{ /row/qty }" ] } } // accumulation
{ "type": "SetVar", "var": "ids", "value": { "merge": [ "{ /vars/ids }", [ "{ /row/sys/id }" ] ] } } // collecte dans un tableauFlux de contrôle
If
Un branchement conditionnel. condition est du JsonLogic, et l'évaluation en vrai ou faux suit les règles de Valeurs vraies et fausses.
| Champ | Description |
|---|---|
condition | JsonLogic (évalué comme un booléen) |
then | Le tableau de statements à exécuter si vrai |
else | (Facultatif) Le tableau de statements à exécuter si faux |
{ "type": "If",
"condition": { "<": [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] },
"then": [ { "type": "Return", "value": { "ok": false, "reason": "crédit insuffisant" } } ],
"else": [ /* ... */ ] }Loop
Une itération. On choisit un seul mode : over (foreach), while (condition) ou for (compté). Quel que soit le mode, le moteur impose une limite supérieure avec maxIterations (pour éviter les boucles infinies). Les appels externes à l'intérieur du body (Http, ingestion de fichier Media) sont interdits.
| Champ | Description |
|---|---|
over | foreach : une expression de valeur qui se résout en un tableau |
while | condition : JsonLogic (répète tant que c'est vrai) |
for | compté : { "from", "to", "step"? }. De from à to inclus ; step vaut 1 par défaut |
maxIterations | Le nombre maximal d'itérations imposé par le moteur (obligatoire) |
as | Le nom auquel lier l'élément ou l'index courant ({ /<as> }) |
body | Le tableau de statements du corps de la boucle |
// foreach
{ "type": "Loop", "over": "{ /payload/fields/items }", "as": "item", "maxIterations": 100,
"body": [ { "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_item" } },
"fields": { "name": { "en-US": "{ /item/name }" } } } ] }
// while
{ "type": "Loop", "while": "{ /vars/hasMore }", "maxIterations": 1000, "body": [ /* ... */ ] }
// counted (1..10 step 2)
{ "type": "Loop", "for": { "from": 1, "to": 10, "step": 2 }, "as": "i", "maxIterations": 100, "body": [ /* ... */ ] }Parallel
Exécute les branches simultanément et poursuit après leur jonction. Les références entre branches ne sont pas autorisées (en cas de dépendance, on les place séquentiellement).
| Champ | Description |
|---|---|
branches | Statement[][]. Chaque élément est une branche (un tableau de statements) |
{ "type": "Parallel", "branches": [
[ { "type": "Http", "method": "GET", "url": "https://api.a.com/x", "name": "a" } ],
[ { "type": "Http", "method": "GET", "url": "https://api.b.com/y", "name": "b" } ]
] }Return
C'est le return de la programmation classique. Il renvoie le résultat du Script à l'appelant et se termine normalement à ce point.
| Champ | Description |
|---|---|
value | (Facultatif) L'expression de valeur à renvoyer |
isError | Par défaut false. Si true, value ressort comme le error de la réponse (sinon comme return) |
statusCode | Le code de statut de la réponse. Par défaut 200 |
- Si
Returnn'est jamais atteint, il n'y a pas de valeur de retour. Pour renvoyer un résultat, on précise explicitementvalue. - Comme il s'agit d'une terminaison normale, et non d'une exception ou d'un throw, ce n'est pas une cible de
catch(même à l'intérieur d'unTry, il termine l'intégralité du Script, maisfinallys'exécute tout de même). - Un guard s'exprime aussi avec ce statement :
Ifcombiné àthen:[Return](renvoyer lorsque la condition est violée, de sorte que la suite ne s'exécute pas). C'est l'un de ses nombreux usages.
{ "type": "Return", "value": { "orderId": "{ /order/sys/id }", "status": "paid" }, "statusCode": 201 }
{ "type": "Return", "value": { "reason": "échec du paiement" }, "isError": true, "statusCode": 402 }Try
Gestion des exceptions.
| Champ | Description |
|---|---|
body | Le tableau de statements à tenter |
catch | (Facultatif) S'exécute en cas d'échec de body. Expose { message, statement } sur /error |
finally | (Facultatif) S'exécute toujours, que ce soit en cas de succès ou d'échec |
- Si
catchla gère, le Script n'est pas interrompu. Seul un échec sanscatchinterrompt le Script (y compris la tentative de compensation). - Ce qui compte comme un « échec », ainsi que les limites de la compensation, sont traités dans Sémantique d'exécution, contraintes et sécurité.
{ "type": "Try",
"body": [ { "type": "Http", "method": "POST", "url": "https://primary.api/gen", "name": "resp" },
{ "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_result" } },
"fields": { "text": { "en-US": "{ /resp/body/text }" } } } ],
"catch": [ { "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_result" } },
"fields": { "text": { "en-US": "Échec de la génération" }, "error": { "en-US": "{ /error/message }" } } } ],
"finally": [ /* toujours exécuté */ ] }Documents associés
- Expressions de valeur : les règles de valeur que suivent tous les champs ci-dessus.
- Sémantique d'exécution, contraintes et sécurité : ordre d'exécution, erreurs, contraintes statiques et sécurité.
- Cookbook : des exemples complets qui combinent ces statements.
- Aperçu de Script : la structure de niveau supérieur et les modes d'exécution.
