Funciones de transformación
La función «Mapping» extrae valores de una solicitud. Una función de transformación va más allá: se trata de su propio código JavaScript, que se ejecuta en cada solicitud antes de que se llame a Shopify Flow, de modo que puede reestructurar la payload, realizar una consulta, decidir si merece la pena ejecutar un flujo de trabajo para esa solicitud o responder usted mismo a quien realiza la llamada.
Se encuentra en la pestaña «Función» de un webhook. Si el editor está vacío, significa que está desactivado.
La forma de una función
export default async function transform(payload, ctx) {
// payload - the parsed request body (JSON, form or XML)
// return an object -> it becomes the payload for mapping and Flow
// return null -> nothing is sent to Flow, and nothing counts
return { ...payload, source: "warehouse" }
}Lo que le ofrece ctx
ctx.request |
method, contentType, la solicitud headers (datos confidenciales ocultos) y query |
ctx.webhook |
Los enlaces del webhook son id y name |
ctx.shop |
Su dominio de myshopify |
ctx.log(...) |
Escribe una línea que se puede leer en el panel de pruebas y en el historial |
await ctx.fetch(url, init) |
Llama a una API pública |
await ctx.shopify(query, variables) |
Lee los datos de las tiendas mediante Admin GraphQL |
ctx.storage |
Conserva los valores pequeños entre ejecuciones (véase más abajo) |
ctx.respond(body, options) |
Responde de inmediato a la persona que llama |
Reestructuración de un payload
El uso más habitual: convertir la estructura de un remitente en los pocos valores que necesita su flujo de trabajo.
export default async function transform(payload) {
const order = payload.data.attributes
return {
orderNumber: String(order.number),
email: order.customer.email.toLowerCase(),
total: Number(order.total_cents) / 100,
}
}Eliminar las solicitudes que no necesite
Si devuelve null, la solicitud se detiene ahí: no se ejecuta Shopify Flow, no se registra ninguna entrada en el historial y no se contabiliza nada en su plan. El solicitante recibe 200 con { "skipped": true }, por lo que no vuelve a intentarlo.
export default async function transform(payload, ctx) {
if (payload.status !== "paid" || payload.total < 100) {
ctx.log("skipping", payload.id, payload.status, payload.total)
return null
}
return payload
}Recordar cosas entre una carrera y otra
ctx.storage Es un pequeño almacén de pares clave-valor que pertenece a su tienda. Es la herramienta ideal para responder a la pregunta «¿He visto esto antes?»: almacene un identificador cuando se produzca un evento y omita la siguiente solicitud que contenga ese mismo identificador, incluso si llega días después.
| Llame | ¿Es así? |
|---|---|
await ctx.storage.get(key) |
El saldo, o null |
await ctx.storage.set(key, value) |
Almacena cualquier valor JSON, sobrescribiendo |
await ctx.storage.delete(key) |
Lo elimina; true si existía |
await ctx.storage.list({ prefix, limit, cursor }) |
Nombres y tamaños clave, página por página |
export default async function transform(payload, ctx) {
const key = `seen:${payload.id}`
if (await ctx.storage.get(key)) return null
await ctx.storage.set(key, { at: Date.now() })
return payload
}Enriquecimiento con datos de las tiendas
ctx.shopify Ejecuta consultas GraphQL de administración de solo lectura para su tienda, por lo que un flujo de trabajo puede comenzar con datos a los que el remitente nunca ha tenido acceso. Solo ve lo que usted le permita: conceda los ámbitos que necesite en «Acceso a los datos de la tienda», en la pestaña «Función». De forma predeterminada, no se concede ningún acceso y se rechazan las mutaciones.
export default async function transform(payload, ctx) {
const data = await ctx.shopify(
`query($q: String!) {
productVariants(first: 1, query: $q) { nodes { id title price } }
}`,
{ q: `sku:${payload.sku}` },
)
const variant = data.productVariants.nodes[0]
if (!variant) return null
return { sku: payload.sku, variantId: variant.id, price: variant.price }
}Atender usted mismo la llamada
ctx.respond() envía una respuesta de inmediato, lo que convierte el webhook en un pequeño punto final de API: valida algo, calcula una respuesta y responde en una sola solicitud. Shopify Flow sigue ejecutándose con lo que usted devuelva.
export default async function transform(payload, ctx) {
const ok = typeof payload.email === "string" && payload.email.includes("@")
ctx.respond({ accepted: ok }, { status: ok ? 200 : 422 })
return ok ? payload : null
}Pruebas
El panel «Prueba», en la pestaña «Función», ejecuta el código del editor - incluidos los cambios no guardados - con un payload de ejemplo. Muestra el valor de retorno, la respuesta que enviaría su función, los campos de Shopify Flow que genera, sus líneas de registro y la duración. No se activa Shopify Flow, no se registra nada en el historial y no se contabiliza nada en su plan. Sin embargo, las llamadas al almacenamiento son reales: una ejecución de prueba lee y escribe en el mismo almacén que las solicitudes en producción.
Cuando una función falla
Si su código genera un error, agota el tiempo de espera o devuelve un resultado inutilizable, la solicitud se rechaza con el código de error 422 y el fallo se registra en el Historial junto con el error y sus líneas de registro, para que pueda ver qué ha ocurrido. Corrija el código y vuelva a ejecutar esa entrada: la repetición ejecutará la nueva versión.
Límites
- 5 segundos y 64 MB por ejecución, y 50 000 caracteres de código.
- No hay paquetes de npm.
ctx.fetches la única opción disponible, y no se admiten direcciones internas ni privadas. ctx.shopifyPermite 10 llamadas por ejecución, solo consultas, limitadas a los ámbitos que haya concedido.- Cada ejecución que llega a Shopify Flow se considera una invocación normal y cuenta para su plan. Una solicitud omitida no cuenta.

