Created
December 14, 2022 16:16
-
-
Save rdraward/a9028e5ad25a6ad1cc73281606aabe2a to your computer and use it in GitHub Desktop.
An example of a code effect added to the Update action of a Shopify Customer model that overrides the metafield data in Gadget first, then sends the information to Shopify so that the data stays in sync
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Fetch the ids for metafields on a resource | |
*/ | |
const fetchMetafieldIds = async ({ resource, shopifyApi, metafieldSchema, id }) => { | |
const gidResource = resource.charAt(0).toUpperCase() + resource.slice(1); | |
const gid = `gid://shopify/${gidResource}/${id}`; | |
return ( | |
await shopifyApi.graphql( | |
` | |
query MetafieldIds($id: ID!) { | |
metafields: ${resource}(id: $id) { | |
${metafieldSchema.metafields.map( | |
({ namespace, key }) => | |
`${namespace}_${key}: metafield(namespace: ${JSON.stringify(namespace)}, key: ${JSON.stringify(key)}) { id }` | |
)} | |
} | |
} | |
`, | |
{ | |
id: gid, | |
} | |
) | |
).metafields; | |
}; | |
/** | |
* Get the shopify metafield configuration for all metadata fields in `model` | |
*/ | |
const getModelMetafieldSchema = (model) => { | |
const metafields = []; | |
const privateMetafields = []; | |
for (const field of Object.values(model.fields)) { | |
const contributorConfig = field.contributorConfiguration["shopify/contributor/field/metafield"]; | |
if (!contributorConfig) continue; | |
const metafield = contributorConfig.metafield; | |
if (!metafield.namespace || !metafield.key) continue; | |
if (!metafield.isPrivate) { | |
metafields.push({ ...metafield, apiIdentifier: field.apiIdentifier }); | |
} else { | |
privateMetafields.push({ ...metafield, apiIdentifier: field.apiIdentifier }); | |
} | |
} | |
return { metafields, privateMetafields }; | |
}; | |
const buildRESTMetafieldsPayload = async ({ resource, shopifyApi, model, record }) => { | |
const metafieldSchema = getModelMetafieldSchema(model); | |
const metafieldIds = await fetchMetafieldIds({ resource, shopifyApi, metafieldSchema, id: record.id }); | |
// Make sure the field we're updating has a metafield and that if it has a Shopify id then include id | |
return metafieldSchema.metafields.map(({ namespace, key, type, apiIdentifier }) => { | |
const gid = metafieldIds[`${namespace}_${key}`]?.id; | |
const id = gid ? gid.match(/^gid:\/\/shopify\/[A-Za-z]+\/(\d+)$/)[1] : null; | |
return { | |
id, | |
namespace, | |
key, | |
type, | |
value: record[apiIdentifier], | |
}; | |
}); | |
}; | |
// Once a record has been updated in Gadget, fire off an update to the Shopify API | |
// to keep our meta fields in sync | |
module.exports = async ({ model, record, connections }) => { | |
const shopifyApi = await connections.shopify.forShopDomain("mycoolshop.myshopify.com"); | |
// If customer's order count is greater than 10, mark them with a VIP metafield flag | |
if (record.ordersCount > 10) { | |
// Set VIP flag to true | |
// This field will have been set up as a metafield in the Shopify Customer model | |
record.isVip = true; | |
// Update metafield on a resource through the REST API | |
await shopifyApi.customer.update(Number(record.id), { | |
metafields: await buildRESTMetafieldsPayload({ | |
resource: "customer", | |
shopifyApi, | |
model, | |
record, | |
}), | |
}); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment