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

The contractjavascript
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.

Flatten and normalisejavascript
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.

Only paid orders above 100javascript
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
Skip events you have already seenjavascript
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.

Look up a variant by SKUjavascript
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.

Reply to the caller and start a workflowjavascript
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.fetch es la única opción disponible, y no se admiten direcciones internas ni privadas.
  • ctx.shopify Permite 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.