Skip to content

Commit

Permalink
feat: octokit.request & octokit.request.endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
gr2m committed Nov 17, 2018
1 parent 5fd0e42 commit 1fdfbf0
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 51 deletions.
11 changes: 4 additions & 7 deletions index.js
@@ -1,11 +1,10 @@
module.exports = GitHubApi

const defaultsDeep = require('lodash/defaultsDeep')
const endpoint = require('@octokit/request').endpoint
const Hook = require('before-after-hook')

const parseClientOptions = require('./lib/parse-client-options')
const request = require('./lib/request')
const ENDPOINT_DEFAULTS = require('./lib/endpoint').DEFAULTS
const requestWithDefaults = require('./lib/request-with-defaults')

const PLUGINS = [
require('./lib/plugins/authentication'),
Expand All @@ -14,15 +13,13 @@ const PLUGINS = [
]

function GitHubApi (options) {
const defaults = defaultsDeep(parseClientOptions(options), ENDPOINT_DEFAULTS)

const hook = new Hook()
const api = {
// NOTE: github.hook, github.plugin and github.request are experimental APIs
// NOTE: github.hook and github.plugin are experimental APIs
// at this point and can change at any time
hook,
plugin: (pluginFunction) => pluginFunction(api),
request: (options) => api.hook('request', defaultsDeep(options, defaults), request)
request: requestWithDefaults(hook, endpoint, parseClientOptions(options))
}

PLUGINS.forEach(api.plugin)
Expand Down
14 changes: 14 additions & 0 deletions lib/parse-client-options.js
@@ -1,10 +1,13 @@
module.exports = parseOptions

const defaults = require('lodash/defaults')
const getUserAgent = require('universal-user-agent')
const pick = require('lodash/pick')

const deprecate = require('./deprecate')
const getRequestAgent = require('./get-request-agent')
const pkg = require('../package.json')

const DEFAULTS = require('./defaults')
const OPTION_NAMES = [
'timeout',
Expand Down Expand Up @@ -42,6 +45,13 @@ function parseOptions (userOptions) {
deprecate('Promise option is no longer supported. The native Promise API is used')
}

if (userOptions.headers) {
userOptions.headers = Object.keys(userOptions.headers).reduce((newObj, key) => {
newObj[key.toLowerCase()] = userOptions.headers[key]
return newObj
}, {})
}

const options = defaults(pick(userOptions, OPTION_NAMES), DEFAULTS)

const clientDefaults = {
Expand Down Expand Up @@ -71,5 +81,9 @@ function parseOptions (userOptions) {
clientDefaults.request.agent = getRequestAgent(clientDefaults.baseUrl, userOptions)
}

const userAgentOption = clientDefaults.headers['user-agent']
const defaultUserAgent = `octokit.js/${pkg.version} ${getUserAgent()}`
clientDefaults.headers['user-agent'] = [userAgentOption, defaultUserAgent].filter(Boolean).join(' ')

return clientDefaults
}
28 changes: 18 additions & 10 deletions lib/plugins/endpoint-methods/index.js
Expand Up @@ -2,14 +2,14 @@

module.exports = apiPlugin

const get = require('lodash/get')
const pick = require('lodash/pick')

const method = require('./method')
const set = require('lodash/set')

const validate = require('./validate')
const ENDPOINT_DEFAULTS = require('../../routes.json')

function apiPlugin (octokit) {
octokit.hook.before('request', validate)

Object.keys(ENDPOINT_DEFAULTS).forEach(namespaceName => {
octokit[namespaceName] = {}

Expand All @@ -19,15 +19,23 @@ function apiPlugin (octokit) {

if (apiOptions.alias) {
deprecated = apiOptions.deprecated
apiOptions = get(ENDPOINT_DEFAULTS, apiOptions.alias)
const [aliasNamespaceName, aliasApiName] = apiOptions.alias.split('.')
apiOptions = ENDPOINT_DEFAULTS[aliasNamespaceName][aliasApiName]
}

const endpointDefaults = pick(apiOptions, ['method', 'url', 'headers', 'request'])
if (deprecated) {
endpointDefaults.deprecated = deprecated
}
const endpointDefaults = ['method', 'url', 'headers'].reduce((map, key) => {
if (typeof apiOptions[key] !== 'undefined') {
map[key] = apiOptions[key]
}

return map
}, {})

set(endpointDefaults, 'request.endpoint', Object.assign({
deprecated
}, apiOptions))

octokit[namespaceName][apiName] = method.bind(null, octokit, endpointDefaults, apiOptions.params)
octokit[namespaceName][apiName] = octokit.request.defaults(endpointDefaults)
})
})
}
18 changes: 15 additions & 3 deletions lib/plugins/endpoint-methods/validate.js
Expand Up @@ -4,12 +4,24 @@ module.exports = validate

const set = require('lodash/set')
const get = require('lodash/get')
const HttpError = require('../../request/http-error')
const HttpError = require('@octokit/request/lib/http-error')

const deprecate = require('../../deprecate')

function validate (endpointParams, options) {
function validate (options) {
if (!options.request.endpoint) {
return
}

const endpointParams = options.request.endpoint.params
const deprecated = options.request.endpoint.deprecated

if (deprecated) {
deprecate(deprecated)
}

// Alias are handled before validation, as validation rules
// ar set the aliased parameter. The `mapTo` property is the other way
// are set to the aliased parameter. The `mapTo` property is the other way
// around, the final parameter name is the mapTo value, but validation
// rules are on parameter with the mapTo property
Object.keys(options).forEach(optionName => {
Expand Down
4 changes: 2 additions & 2 deletions lib/plugins/pagination/get-first-page.js
Expand Up @@ -2,6 +2,6 @@ module.exports = getFirstPage

const getPage = require('./get-page')

function getFirstPage (octokit, link, headers, callback) {
return getPage(octokit, link, 'first', headers, callback)
function getFirstPage (octokit, link, headers) {
return getPage(octokit, link, 'first', headers)
}
4 changes: 2 additions & 2 deletions lib/plugins/pagination/get-last-page.js
Expand Up @@ -2,6 +2,6 @@ module.exports = getLastPage

const getPage = require('./get-page')

function getLastPage (octokit, link, headers, callback) {
return getPage(octokit, link, 'last', headers, callback)
function getLastPage (octokit, link, headers) {
return getPage(octokit, link, 'last', headers)
}
4 changes: 2 additions & 2 deletions lib/plugins/pagination/get-next-page.js
Expand Up @@ -2,6 +2,6 @@ module.exports = getNextPage

const getPage = require('./get-page')

function getNextPage (octokit, link, headers, callback) {
return getPage(octokit, link, 'next', headers, callback)
function getNextPage (octokit, link, headers) {
return getPage(octokit, link, 'next', headers)
}
26 changes: 3 additions & 23 deletions lib/plugins/pagination/get-page.js
@@ -1,26 +1,13 @@
module.exports = getPage

const HttpError = require('../../request/http-error')
const HttpError = require('@octokit/request/lib/http-error')
const getPageLinks = require('./get-page-links')
const deprecate = require('../../deprecate')

function getPage (octokit, link, which, headers, callback) {
if (typeof headers === 'function') {
callback = headers
headers = null
}

if (callback) {
deprecate('callbacks will be removed in v16. Use async/await or Promises instead.')
}

function getPage (octokit, link, which, headers) {
const url = getPageLinks(link)[which]

if (!url) {
const urlError = new HttpError(`No ${which} page found`, 404)
if (callback) {
return callback(urlError)
}
return Promise.reject(urlError)
}

Expand All @@ -29,14 +16,7 @@ function getPage (octokit, link, which, headers, callback) {
headers: applyAcceptHeader(link, headers)
}

const promise = octokit.request(requestOptions)

if (callback) {
promise.then(callback.bind(null, null), callback)
return
}

return promise
return octokit.request(requestOptions)
}

function applyAcceptHeader (res, headers) {
Expand Down
4 changes: 2 additions & 2 deletions lib/plugins/pagination/get-previous-page.js
Expand Up @@ -2,6 +2,6 @@ module.exports = getPreviousPage

const getPage = require('./get-page')

function getPreviousPage (octokit, link, headers, callback) {
return getPage(octokit, link, 'prev', headers, callback)
function getPreviousPage (octokit, link, headers) {
return getPage(octokit, link, 'prev', headers)
}
17 changes: 17 additions & 0 deletions lib/request-with-defaults.js
@@ -0,0 +1,17 @@
module.exports = withDefaults

const request = require('@octokit/request/lib/request')

function withDefaults (hook, oldEndpoint, newDefaults) {
const endpoint = oldEndpoint.defaults(newDefaults)

const newApi = function (route, options) {
const endpointOptions = endpoint.merge(route, options)
return hook('request', endpointOptions, function (options) {
return request(endpoint.parse(options))
})
}
newApi.endpoint = endpoint
newApi.defaults = withDefaults.bind(null, hook, endpoint)
return newApi
}

0 comments on commit 1fdfbf0

Please sign in to comment.