Script

Script es un endpoint de backend declarativo que un frontend llama por HTTP. En lugar de escribir código de servidor, se declara «qué hacer» como JSON y el motor de WEEGLOO se encarga de ejecutarlo. El objetivo es reemplazar con un solo Script la típica capa intermedia de backend que sostiene un frontend (un BFF, Backend-for-Frontend): la autenticación, las comprobaciones de condiciones (guards), el CRUD encadenado, las llamadas a API externas y la transformación de valores.

Este conjunto de documentos es la referencia de la sintaxis de Script. Los detalles de cada parte de la sintaxis se reparten entre las páginas de Documentos de este grupo, más abajo.

Crear y gestionar un Script (crear, consultar, modificar y eliminar) se hace en CMA (https://cma.weegloo.com/v1). De la ejecución se encarga la ruta de ejecución del host dedicado de Script (https://script.weegloo.com/v1). Esa única ruta de ejecución acepta los dos tokens: el de un Weegloo User y el de un miembro registrado en el producto (un ServiceUser). ACMA no tiene API de Script, y tampoco la tienen las API de entrega de solo lectura (CDA, ACDA).

Modelo mental

  • Un Script es un endpoint HTTP. El método de llamada (method) determina qué Script se ejecuta.
  • El cuerpo es un array statements. Se ejecutan de forma secuencial, de arriba abajo. Es igual que el cuerpo de una función en la programación habitual.
  • Es declaración, no código. No se inserta código arbitrario (FaaS), sino que se combinan tipos de Statement predefinidos. Está diseñado menos para escribirse a mano por una persona y más para que lo genere un agente de IA a través de MCP.
  • Los valores fluyen a través de plantillas de JSON Pointer. Se referencia el resultado del paso anterior, el payload de entrada o una variable con { /pointer } y se pasa al paso siguiente. Cuando hace falta una condición o un cálculo, se usan los operadores de JsonLogic. Las reglas completas se tratan en Expresiones de valor.

Estructura de nivel superior (ScriptDefinition)

Un Script se define con la siguiente estructura ScriptDefinition.

{
  "method": "Post",               // Get | Post | Put | Patch | Delete. El método HTTP con el que se empareja al llamar (obligatorio)
  "payloadSchema": { /* ... */ }, // (opcional) JSON Schema. Si está presente, valida el payload de la petición antes de la ejecución
  "statements": [ /* Statement[]. Se ejecutan de arriba abajo (obligatorio, 1 o más) */ ],
  "secrets": [ /* (opcional) Lista de valores secretos. Se leen en un Statement con { /secrets/<key> } */ ]
}
CampoObligatorioDescripción
methodObligatorioEs el método HTTP con el que se llama a este Script. La llamada se empareja según este valor.
payloadSchemaOpcionalEs un JSON Schema. Si se especifica, el cuerpo de la petición (payload) se valida con este esquema antes de la ejecución y, si la validación falla, la petición se rechaza sin ejecutarse.
statementsObligatorioEs un array ordenado de Statement que se van a ejecutar. Al menos uno.
secretsOpcionalEs la lista de valores secretos que no deben escribirse tal cual en un Statement, como claves de API externas o claves de firma. Cada elemento lleva key, value, description, y en un Statement ese value se lee con { /secrets/<key> }. WEEGLOO cifra los valores y los almacena de forma segura. Las reglas se tratan en secrets en el modelo de seguridad.

El payload solo acepta objetos JSON. Al cuerpo de la llamada se accede a través de la raíz de contexto /payload ({ /payload/... }), y si se necesita la cadena original previa al parseo, se accede a través de /rawPayload (por ejemplo, cuando se calcula sobre los bytes enviados, como en la verificación de firma). Las cabeceras HTTP de la petición de la llamada se referencian a través de la raíz /headers ({ /headers/... }, con las claves en minúsculas). El instante en que arrancó la ejecución está en la raíz /now. Los valores secretos declarados en secrets se leen a través de la raíz /secrets ({ /secrets/<key> }). El conjunto completo de raíces de contexto se trata en Expresiones de valor.

Petición y respuesta

Al final, un Script devuelve a quien hace la llamada el valor de su Statement Return. La forma de la respuesta es la siguiente.

{
  "requestId": "…",     // Identificador de ejecución
  "durationMs": 1234,   // Tiempo de ejecución (ms)
  "statusCode": 200,    // El statusCode del Return alcanzado (por defecto 200)
  "return": <value>     // Solo cuando Return.isError es false. Si el valor es null, ""
  // "error": <value>   // Cuando Return.isError es true, o cuando la ejecución falla (en ese caso no está "return"). Si el valor es null, ""
}
  • requestId es el identificador de esta ejecución. Ese mismo valor va al sys.requestId del ScriptLog que deja esa ejecución, así que este valor es el que se usa para localizar esta ejecución en los registros.
  • return y error nunca aparecen juntos. El isError del Statement Return decide cuál de los dos es.
  • Si el Script termina sin alcanzar un Statement Return, return y error están ambos ausentes y statusCode es el valor por defecto (200).
  • Si la ejecución falla, error se rellena incluso sin un Return. Cuando el fallo viene del lado de quien llama, como un payload inválido, y ningún Try lo captura, error lleva el motivo del fallo y statusCode pasa a ser el código que corresponde a ese fallo (4xx para un payload inválido, 502 cuando falla una llamada externa o un envío de correo). En la práctica, esta es la respuesta de error que más a menudo se encuentra. Una ejecución que pasa de su presupuesto de tiempo responde con 408 en lugar de este sobre de respuesta.
  • Si un valor es null, ese campo se emite como una cadena vacía "".

Con value, isError y statusCode de Return se controlan el cuerpo de la respuesta y el código de estado. Los detalles se tratan en Return en el Catálogo de Statement.

Cuánto tiempo recibe una ejecución

Un Script se ejecuta en línea, en la ruta que atiende la petición de la llamada. No hay ningún flujo que pase el trabajo a segundo plano ni que devuelva primero un acuse de recibo: el cuerpo de la respuesta de la llamada es el resultado de la ejecución. Tampoco hay una ruta de sondeo para recoger el resultado más tarde.

El tiempo permitido para una ejecución es como máximo de 180 segundos. Se permiten 30 segundos de base más el tiempo que pueden usar las llamadas externas (Http, EmailSend), y en un Http que envía archivos se suma además el tiempo de descarga de cada archivo.

  • Las tareas que no son llamadas externas, como leer y escribir recursos, se procesan dentro de la base de 30 segundos.
  • La iteración (Loop, ResourceForEach) multiplica el tiempo de su interior por el número de iteraciones. Por eso, una iteración sin llamadas externas debe terminar dentro de la base de 30 segundos.
  • Aunque el valor calculado pase de 180 segundos, el guardado y la ejecución se permiten, y cuando la ejecución llega a 180 segundos se interrumpe en ese momento.

El tiempo que suma cada Statement y los ejemplos de cálculo se tratan en Presupuesto de tiempo.

Ejemplo mínimo

Crea un Content de publicación con el título y el cuerpo del payload de la petición, lo publica de inmediato y luego devuelve el sys.id creado.

{
  "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 crea el Content y vincula el resultado al nombre post.
  • Return devuelve { "id": <nuevo Content id> } con 201.
  • El motivo por el que los valores de fields de un Content son mapas de locale ({ "en-US": ... }) se trata en Mapas de locale en Expresiones de valor.

Hay más escenarios variados en el Cookbook.

Documentos de este grupo

  • Expresiones de valor: trata las referencias { /pointer }, los literales, las operaciones y condiciones de JsonLogic, las raíces de contexto y los mapas de locale. Es el núcleo de la sintaxis.
  • Catálogo de Statement: trata los campos y los resultados de los 25 tipos de Statement (CRUD y lecturas de recursos, Http, EmailSend, SetVar, Cache, ParseJson, Signature, Hash, Regex, If, Loop, Parallel, Try, Return).
  • Semántica de ejecución, restricciones y seguridad: trata el orden de ejecución, los guards, la compensación, el bloqueo optimista, los errores, las restricciones estáticas y los límites de plan, y el modelo de seguridad.
  • Cookbook: trata ejemplos completos como upsert, un guard de créditos, un proxy de LLM, la paginación, la ejecución en paralelo, una saga de pago y la verificación de la firma de un webhook.
  • Recurso Script y endpoints: trata la estructura sys del recurso Script y su autoría, la especificación de los endpoints HTTP de ejecución (/execute) y el registro de ejecución ScriptLog.

Si es la primera vez, recomendamos leer a partir de esta página en el orden Expresiones de valor y luego Catálogo de Statement. El Cookbook también se puede hojear entero.