Skip to content

Instantly share code, notes, and snippets.

@mmgj
Created September 22, 2018 17:02
Show Gist options
  • Save mmgj/d361ad83c99f52699a5bc3a8326fccfa to your computer and use it in GitHub Desktop.
Save mmgj/d361ad83c99f52699a5bc3a8326fccfa to your computer and use it in GitHub Desktop.
Sanity -> Webtask.io
/**
* Cloud function triggered by changes in dataset which will generate metadata for art asset.
*/
const Promise = require('es6-promise').Promise;
const sanityClient = require('@sanity/client');
/** Setup */
const client = token => sanityClient({
projectId: '<projectId>',
dataset: '<dataSet>',
useCdn: false,
token
});
function generateArtMetadata(asset, SANITY_TOKEN) {
return new Promise(function(resolve, reject) {
/** A bunch of async operations to generate metadata
* happens here. Omitted for sake of brevity and relevance.
**/
});
}
function validateAndPatch(id, SANITY_TOKEN, storage, recentRevisions = null) {
return new Promise((resolve, reject) => {
client(SANITY_TOKEN).fetch(`*[_id == "${id}"] {_id, _type, _rev, "asset": imageField.asset-> }[0]`).then(thing => {
/** Check for obvious fails and then go ahead with the patching */
if(thing._type !== 'card') {
resolve(`WRONG TYPE > Exit 200`);
} else if (recentRevisions && recentRevisions.indexOf(thing._rev) > -1) {
resolve(`REVISION ID BLACKLISTED > Exit 200`);
} else if (thing.asset === undefined || thing.asset === null) {
resolve(`NO ART ASSET > Exit 200`);
} else {
/** Passed basic sanity checks. Let's roll! */
generateArtMetadata(thing.asset).then(meta => {
client(SANITY_TOKEN)
.patch(thing._id)
.set({
'imageField.palette': meta.palette,
'imageField.keyNumbers': meta.keyNumbers,
})
.commit()
.then(patched => {
const blacklist = [patched._rev, ...recentRevisions].slice(0, 25); // Randomly chosen cutoff point at 25.
addRevisionToBlacklist(storage, blacklist).then(good => {
resolve(`GOOD: Document patched! Saved ${patched._rev} to blacklist!`);
}).catch(err => {
reject(`BAD: Document was patched, but failed to save revision with ID: ${patched._rev} to blacklist.` );
});
})
.catch(err => {
reject('Failed at step [ patching document ] with error: ', err);
}); // EOF patch()
})
.catch(err => {
reject('Failed at step [ generating metadata ] with error: ', err);
}); // EOF getArtDetails()
}
})
.catch(err => {
reject('Failed at step [ initally fetching document ] with error: ', err);
}); // EOF client.fetch()
}); // EOF Promise()
}
/** Because we are listening to events of both 'create' and 'update' types
* we quickly realize that the patch operation a few lines up (if successful) will
* trigger its own 'update' event, and we are set for an infinite loop.
* There are probably several ways to deal with this, but I chose to save the
* revision ID (_rev) returned in patch() in the webtask storage and compare with
* revision ID of incoming events and exit if the revision ID originated here.
*/
function getRevisionBlacklist(storage) {
return new Promise((resolve, reject) => {
storage.get((error, data) => {
if (error) reject(error);
resolve(data.blacklist);
});
});
}
function addRevisionToBlacklist(storage, blacklist) {
return new Promise((resolve, reject) => {
storage.set({ blacklist: blacklist }, (error) => {
if (error) reject(error);
resolve();
});
});
}
module.exports = function(context, cb) {
const { storage } = context;
const { SANITY_TOKEN } = context.secrets;
const { created = [], updated = [] } = context.body.ids;
getRevisionBlacklist(storage).then(recentRevisions => {
const cards = [...created, ...updated].map(id => {
return validateAndPatch(id, SANITY_TOKEN, storage, recentRevisions);
});
Promise.all(cards).then(good => {
console.log('Exit 200: ', good);
cb(null, 200);
}).catch(bad => {
console.log('Exit 500: ', bad);
cb(null, 500)
});
}).catch(error => {
console.log('Exit 500 on first level: ', error)
cb(null, 500)
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment