Funções de transformação

O mapeamento extrai valores de uma solicitação. Uma função de transformação vai além: trata-se de seu próprio código JavaScript, executado em todas as solicitações antes de Shopify Flow, para que você possa reformular a Payload, consultar alguma informação, decidir se vale a pena executar um fluxo de trabalho para essa solicitação ou responder diretamente ao solicitante.

Essa opção está disponível na guia “Função” de um webhook. Um editor vazio significa que a função está desativada.

A forma de uma função

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" }
}

O que o site ctx oferece a você

ctx.request method, contentType, a solicitação headers (informações confidenciais ocultadas) e query
ctx.webhook The webhooks id e name
ctx.shop Seu domínio do myShopify
ctx.log(...) Exibe uma linha que o senhor pode ler no painel de teste e no Histórico
await ctx.fetch(url, init) Chama uma API pública
await ctx.shopify(query, variables) Lê os dados das lojas com o Admin GraphQL
ctx.storage Mantém valores pequenos entre as execuções (veja abaixo)
ctx.respond(body, options) Atende a chamada imediatamente

Reestruturação do payload

O uso mais comum: transformar a estrutura de um remetente nos poucos valores de que seu fluxo de trabalho necessita.

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,
  }
}

Excluir solicitações desnecessárias

Retorne null e a solicitação será interrompida nesse ponto: não haverá execução do Shopify Flow, nenhuma entrada no histórico e nada será contabilizado no seu plano. O chamador receberá 200 com { "skipped": true }, de modo que não fará uma nova tentativa.

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
}

Lembrar-se das coisas entre as corridas

ctx.storage é um pequeno banco de dados de chave-valor que pertence à sua loja. É a ferramenta para responder à pergunta “já vi isso antes?”: armazene um ID quando um evento ocorrer e ignore a próxima solicitação que contenha o mesmo ID, mesmo que ela chegue dias depois.

Ligar Será que
await ctx.storage.get(key) A loja, ou null
await ctx.storage.set(key, value) Armazena qualquer valor JSON, sobrescrevendo
await ctx.storage.delete(key) Remove-o; true, caso existisse
await ctx.storage.list({ prefix, limit, cursor }) Principais nomes e tamanhos, 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
}

Enriquecimento com dados das lojas

ctx.shopify Executa consultas GraphQL de administração somente leitura para a sua loja, de modo que um fluxo de trabalho possa ser iniciado com dados aos quais o remetente nunca teve acesso. Ele só tem acesso ao que o senhor permitir: conceda os escopos necessários na seção “Acesso aos dados da loja”, na guia “Função”. Nada é concedido por padrão, e as mutações são recusadas.

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 você mesmo a chamada

ctx.respond() envia uma resposta imediatamente, o que transforma o webhook em um pequeno endpoint de API: valida algo, calcula uma resposta e responde em uma única solicitação. O Shopify Flow continua a ser executado independentemente do que o senhor retornar.

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
}

Testes

O painel “Teste”, na guia “Função”, executa o código no editor - incluindo alterações não salvas - com base em um payload de teste. Ele exibe o valor de retorno, a resposta que sua função enviaria, os campos do Shopify Flow gerados, suas linhas de log e a duração. Nada aciona o Shopify Flow, nada é registrado no Histórico e nada é contabilizado no seu plano. As chamadas de armazenamento, porém, são reais: uma execução de teste lê e grava no mesmo armazenamento que as solicitações em produção.

Quando uma função falha

Caso seu código gere uma exceção, atinja o tempo limite ou retorne algo inutilizável, a solicitação será rejeitada com o código de erro 422 e a falha será registrada no Histórico, juntamente com o erro e suas linhas de log, para que você possa verificar o que ocorreu. Corrija o código e repita essa entrada: a repetição executará a nova versão.

Limites

  • 5 segundos e 64 MB por execução, além de 50.000 caracteres de código.
  • Não há pacotes npm. O endereço ctx.fetch é a única opção disponível, e endereços internos ou privados não são aceitos.
  • ctx.shopify permite 10 chamadas por execução, apenas consultas, limitadas aos escopos que o senhor concedeu.
  • Cada execução que chega ao Shopify Flow é considerada uma invocação normal e conta para o seu plano. Uma solicitação ignorada não conta.