Skip to content

Instantly share code, notes, and snippets.

@iamkevingreen
Last active October 20, 2023 06:55
Show Gist options
  • Save iamkevingreen/3872f5acbaf5b100a8ebc02e4d95a03e to your computer and use it in GitHub Desktop.
Save iamkevingreen/3872f5acbaf5b100a8ebc02e4d95a03e to your computer and use it in GitHub Desktop.
const sanityClient = require('@sanity/client');
const crypto = require('crypto');
const {
SANITY_API_TOKEN,
SANITY_PROJECT_ID,
SANITY_DATASET,
SHOPIFY_SECRET
} = process.env;
const client = sanityClient({
projectId: SANITY_PROJECT_ID,
dataset: SANITY_DATASET,
token: SANITY_API_TOKEN,
});
exports.handler = async (event, context) => {
if (event.httpMethod !== 'POST' || !event.body) {
return {
statusCode: 400,
body: ''
};
}
let data;
let hasVariantsToSync = false;
const hmac = event.headers['x-shopify-hmac-sha256']
try {
data = JSON.parse(event.body);
const generatedHash = crypto
.createHmac('sha256', SHOPIFY_SECRET)
.update(event.body)
.digest('base64')
if (generatedHash !== hmac) {
return {
statusCode: 400,
body: JSON.stringify({
error: 'Bad Webhook Request'
})
}
}
} catch (error) {
console.log('JSON parsing error:', error);
return {
statusCode: 400,
body: JSON.stringify({
error: 'Bad request body'
})
};
}
// Build our initial product
const product = {
_type: 'product',
_id: data.id.toString(),
productId: data.id,
title: data.title,
defaultPrice: data.variants[0].price,
slug: {
_type: 'slug',
current: data.handle
}
};
return client
.transaction()
.createIfNotExists(product)
.patch(data.id.toString(), patch => patch.set(product))
.commit()
.then(res => {
console.log(`Successfully updated/patched Product ${data.id} in Sanity`);
if (data.variants.length > 1) {
hasVariantsToSync = true;
return Promise.all(data.variants.map(variant => {
const variantData = {
_type: 'productVariant',
_id: variant.id.toString(),
productId: data.id,
variantId: variant.id,
title: data.title,
variantTitle: variant.title,
sku: variant.sku,
price: variant.price
};
return client
.transaction()
.createIfNotExists(variantData)
.patch(variant.id.toString(), patch => patch.set(variantData))
.commit()
.then(response => {
console.log(`Successfully updated/patched Variant ${variant.id} in Sanity`);
return response;
})
.catch(error => {
console.log('Sanity error:', error);
return error;
});
})).then(result => {
if (hasVariantsToSync) {
return client
.transaction()
.createIfNotExists(product)
.patch(data.id.toString(), patch => patch.set({
variants: data.variants.map(variant => ({
_type: 'reference',
_ref: variant.id.toString(),
_key: variant.id.toString(),
}))
}))
.commit()
.then(response => {
console.log(`Successfully added variant references to ${data.id} in Sanity`);
return {
statusCode: 200,
body: JSON.stringify(response)
};
})
.catch(error => {
console.log('Sanity error:', error);
return error;
});
} else {
return {
statusCode: 200,
body: JSON.stringify(res)
};
}
}).catch(error => {
console.log('Sanity error:', error);
return {
statusCode: 500,
body: JSON.stringify({
error: 'An internal server error has occurred',
})
};
});
} else {
return {
statusCode: 200,
body: JSON.stringify(res)
};
}
})
.catch(error => {
console.log('Sanity error:', error);
return {
statusCode: 500,
body: JSON.stringify({
error: 'An internal server error has occurred',
})
};
});
};
@alexcasche
Copy link

alexcasche commented Oct 14, 2020 via email

@iamkevingreen
Copy link
Author

@alexcasche yeah I wish there was a better way to diff compare without a third party, and since shopify no longer sends inventory change it's pretty frustrating the hacks we need to implement to prevent the updates. But if I have to check sanity before updating i'd prefer that and prevent the rebuilding. I am experimenting with a different way to handle it that can also scale for users with hopefully low overhead. Also looking into Fauna as an option as it works pretty well with serverless and has pretty decent free plans.

@alexcasche
Copy link

@iamkevingreen yeah right now we’re doing SSR so we can handle some server tasks. But netlify add ons could easily replace the need soon. Background jobs and some redis integration would be awesome. Fauna looks really cool too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment