Last active
August 29, 2015 14:08
-
-
Save grncdr/7b910144cf9a75583c64 to your computer and use it in GitHub Desktop.
Collect untranslated fields in a contentful entry and forward them elsewhere.
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
var hyperquest = require('hyperquest'); | |
module.exports = checkForUntranslatedFields; | |
module.exports.schema = { | |
access_token: 'string', | |
translation_url: 'string', | |
space_id: 'string', | |
entry_id: 'string' | |
}; | |
function checkForUntranslatedFields (hook) { | |
function ignore () { | |
hook.debug('ignored'); | |
hook.res.end('{"message":"ignored"}'); | |
} | |
function fail (err) { | |
hook.debug(err.stack); | |
hook.res.statusCode = 500; | |
hook.res.end(JSON.stringify({ message: err.message })); | |
} | |
var cma = createContentManagementClient(hook); | |
var getEntry; | |
if (hook.params.space_id && hook.params.entry_id) { | |
var entryPath = '/spaces/' + hook.params.space_id + '/entries/' + hook.params.entry_id + '/published'; | |
hook.debug('entry from query params: ' + entryPath); | |
getEntry = cma.bind(null, entryPath); | |
} else if (hook.req.headers['x-contentful-topic'] !== "ContentManagement.Entry.publish") { | |
return ignore(); | |
} else { | |
hook.debug('entry from request body'); | |
getEntry = collectJSON.bind(null, hook.req); | |
} | |
getEntry(function (err, entry) { | |
if (err) { | |
return fail(err); | |
} | |
hook.debug('got entry'); | |
getLocalesAndContentType(entry, function (err, locales, contentType) { | |
if (err) return fail(err); | |
var neededTranslations; | |
try { | |
neededTranslations = getNeededTranslations(locales, contentType, entry, hook); | |
} catch (err) { | |
return fail(err); | |
} | |
return hook.res.end(JSON.stringify(neededTranslations)); | |
if (!neededTranslations.length) { | |
return ignore(); | |
} else { | |
return hook.res.end(JSON.stringify(neededTranslations)); | |
} | |
var req = hyperquest(hook.params.translation_url, { | |
method: 'POST', | |
headers: { | |
'content-type': 'application/json' | |
} | |
}).on('error', function (err) { | |
hook.debug('translation request failed'); | |
fail(err); | |
}).on('response', function (response) { | |
hook.res.statusCode = response.statusCode; | |
for (var key in response.headers) if (key !== 'Host') { | |
hook.res.setHeader(key, response.headers[key]); | |
} | |
response.pipe(hook.res); | |
}); | |
req.end(JSON.strinigy({ | |
entry: entry, | |
neededTranslations: neededTranslations | |
})); | |
}); | |
}); | |
function getLocalesAndContentType(entry, callback) { | |
var spacePath = '/spaces/' + entry.sys.space.sys.id; | |
var result = {}; | |
var remaining = 2; | |
getOne(spacePath + '/locales', 'locales'); | |
getOne(spacePath + '/content_types/' + entry.sys.contentType.sys.id + '/published', | |
'contentType'); | |
function getOne (path, property) { | |
cma(path, function (err, data) { | |
if (err && remaining) { | |
remaining = 0; | |
return callback(err); | |
} else { | |
hook.debug('got ' + property); | |
result[property] = data; | |
if (! --remaining) { | |
callback(null, result.locales, result.contentType); | |
} | |
} | |
}); | |
} | |
} | |
} | |
function createContentManagementClient (hook) { | |
var opts = { | |
headers: { Authorization: 'Bearer ' + hook.params.access_token } | |
}; | |
return function (path, callback) { | |
var uri = 'https://api.contentful.com' + path; | |
hook.debug('requesting ' + uri); | |
var stream = hyperquest(uri, opts); | |
var statusCode; | |
stream.on('response', function (response) { statusCode = response.statusCode; }); | |
collectJSON(stream, function (err, data) { | |
hook.debug('status code: ' + statusCode); | |
if (err) { | |
callback(err); | |
} else if (statusCode && statusCode !== 200) { | |
callback(data); | |
} else { | |
callback(null, data); | |
} | |
}); | |
}; | |
} | |
function getNeededTranslations (locales, contentType, entry, hook) { | |
var fieldsById = lookup(contentType.fields, 'id'); | |
var localesByCode = lookup(locales.items, 'code'); | |
var neededTranslations = []; | |
for (var fieldId in entry.fields) if (fieldsById[fieldId].localized) { | |
var untranslated = []; | |
for (var locale in localesByCode) { | |
if (!entry.fields[fieldId][locale]) { | |
untranslated.push(locale); | |
} | |
} | |
if (untranslated.length) { | |
neededTranslations.push({ | |
field: entry.fields[fieldId], | |
missingLocales: untranslated | |
}); | |
} | |
} | |
return neededTranslations; | |
} | |
function lookup (objects, prop) { | |
return objects.reduce(function (result, object) { | |
result[object[prop]] = object; | |
return result; | |
}, {}); | |
} | |
function collectJSON (stream, callback) { | |
return collect(stream, function (err, payload) { | |
if (err) return callback(err); | |
var data; | |
try { | |
data = JSON.parse(payload); | |
} catch (parseError) { | |
return callback(parseError); | |
} | |
callback(null, data); | |
}); | |
} | |
function collect (stream, callback) { | |
var all = ""; | |
var done = false; | |
stream | |
.on('error', function (err) { | |
if (!done) callback(err); | |
done = true; | |
}) | |
.on('data', function (chunk) { | |
all += chunk; | |
}) | |
.on('end', function () { | |
if (!done) callback(null, all); | |
done = true; | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment