Script

Script est un endpoint backend déclaratif qu'un frontend appelle via HTTP. Au lieu d'écrire du code serveur, on déclare « quoi faire » sous forme de JSON, et le moteur WEEGLOO se charge de l'exécuter. L'objectif est de remplacer, avec un seul Script, la tuyauterie backend typique qui soutient un frontend (un BFF, Backend-for-Frontend) : l'authentification, les vérifications de condition (guards), le CRUD enchaîné, les appels à des API externes et la transformation de valeurs.

Cet ensemble de documents constitue la référence de la syntaxe de Script. Les détails de chaque partie de la syntaxe sont répartis entre les pages listées dans Documents de ce groupe, plus bas.

La création et la gestion d'un Script (création, consultation, modification, suppression) se font sur CMA (https://cma.weegloo.com/v1). L'exécution, elle, relève du chemin d'exécution de l'hôte Script dédié (https://script.weegloo.com/v1). Ce chemin d'exécution unique accepte à la fois un jeton Weegloo User et le jeton d'un membre inscrit au produit (un ServiceUser). ACMA n'a pas d'API Script, et les API de livraison en lecture seule (CDA, ACDA) non plus.

Modèle mental

  • Un Script est un endpoint HTTP. La méthode d'appel (method) détermine quel Script s'exécute.
  • Le corps est un tableau statements. Ils s'exécutent séquentiellement, de haut en bas. C'est exactement comme le corps d'une fonction en programmation classique.
  • C'est une déclaration, pas du code. On n'insère pas de code arbitraire (FaaS) ; on combine des types de statement prédéfinis. Il est conçu moins pour être rédigé à la main par une personne que pour être généré par un agent d'IA via MCP.
  • Les valeurs circulent à travers des modèles JSON Pointer. On référence le résultat de l'étape précédente, le payload d'entrée ou une variable avec { /pointer }, puis on le transmet à l'étape suivante. Lorsqu'une condition ou un calcul est nécessaire, on utilise les opérateurs JsonLogic. Les règles complètes sont traitées dans Expressions de valeur.

Structure de niveau supérieur (ScriptDefinition)

Un Script se définit avec la structure ScriptDefinition suivante.

{
  "method": "Post",               // Get | Post | Put | Patch | Delete. La méthode HTTP mise en correspondance lors de l'appel (obligatoire)
  "payloadSchema": { /* ... */ }, // (facultatif) JSON Schema. Si présent, valide le payload de la requête avant l'exécution
  "statements": [ /* Statement[]. Exécutés de haut en bas (obligatoire, au moins 1) */ ]
}
ChampObligatoireDescription
methodObligatoireLa méthode HTTP utilisée pour appeler ce Script. Les appels sont mis en correspondance selon cette valeur.
payloadSchemaFacultatifUn JSON Schema. S'il est spécifié, le corps de la requête (payload) est validé avec ce schéma avant l'exécution ; si la validation échoue, la requête est rejetée sans être exécutée.
statementsObligatoireUn tableau ordonné de statements à exécuter. Au moins un.

Le payload n'accepte que des objets JSON. Le corps de l'appel est accessible via la racine de contexte /payload ({ /payload/... }) et, si l'on a besoin de la chaîne d'origine avant parsing, via /rawPayload (le cas d'un calcul sur les octets envoyés, comme une vérification de signature). Les en-têtes HTTP de la requête de l'appel se référencent via la racine /headers ({ /headers/... }, avec des clés en minuscules). L'instant où l'exécution a démarré se trouve dans la racine /now. L'ensemble complet des racines de contexte est traité dans Expressions de valeur.

Requête et réponse

Au final, un Script renvoie à l'appelant la valeur de son statement Return. La forme de la réponse est la suivante.

{
  "requestId": "…",     // Identifiant d'exécution
  "durationMs": 1234,   // Durée d'exécution (ms)
  "statusCode": 200,    // Le statusCode du Return atteint (200 par défaut)
  "return": <value>     // Uniquement lorsque Return.isError vaut false. Si la valeur est null, ""
  // "error": <value>   // Lorsque Return.isError vaut true, ou lorsque l'exécution a échoué (dans ce cas "return" est absent). Si la valeur est null, ""
}
  • requestId est l'identifiant de cette exécution. La même valeur se retrouve dans le sys.requestId du ScriptLog que cette exécution a laissé, ce qui en fait la clé pour retrouver cette exécution dans les logs.
  • return et error n'apparaissent jamais ensemble. Le isError du statement Return détermine lequel des deux apparaît.
  • Si le Script se termine sans atteindre de statement Return, return et error sont tous deux absents et statusCode prend la valeur par défaut (200).
  • Si l'exécution échoue, error est renseigné même sans Return. Lorsque l'échec a une cause du côté de l'appel, comme un payload invalide, et qu'aucun Try ne l'attrape, error contient le motif de l'échec et statusCode prend le code correspondant à cet échec (un payload invalide donne un 4xx ; un appel externe ou un envoi de courriel en échec donne 502). C'est cette forme que prend la réponse d'erreur la plus fréquemment rencontrée en pratique. Une exécution qui dépasse le budget de temps répond non pas avec l'enveloppe, mais avec un 408.
  • Si une valeur est null, ce champ est émis sous forme de chaîne vide "".

Le corps de la réponse et le code de statut se contrôlent avec les value, isError et statusCode du statement Return. Pour les détails, voir Return dans le Catalogue des statements.

Le temps alloué à une exécution

Un Script s'exécute en ligne, sur le chemin qui traite la requête d'appel. Il n'existe pas de flux qui confie l'exécution à l'arrière-plan ou qui renvoie d'abord une réponse d'acceptation, et le corps de la réponse de l'appel est le résultat de l'exécution. Il n'existe pas non plus de chemin de sondage pour récupérer le résultat plus tard.

Le temps alloué à une exécution est fixé par une seule formule : min(30 secondes + la somme des temps déclarés par les statements, 180 secondes).

  • Le budget de base est de 30 secondes. S'y ajoutent les temps que chaque statement déclare.
  • Un statement sans déclaration compte 0 seconde. Le temps qu'il consomme réellement sort du budget de base de 30 secondes.
  • Si la somme dépasse 180 secondes, l'enregistrement n'est pas refusé, mais le budget est tronqué à 180 secondes.

Voici l'essentiel des règles de déclaration, statement par statement.

StatementTemps déclaré
Http(30 secondes en l'absence de timeoutMs) × (1 + retry)
EmailSendtimeoutMs, ou 10 secondes à défaut
Loopla somme des statements du body × (maxIterations, ou 10 000 à défaut)
ResourceForEachla somme des statements d'onEach × (limit, ou 10 000 à défaut)
Ifla plus grande des valeurs entre la branche then et la branche else
Parallella plus grande des valeurs parmi les branches
  • Une itération est une multiplication. Loop et ResourceForEach multiplient le temps déclaré par le body (onEach) par le plafond d'itérations.
  • Une itération sans appel externe a un temps déclaré de 0 pour son body, si bien que le budget de base de 30 secondes constitue la limite effective.

Les règles détaillées par statement et les limites de plan sont traitées dans Sémantique d'exécution, contraintes et sécurité.

Exemple minimal

Cet exemple crée un Content d'article à partir du titre et du corps du payload de la requête, le publie aussitôt, puis renvoie le sys.id créé.

{
  "method": "Post",
  "statements": [
    { "type": "ResourceCreate", "resource": "Content",
      "contentType": { "sys": { "id": "ct_post" } },
      "fields": {
        "title": { "en-US": "{ /payload/fields/title }" },
        "body":  { "en-US": "{ /payload/fields/body }" }
      },
      "publish": true,
      "name": "post" },
 
    { "type": "Return", "value": { "id": "{ /post/sys/id }" }, "statusCode": 201 }
  ]
}
  • ResourceCreate crée le Content et lie le résultat au nom post.
  • Return renvoie { "id": <nouveau Content id> } avec 201.
  • La raison pour laquelle les valeurs de fields d'un Content sont des mappages de locale ({ "en-US": ... }) est traitée dans Mappages de locale dans les Expressions de valeur.

On trouvera des scénarios plus variés dans le Cookbook.

Documents de ce groupe

  • Expressions de valeur : traite les références { /pointer }, les littéraux, les opérations et conditions JsonLogic, les racines de contexte et les mappages de locale. C'est le cœur de la syntaxe.
  • Catalogue des statements : traite les champs et les résultats des 25 types de statement (CRUD et lectures de ressources, Http, EmailSend, SetVar, Cache, ParseJson, Signature, Hash, Regex, If, Loop, Parallel, Try, Return).
  • Sémantique d'exécution, contraintes et sécurité : traite l'ordre d'exécution, les guards, la compensation, le verrouillage optimiste, les erreurs, les contraintes statiques et les limites de plan, ainsi que le modèle de sécurité.
  • Cookbook : traite des exemples complets tels que l'upsert, un guard de crédits, un proxy LLM, la pagination, l'exécution en parallèle, une saga de paiement et la vérification de signature d'un webhook.
  • Ressource Script et endpoints : traite la structure sys de la ressource Script, la rédaction, la spécification des endpoints HTTP d'exécution (/execute) et le journal d'exécution ScriptLog.

Si c'est votre première fois, nous recommandons de lire, à partir de cette page, dans l'ordre Expressions de valeur puis Catalogue des statements. Le Cookbook mérite aussi d'être parcouru en entier.