Skip to content

Commit

Permalink
Rework [suggest] code using async/await (#2029)
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmelnikow authored Oct 31, 2018
1 parent cc84394 commit 07c5f47
Showing 1 changed file with 102 additions and 119 deletions.
221 changes: 102 additions & 119 deletions lib/suggest.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,83 @@
// Suggestion API
//
// eg. /$suggest/v1?url=https://github.com/badges/shields
//
// Tests for this endpoint are in services/suggest/suggest.spec.js. The
// endpoint is called from frontend/components/suggestion-and-search.js.

'use strict'

const nodeUrl = require('url')
const request = require('request')

// data: {url}, JSON-serializable object.
// end: function(json), with json of the form:
// - badges: list of objects of the form:
// - link: target as a string URL.
// - badge: shields image URL.
// - name: string
function suggest(allowedOrigin, githubApiProvider, data, end, ask) {
// The typical dev and production setups are cross-origin. However, in
// Heroku deploys and some self-hosted deploys these requests may come from
// the same host.
const origin = ask.req.headers.origin
if (origin) {
if (allowedOrigin.includes(origin)) {
ask.res.setHeader('Access-Control-Allow-Origin', origin)
} else {
ask.res.setHeader('Access-Control-Allow-Origin', 'null')
end({ err: 'Disallowed' })
return
}
function twitterPage(url) {
if (url.protocol === null) {
return null
}

const schema = url.protocol.slice(0, -1)
const host = url.host
const path = url.path
return {
name: 'Twitter',
link: `https://twitter.com/intent/tweet?text=Wow:&url=${encodeURIComponent(
url.href
)}`,
badge: `https://img.shields.io/twitter/url/${schema}/${host}${path}.svg?style=social`,
}
}

function githubIssues(user, repo) {
const repoSlug = `${user}/${repo}`
return {
name: 'GitHub issues',
link: `https://github.com/${repoSlug}/issues`,
badge: `https://img.shields.io/github/issues/${repoSlug}.svg`,
}
}

let url
function githubForks(user, repo) {
const repoSlug = `${user}/${repo}`
return {
name: 'GitHub forks',
link: `https://github.com/${repoSlug}/network`,
badge: `https://img.shields.io/github/forks/${repoSlug}.svg`,
}
}

function githubStars(user, repo) {
const repoSlug = `${user}/${repo}`
return {
name: 'GitHub stars',
link: `https://github.com/${repoSlug}/stargazers`,
badge: `https://img.shields.io/github/stars/${repoSlug}.svg`,
}
}

async function githubLicense(githubApiProvider, user, repo) {
const repoSlug = `${user}/${repo}`

let link = `https://github.com/${repoSlug}`

const { buffer } = await githubApiProvider.requestAsPromise(
request,
`/repos/${repoSlug}/license`
)
try {
url = nodeUrl.parse(data.url)
} catch (e) {
end({ err: '' + e })
return
const data = JSON.parse(buffer)
if ('html_url' in data) {
link = data.html_url
}
} catch (e) {}

return {
name: 'GitHub license',
badge: `https://img.shields.io/github/license/${repoSlug}.svg`,
link,
}
findSuggestions(githubApiProvider, url, end)
}

// url: string
// cb: function({badges})
function findSuggestions(githubApiProvider, url, cb) {
async function findSuggestions(githubApiProvider, url) {
let promises = []
if (url.hostname === 'github.com') {
const userRepo = url.pathname.slice(1).split('/')
Expand All @@ -54,106 +91,52 @@ function findSuggestions(githubApiProvider, url, cb) {
])
}
promises.push(twitterPage(url))
Promise.all(promises)
.then(badges => {
// eslint-disable-next-line standard/no-callback-literal
cb({
badges: badges.filter(b => b != null),
})
})
.catch(err => {
// eslint-disable-next-line standard/no-callback-literal
cb({ badges: [], err: err })
})
}

function twitterPage(url) {
if (url.protocol === null) {
return Promise.resolve(null)
}
const schema = url.protocol.slice(0, -1)
const host = url.host
const path = url.path
return Promise.resolve({
name: 'Twitter',
link:
'https://twitter.com/intent/tweet?text=Wow:&url=' +
encodeURIComponent(url.href),
badge:
'https://img.shields.io/twitter/url/' +
schema +
'/' +
host +
path +
'.svg?style=social',
})
}
const suggestions = await Promise.all(promises)

function githubIssues(user, repo) {
const userRepo = user + '/' + repo
return Promise.resolve({
name: 'GitHub issues',
link: 'https://github.com/' + userRepo + '/issues',
badge: 'https://img.shields.io/github/issues/' + userRepo + '.svg',
})
return suggestions.filter(b => b != null)
}

function githubForks(user, repo) {
const userRepo = user + '/' + repo
return Promise.resolve({
name: 'GitHub forks',
link: 'https://github.com/' + userRepo + '/network',
badge: 'https://img.shields.io/github/forks/' + userRepo + '.svg',
})
}

function githubStars(user, repo) {
const userRepo = user + '/' + repo
return Promise.resolve({
name: 'GitHub stars',
link: 'https://github.com/' + userRepo + '/stargazers',
badge: 'https://img.shields.io/github/stars/' + userRepo + '.svg',
})
}

function githubLicense(githubApiProvider, user, repo) {
return new Promise(resolve => {
const apiUrl = `/repos/${user}/${repo}/license`
githubApiProvider.request(request, apiUrl, {}, (err, res, buffer) => {
if (err !== null) {
resolve(null)
// data: {url}, JSON-serializable object.
// end: function(json), with json of the form:
// - badges: list of objects of the form:
// - link: target as a string URL.
// - badge: shields image URL.
// - name: string
function setRoutes(allowedOrigin, githubApiProvider, server) {
server.ajax.on('suggest/v1', (data, end, ask) => {
// The typical dev and production setups are cross-origin. However, in
// Heroku deploys and some self-hosted deploys these requests may come from
// the same host.
const origin = ask.req.headers.origin
if (origin) {
if (allowedOrigin.includes(origin)) {
ask.res.setHeader('Access-Control-Allow-Origin', origin)
} else {
ask.res.setHeader('Access-Control-Allow-Origin', 'null')
end({ err: 'Disallowed' })
return
}
const defaultBadge = {
name: 'GitHub license',
link: `https://github.com/${user}/${repo}`,
badge: `https://img.shields.io/github/license/${user}/${repo}.svg`,
}
if (res.statusCode !== 200) {
resolve(defaultBadge)
}
try {
const data = JSON.parse(buffer)
if (data.html_url) {
defaultBadge.link = data.html_url
resolve(defaultBadge)
} else {
resolve(defaultBadge)
}
} catch (e) {
resolve(defaultBadge)
}
})
})
}
}

function setRoutes(allowedOrigin, githubApiProvider, server) {
server.ajax.on('suggest/v1', (data, end, ask) =>
suggest(allowedOrigin, githubApiProvider, data, end, ask)
)
let url
try {
url = nodeUrl.parse(data.url)
} catch (e) {
end({ err: '' + e })
return
}

findSuggestions(githubApiProvider, url)
.then(badges => {
end({ badges })
})
.catch(err => {
end({ badges: [], err })
})
})
}

module.exports = {
suggest,
setRoutes,
}

0 comments on commit 07c5f47

Please sign in to comment.