Skip to content

Commit

Permalink
refactor: node-github -> @octokit/rest
Browse files Browse the repository at this point in the history
  • Loading branch information
gr2m committed Jan 17, 2018
1 parent dcd4801 commit c2c88c0
Show file tree
Hide file tree
Showing 33 changed files with 850 additions and 942 deletions.
31 changes: 31 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module.exports = GitHubApi

const defaultsDeep = require('lodash/defaultsDeep')
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 PLUGINS = [
require('./lib/plugins/authentication'),
require('./lib/plugins/endpoint-methods'),
require('./lib/plugins/pagination')
]

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
// at this point and can change at any time
hook,
plugin: (pluginFunction) => pluginFunction(api),
request: (options) => api.hook('request', defaultsDeep(options, defaults), request)
}

PLUGINS.forEach(api.plugin)

return api
}
13 changes: 13 additions & 0 deletions lib/defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = {
ca: undefined,
family: undefined, // 4 for v4, 6 for v6
headers: {},
host: 'api.github.com',
pathPrefix: '', // for GitHub Enterprise
port: undefined,
protocol: 'https',
proxy: undefined,
rejectUnauthorized: true,
requestMedia: 'application/vnd.github.v3+json',
timeout: 0
}
69 changes: 69 additions & 0 deletions lib/endpoint/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
[back to `@octokit/rest`]('../..')

# `@octokit/rest/endpoint`

> Turn REST API endpoint options into generic request options
---

# ⚠️ This is not a public API at this point and can change at any time

---

## Usage

```js
const octokitRestEndpoint = require('@octokit/rest/lib/endpoint')

const options = octokitRestEndpoint({
// request options
method: 'GET',
url: '/orgs/:org/repos',
// parameters
org: 'octokit',
type: 'private'
})
```

`options` would now look something like

```js
{
method: 'GET',
url: 'https://api.github.com/orgs/octokit/repos?type=private',
headers: {
'user-agent': 'octokit/rest.js v1.2.3',
accept: 'application/vnd.github.v3+json'
}
}
```

You can pass them to your request library of preference.

## Options

### `method`

Any supported [http verb](https://developer.github.com/v3/#http-verbs), case insensitive.

### `url`

A path or full URL which may contain `:variable` or `{variable}` placeholders,
e.g. `/orgs/:org/repos`. The `url` is parsed using

## Defaults

| Name | Value |
|------------------------|-------------------------------------------------------------------------------------|
| **method** | `'get'` |
| **baseUrl** | `'https://api.github.com'` |
| **headers.accept** | `'application/vnd.github.v3+json'` |
| **headers.user-agent** | `'octokit/rest.js v1.2.3'` (1.2.3 being the current `@octokit.rest` version number) |

_To be done_: change defaults with

```js
const octokitRestEndpoint = require('@octokit/rest/lib/endpoint').defaults({
baseUrl: 'http://my-custom-host/api/v3'
})
```
22 changes: 22 additions & 0 deletions lib/endpoint/add-query-parameters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module.exports = addQueryParameters

function addQueryParameters (url, parameters) {
const separator = /\?/.test(url) ? '&' : '?'
const names = Object.keys(parameters)

if (names.length === 0) {
return url
}

return url + separator + names
.map(name => {
if (name === 'q') {
return 'q=' + parameters.q.split('+')
.map(encodeURIComponent)
.join('+')
}

return `${name}=${encodeURIComponent(parameters[name])}`
})
.join('&')
}
11 changes: 11 additions & 0 deletions lib/endpoint/defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const pkg = require('../../package.json')

module.exports = {
method: 'get',
baseUrl: 'https://api.github.com',
headers: {
accept: 'application/vnd.github.v3+json',
'user-agent': `octokit/rest.js v${pkg.version}`
},
request: {}
}
18 changes: 18 additions & 0 deletions lib/endpoint/extract-url-variable-names.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = extractUrlVariableName

const _ = require('lodash')

const urlVariableRegex = /\{[^}]+\}/g
function extractUrlVariableName (url) {
const matches = url.match(urlVariableRegex)

if (!matches) {
return []
}

return _.flatten(matches.map(removeNonChars))
}

function removeNonChars (variableName) {
return variableName.replace(/^\W+|\W+$/g, '').split(/,/)
}
60 changes: 60 additions & 0 deletions lib/endpoint/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use strict'

module.exports = restEndpoint

const _ = require('lodash')
const urlTemplate = require('url-template')

const addQueryParameters = require('./add-query-parameters')
const extractUrlVariableNames = require('./extract-url-variable-names')

const DEFAULTS = module.exports.DEFAULTS = require('./defaults')
const NON_PARAMETERS = [
'request',
'baseUrl'
]

function restEndpoint (options) {
options = _.defaultsDeep({}, options, DEFAULTS)
let method = options.method
let baseUrl = options.baseUrl
let url = options.url
let body = options.body
let headers = options.headers
let remainingOptions = _.omit(options, ['method', 'baseUrl', 'url', 'headers'])

method = method.toLowerCase()
headers = _.mapKeys(headers, (value, key) => key.toLowerCase())

// replace :varname with {varname} to make it RFC 6570 compatible
url = url.replace(/:(\w+)/g, '{+$1}')

// extract variable names from URL to calculate remaining variables later
const urlVariableNames = extractUrlVariableNames(url)

url = urlTemplate.parse(url).expand(remainingOptions)

if (!/^http/.test(url)) {
url = (baseUrl) + url
}

const requestOptions = remainingOptions.request
remainingOptions = _.omit(remainingOptions, _.intersection(Object.keys(options), urlVariableNames).concat(NON_PARAMETERS))

if (method === 'get' || method === 'head') {
url = addQueryParameters(url, remainingOptions)
} else {
if ('input' in remainingOptions) {
body = remainingOptions.input
} else {
body = Object.keys(remainingOptions).length ? remainingOptions : undefined
}
}

return Object.assign(requestOptions, {
method,
url,
headers,
body
})
}
110 changes: 0 additions & 110 deletions lib/error.js

This file was deleted.

Loading

0 comments on commit c2c88c0

Please sign in to comment.