Transformationsfunktioner

Mapping henter værdier ud af en anmodning. En transform-funktion går et skridt videre: Det er din egen JavaScript-kode, der kører på hver eneste anmodning, før den sendes videre til Shopify Flow, så du kan omforme Payloaden, slå noget op, afgøre, om anmodningen overhovedet er værd at køre en arbejdsgang på, eller selv svare den, der har sendt anmodningen.

Den findes under fanen »Funktion« i en webhook. En tom editor betyder, at den er slået fra.

En funktions form

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

Hvad du får med »ctx«

ctx.request method, contentType, forespørgslen headers (hemmelige oplysninger er skjult) og query
ctx.webhook Webhookens id og name
ctx.shop Dit myshopify-domæne
ctx.log(...) Skriver en linje, som du kan læse i testpanelet og i historikken
await ctx.fetch(url, init) Kaldes via et offentligt API
await ctx.shopify(query, variables) Læser butiksdata med Admin GraphQL
ctx.storage Bevarer små værdier mellem kørslerne (se nedenfor)
ctx.respond(body, options) Tager straks imod opkaldet

Omstrukturering af en payload

Den mest almindelige anvendelse: at omdanne en afsenders struktur til de få værdier, som din arbejdsgang har brug for.

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

Slet de anmodninger, du ikke har brug for

Returner null, og anmodningen stopper der: ingen Shopify Flow-kørsel, ingen historikpost, og intet tæller med i dit abonnement. Den, der kalder, får 200 med { "skipped": true }, så der foretages ikke et nyt forsøg.

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
}

At huske ting mellem løbeturene

ctx.storage er et lille nøgle-værdi-lager, der hører til din butik. Det er værktøjet til at finde ud af, om du har set det før: Gem et id, når en begivenhed indtræffer, og spring den næste anmodning over, der indeholder det samme id, selvom den kommer flere dage senere.

Ring Gør
await ctx.storage.get(key) Den lagrede værdi, eller »null«
await ctx.storage.set(key, value) Gemmer enhver JSON-værdi og overskriver den
await ctx.storage.delete(key) Sletter den; true, hvis den fandtes
await ctx.storage.list({ prefix, limit, cursor }) Vigtige betegnelser og størrelser, side for side
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
}

Berigelse med butikskenoplysninger

ctx.shopify Kører skrivebeskyttede Admin GraphQL-forespørgsler for din butik, så en arbejdsgang kan starte med data, som afsenderen aldrig har haft adgang til. Den ser kun det, du tillader: Tildel de omfang, du har brug for, under »Butiksdataadgang« på fanen »Funktion«. Der er ikke tildelt noget som standard, og mutationer afvises.

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

Selv at besvare opkaldet

ctx.respond() sender straks et svar tilbage, hvilket gør webhooken til et lille API-endpoint: valider noget, beregn et svar og svar i én enkelt anmodning. Shopify Flow kører stadig videre, uanset hvad du returnerer.

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
}

Testning

Testpanelet på fanen »Funktion« kører koden i editoren - inklusive ugemte ændringer - mod en eksempel-payload. Det viser returværdien, det svar, din funktion ville sende, de Flow-felter, den genererer, dine loglinjer og varigheden. Intet udløser Shopify Flow, intet skrives til historikken, og intet tæller med i dit abonnement. Opkald til lageret er dog reelle: En testkørsel læser og skriver til det samme lager som live-anmodninger.

Når en funktion mislykkes

Hvis din kode kaster en undtagelse, går i timeout eller returnerer noget ubrugeligt, afvises anmodningen med en »422«, og fejlen registreres i historikken sammen med fejlmeddelelsen og dine loglinjer, så du kan se, hvad der skete. Ret koden, og afspil den pågældende post igen: Afspilningen kører den nye version.

Grænser

  • 5 sekunder og 64 MB pr. kørsel samt 50.000 tegn kode.
  • Ingen npm-pakker. ctx.fetch er den eneste løsning, og interne eller private adresser afvises.
  • ctx.shopify Tillader 10 opkald pr. kørsel, udelukkende forespørgsler, begrænset til de omfang, du har tildelt.
  • Hver kørsel, der når frem til Shopify Flow, er en normal opkald og tæller med i din plan. En oversprungen anmodning tæller ikke med.