You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
2.7 KiB

const jsonist = require('jsonist')
, xtend = require('xtend')
, qs = require('querystring')
, apiRoot = 'https://api.github.com'
function makeOptions (auth, options) {
var headers = xtend(
{ 'user-agent' : 'Magic Node.js application that does magic things' }
, typeof options == 'object' && typeof options.headers == 'object' ? options.headers : {}
)
options = xtend({ auth: auth.user + ':' + auth.token }, options)
options.headers = headers
if (!options.auth) delete options.auth
return options
}
function handler (callback) {
return function responseHandler (err, data, res) {
if (err)
return callback(err)
if (data && (data.error || data.message))
return callback(createError(data))
callback(null, data, res)
}
}
function createError (data) {
var message = data.error || data.message
var extra = data.errors ? ' (' + JSON.stringify(data.errors) + ')' : ''
return new Error('Error from GitHub: ' + message + extra)
}
function ghget (auth, url, options, callback) {
options = makeOptions(auth, options)
jsonist.get(url, xtend(options, { followRedirects: true }), handler(callback))
}
function ghpost (auth, url, data, options, callback) {
options = makeOptions(auth, options)
jsonist.post(url, data, options, handler(callback))
}
function lister (auth, urlbase, options, callback) {
var retdata = []
, afterDate = (options.afterDate instanceof Date) && options.afterDate
, optqsobj
, optqs
// overloading use of 'options' is ... not great
optqsobj = xtend(options)
delete optqsobj.afterDate
delete optqsobj.headers
optqs = qs.stringify(optqsobj)
;(function next (url) {
if (optqs)
url += '&' + optqs
ghget(auth, url, options, function (err, data, res) {
if (err)
return callback(err)
if (data.length)
retdata.push.apply(retdata, data)
var nextUrl = getNextUrl(res.headers.link)
, createdAt
if (nextUrl) {
if (!afterDate || (
(createdAt = retdata[retdata.length - 1].created_at) && new Date(createdAt) > afterDate
)) {
return next(nextUrl)
}
}
if (afterDate) {
retdata = retdata.filter(function (data) {
return !data.created_at || new Date(data.created_at) > afterDate
})
}
callback(null, retdata)
})
}(urlbase))
function getNextUrl (link) {
if (typeof link == 'undefined')
return
var match = /<([^>]+)>; rel="next"/.exec(link)
return match && match[1]
}
}
module.exports.makeOptions = makeOptions
module.exports.ghpost = ghpost
module.exports.ghget = ghget
module.exports.handler = handler
module.exports.lister = lister
module.exports.apiRoot = apiRoot