install @octokit/rest
This commit is contained in:
1 parent
39d9c0de99
commit
e44c6cb357
1145 files changed
+67878
-1
No files matched your search
+22
@@ -0,0 +1,22 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2012 Cloud9 IDE, Inc. (Mike de Boer)
|
||||
Copyright (c) 2017 Octokit contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
# rest.js
|
||||
|
||||
> GitHub REST API client for Node.js
|
||||
|
||||
[](https://travis-ci.org/octokit/rest.js)
|
||||
[](https://coveralls.io/github/octokit/rest.js)
|
||||
[](https://greenkeeper.io/)
|
||||
[](https://www.npmjs.com/package/@octokit/rest)
|
||||
|
||||
## Usage
|
||||
|
||||
Install with `npm install @octokit/rest`.
|
||||
|
||||
<!-- HEADS UP: when changing the options for the constructor, make sure to also
|
||||
update the type definition templates in scripts/templates/* -->
|
||||
```js
|
||||
const octokit = require('@octokit/rest')()
|
||||
|
||||
// Compare: https://developer.github.com/v3/repos/#list-organization-repositories
|
||||
octokit.repos.getForOrg({
|
||||
org: 'octokit',
|
||||
type: 'public'
|
||||
}).then(({data}) => {
|
||||
// handle data
|
||||
})
|
||||
```
|
||||
|
||||
All available client options with default values
|
||||
|
||||
```js
|
||||
const octokit = require('@octokit/rest')({
|
||||
timeout: 0, // 0 means no request timeout
|
||||
requestMedia: 'application/vnd.github.v3+json',
|
||||
headers: {
|
||||
'user-agent': 'octokit/rest.js v1.2.3' // v1.2.3 will be current version
|
||||
},
|
||||
|
||||
// change for custom GitHub Enterprise URL
|
||||
host: 'api.github.com',
|
||||
pathPrefix: '',
|
||||
protocol: 'https',
|
||||
port: 433,
|
||||
|
||||
// advanced request options
|
||||
// see https://nodejs.org/api/http.html
|
||||
proxy: undefined,
|
||||
ca: undefined,
|
||||
rejectUnauthorized: undefined,
|
||||
family: undefined
|
||||
})
|
||||
```
|
||||
|
||||
`@octokit/rest` API docs: https://octokit.github.io/rest.js/
|
||||
GitHub v3 REST API docs: https://developer.github.com/v3/
|
||||
|
||||
## Authentication
|
||||
|
||||
Most GitHub API calls don't require authentication. Rules of thumb:
|
||||
|
||||
1. If you can see the information by visiting the site without being logged in, you don't have to be authenticated to retrieve the same information through the API.
|
||||
2. If you want to change data, you have to be authenticated.
|
||||
|
||||
```javascript
|
||||
// basic
|
||||
octokit.authenticate({
|
||||
type: 'basic',
|
||||
username: 'yourusername',
|
||||
password: 'password'
|
||||
})
|
||||
|
||||
// oauth
|
||||
octokit.authenticate({
|
||||
type: 'oauth',
|
||||
token: 'secrettoken123'
|
||||
})
|
||||
|
||||
// oauth key/secret (to get a token)
|
||||
octokit.authenticate({
|
||||
type: 'oauth',
|
||||
key: 'client_id',
|
||||
secret: 'client_secret'
|
||||
})
|
||||
|
||||
// token (https://github.com/settings/tokens)
|
||||
octokit.authenticate({
|
||||
type: 'token',
|
||||
token: 'secrettoken123'
|
||||
})
|
||||
|
||||
// GitHub app
|
||||
octokit.authenticate({
|
||||
type: 'integration',
|
||||
token: 'secrettoken123'
|
||||
})
|
||||
```
|
||||
|
||||
Note: `authenticate` is synchronous because it only sets the credentials
|
||||
for the following requests.
|
||||
|
||||
## Pagination
|
||||
|
||||
There are a few pagination-related methods:
|
||||
|
||||
- `hasNextPage(response)`
|
||||
- `hasPreviousPage(response)`
|
||||
- `hasFirstPage(response)`
|
||||
- `hasLastPage(response)`
|
||||
- `getNextPage(response)`
|
||||
- `getPreviousPage(response)`
|
||||
- `getFirstPage(response)`
|
||||
- `getLastPage(response)`
|
||||
|
||||
Usage
|
||||
|
||||
```js
|
||||
async function paginate (method) {
|
||||
let response = await method({per_page: 100})
|
||||
let {data} = response
|
||||
while (octokit.hasNextPage(response)) {
|
||||
response = await octokit.getNextPage(response)
|
||||
data = data.concat(response.data)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
paginate(octokit.repos.getAll)
|
||||
.then(data => {
|
||||
// handle all results
|
||||
})
|
||||
```
|
||||
|
||||
## DEBUG
|
||||
|
||||
Set `DEBUG=octokit:rest*` for additional debug logs.
|
||||
|
||||
## Tests
|
||||
|
||||
Run all tests
|
||||
|
||||
```bash
|
||||
$ npm test
|
||||
```
|
||||
|
||||
Or run a specific test
|
||||
|
||||
```bash
|
||||
$ ./node_modules/.bin/mocha test/test/integration/get-repository-test.js
|
||||
```
|
||||
|
||||
The examples are run as part of the tests. You can set an `EXAMPLES_GITHUB_TOKEN` environment
|
||||
variable (or set it in a `.env` file) to avoid running against GitHub's rate limit.
|
||||
|
||||
## Contributing
|
||||
|
||||
We would love you to contribute to `@octokit/rest`, pull requests are very welcomed!
|
||||
Please see [CONTRIBUTING.md](CONTRIBUTING.md) for more information.
|
||||
|
||||
## Credits
|
||||
|
||||
`@octokit/rest` was originally created as [`node-github`](https://www.npmjs.com/package/github)
|
||||
in 2012 by Mike de Boer from Cloud9 IDE, Inc.
|
||||
It was adopted and renamed by GitHub in 2017
|
||||
|
||||
## LICENSE
|
||||
|
||||
[MIT](LICENSE)
|
||||
+3475
File diff suppressed because it is too large.
Load diff
+31
@@ -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
|
||||
}
|
||||
+3441
File diff suppressed because it is too large.
Load diff
+13
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
})
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
module.exports = parseOptions
|
||||
|
||||
const _ = require('lodash')
|
||||
|
||||
const DEFAULTS = require('./defaults')
|
||||
const OPTION_NAMES = [
|
||||
'timeout',
|
||||
'host',
|
||||
'pathPrefix',
|
||||
'protocol',
|
||||
'port',
|
||||
'proxy',
|
||||
'ca',
|
||||
'headers',
|
||||
'requestMedia',
|
||||
'rejectUnauthorized',
|
||||
'family'
|
||||
]
|
||||
|
||||
function parseOptions (options) {
|
||||
if (!options) {
|
||||
options = {}
|
||||
}
|
||||
|
||||
if ('followRedirects' in options) {
|
||||
console.warn('DEPRECATED: followRedirects option is no longer supported. All redirects are followed correctly')
|
||||
}
|
||||
|
||||
if ('Promise' in options) {
|
||||
console.warn('DEPRECATED: Promise option is no longer supported. The native Promise API is used')
|
||||
}
|
||||
|
||||
options = _.defaults(_.pick(options, OPTION_NAMES), DEFAULTS)
|
||||
|
||||
const defaults = {
|
||||
headers: options.headers,
|
||||
request: {
|
||||
ca: options.ca,
|
||||
family: options.family,
|
||||
proxy: options.proxy,
|
||||
rejectUnauthorized: options.rejectUnauthorized,
|
||||
timeout: options.timeout
|
||||
}
|
||||
}
|
||||
|
||||
defaults.baseUrl = `${options.protocol}://${options.host}`
|
||||
|
||||
if (options.port) {
|
||||
defaults.baseUrl += `:${options.port}`
|
||||
}
|
||||
|
||||
// Check if a prefix is passed in the options and strip any leading or trailing slashes from it.
|
||||
if (options.pathPrefix) {
|
||||
defaults.baseUrl += '/' + options.pathPrefix.replace(/(^[/]+|[/]+$)/g, '')
|
||||
}
|
||||
|
||||
return defaults
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
# `@octokit/plugins/*`
|
||||
|
||||
---
|
||||
|
||||
# ⚠️ Plugins are currently experimental. APIs can change at any time.
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const octokit = require('@octokit/rest')()
|
||||
|
||||
function myPlugin (octokit) {
|
||||
octokit.myMethod = function () {
|
||||
// ...
|
||||
}
|
||||
octokit.hook.before('request', (options) => {
|
||||
// change options or cancel request.
|
||||
// return promise for async methods
|
||||
})
|
||||
octokit.hook.after('request', (result, options) => {
|
||||
// ...
|
||||
})
|
||||
}
|
||||
|
||||
octokit.plugin(myPlugin)
|
||||
|
||||
octokit.myMethod()
|
||||
octokit.request({url: '/'}) // runs before/after hooks defined above
|
||||
```
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
module.exports = authenticate
|
||||
|
||||
function authenticate (state, options) {
|
||||
if (!options) {
|
||||
state.auth = false
|
||||
return
|
||||
}
|
||||
|
||||
switch (options.type) {
|
||||
case 'basic':
|
||||
if (!options.username || !options.password) {
|
||||
throw new Error('Basic authentication requires both a username and password to be set')
|
||||
}
|
||||
break
|
||||
|
||||
case 'oauth':
|
||||
if (!options.token && !(options.key && options.secret)) {
|
||||
throw new Error('OAuth2 authentication requires a token or key & secret to be set')
|
||||
}
|
||||
break
|
||||
|
||||
case 'token':
|
||||
case 'integration':
|
||||
if (!options.token) {
|
||||
throw new Error('Token authentication requires a token to be set')
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
throw new Error("Invalid authentication type, must be 'basic', 'integration', or 'oauth'")
|
||||
}
|
||||
|
||||
state.auth = options
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
module.exports = authenticationBeforeRequest
|
||||
|
||||
function authenticationBeforeRequest (state, options) {
|
||||
if (!state.auth.type) {
|
||||
return
|
||||
}
|
||||
|
||||
if (state.auth.type === 'basic') {
|
||||
const hash = Buffer.from(
|
||||
`${state.auth.username}:${state.auth.password}`, 'ascii'
|
||||
).toString('base64')
|
||||
options.headers['authorization'] = `Basic ${hash}`
|
||||
return
|
||||
}
|
||||
|
||||
if (state.auth.type === 'token') {
|
||||
options.headers['authorization'] = `token ${state.auth.token}`
|
||||
return
|
||||
}
|
||||
|
||||
if (state.auth.type === 'integration') {
|
||||
options.headers['authorization'] = `Bearer ${state.auth.token}`
|
||||
options.headers['accept'] = 'application/vnd.github.machine-man-preview+json'
|
||||
return
|
||||
}
|
||||
|
||||
options.url += options.url.indexOf('?') === -1 ? '?' : '&'
|
||||
|
||||
if (state.auth.token) {
|
||||
options.url += `access_token=${encodeURIComponent(state.auth.token)}`
|
||||
return
|
||||
}
|
||||
|
||||
const key = encodeURIComponent(state.auth.key)
|
||||
const secret = encodeURIComponent(state.auth.secret)
|
||||
options.url += `client_id=${key}&client_secret=${secret}`
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
module.exports = authenticationPlugin
|
||||
|
||||
const authenticate = require('./authenticate')
|
||||
const beforeRequest = require('./before-request')
|
||||
|
||||
function authenticationPlugin (octokit) {
|
||||
const state = {
|
||||
auth: false
|
||||
}
|
||||
octokit.authenticate = authenticate.bind(null, state)
|
||||
octokit.hook.before('request', beforeRequest.bind(null, state))
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
module.exports = deprecate
|
||||
|
||||
function deprecate (func, message) {
|
||||
return function () {
|
||||
const caller = (new Error()).stack.split('\n')[2]
|
||||
console.warn('DEPRECATED: ' + message)
|
||||
console.warn(caller)
|
||||
|
||||
return func.apply(null, arguments)
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
module.exports = apiPlugin
|
||||
|
||||
const _ = require('lodash')
|
||||
|
||||
const method = require('./method')
|
||||
const deprecate = require('./deprecate')
|
||||
|
||||
const ENDPOINT_DEFAULTS = require('../../routes.json')
|
||||
|
||||
function apiPlugin (octokit) {
|
||||
Object.keys(ENDPOINT_DEFAULTS).forEach(namespaceName => {
|
||||
octokit[namespaceName] = {}
|
||||
|
||||
Object.keys(ENDPOINT_DEFAULTS[namespaceName]).forEach(apiName => {
|
||||
const apiOptions = ENDPOINT_DEFAULTS[namespaceName][apiName]
|
||||
const endpointDefaults = _.pick(apiOptions, ['method', 'url', 'headers', 'request'])
|
||||
|
||||
octokit[namespaceName][apiName] = method.bind(null, octokit, endpointDefaults, apiOptions.params)
|
||||
|
||||
// log deprecation warning for APIs flagged as deprecated
|
||||
if (apiOptions.deprecated) {
|
||||
octokit[namespaceName][apiName] = deprecate(
|
||||
octokit[namespaceName][apiName],
|
||||
apiOptions.deprecated
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
module.exports = apiMethod
|
||||
|
||||
const defaultsDeep = require('lodash/defaultsDeep')
|
||||
|
||||
const validate = require('./validate')
|
||||
|
||||
function apiMethod (octokit, endpointDefaults, endpointParams, options, callback) {
|
||||
const endpointOptions = defaultsDeep(options, endpointDefaults)
|
||||
|
||||
const promise = Promise.resolve(endpointOptions)
|
||||
.then(validate.bind(null, endpointParams))
|
||||
.then(octokit.request)
|
||||
|
||||
if (callback) {
|
||||
promise.then(callback.bind(null, null), callback)
|
||||
return
|
||||
}
|
||||
|
||||
return promise
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = validate
|
||||
|
||||
const set = require('lodash/set')
|
||||
const HttpError = require('../../request/http-error')
|
||||
|
||||
function validate (endpointParams, options) {
|
||||
Object.keys(endpointParams).forEach(parameterName => {
|
||||
const parameter = endpointParams[parameterName]
|
||||
const expectedType = parameter.type
|
||||
let value = options[parameterName]
|
||||
|
||||
const paramIsPresent = parameterName in options
|
||||
const paramIsNull = value === null
|
||||
|
||||
if (!parameter.required && !paramIsPresent) {
|
||||
return
|
||||
}
|
||||
|
||||
if (parameter['allow-null'] === true && paramIsNull) {
|
||||
return
|
||||
}
|
||||
|
||||
if ((parameter.required && !paramIsPresent) ||
|
||||
(parameter['allow-null'] === false && paramIsNull)) {
|
||||
throw new HttpError(`Empty value for parameter '${parameterName}': ${value}`, 400)
|
||||
}
|
||||
|
||||
if (parameter.enum) {
|
||||
if (parameter.enum.indexOf(value) === -1) {
|
||||
throw new HttpError(`Invalid value for parameter '${parameterName}': ${value}`, 400)
|
||||
}
|
||||
}
|
||||
|
||||
if (parameter.validation) {
|
||||
const regex = new RegExp(parameter.validation)
|
||||
if (!regex.test(value)) {
|
||||
throw new HttpError(`Invalid value for parameter '${parameterName}': ${value}`, 400)
|
||||
}
|
||||
}
|
||||
|
||||
if (expectedType === 'number') {
|
||||
value = parseInt(value, 10)
|
||||
if (isNaN(value)) {
|
||||
throw new HttpError(`Invalid value for parameter '${parameterName}': ${options[parameterName]} is NaN`, 400)
|
||||
}
|
||||
}
|
||||
|
||||
if (expectedType === 'json' && typeof value === 'string') {
|
||||
try {
|
||||
value = JSON.parse(value)
|
||||
} catch (exception) {
|
||||
throw new HttpError(`JSON parse error of value for parameter '${parameterName}': ${value}`, 400)
|
||||
}
|
||||
}
|
||||
|
||||
set(options, parameter.mapTo || parameterName, value)
|
||||
})
|
||||
|
||||
return options
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
module.exports = getFirstPage
|
||||
|
||||
const getPage = require('./get-page')
|
||||
|
||||
function getFirstPage (octokit, link, headers, callback) {
|
||||
return getPage(octokit, link, 'first', headers, callback)
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
module.exports = getLastPage
|
||||
|
||||
const getPage = require('./get-page')
|
||||
|
||||
function getLastPage (octokit, link, headers, callback) {
|
||||
return getPage(octokit, link, 'last', headers, callback)
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
module.exports = getNextPage
|
||||
|
||||
const getPage = require('./get-page')
|
||||
|
||||
function getNextPage (octokit, link, headers, callback) {
|
||||
return getPage(octokit, link, 'next', headers, callback)
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
module.exports = getPageLinks
|
||||
|
||||
function getPageLinks (link) {
|
||||
link = link.link || link.meta.link || ''
|
||||
|
||||
const links = {}
|
||||
|
||||
// link format:
|
||||
// '<https://api.github.com/users/aseemk/followers?page=2>; rel="next", <https://api.github.com/users/aseemk/followers?page=2>; rel="last"'
|
||||
link.replace(/<([^>]*)>;\s*rel="([\w]*)"/g, (m, uri, type) => {
|
||||
links[type] = uri
|
||||
})
|
||||
|
||||
return links
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
module.exports = getPage
|
||||
|
||||
const HttpError = require('../../request/http-error')
|
||||
const getPageLinks = require('./get-page-links')
|
||||
|
||||
function getPage (octokit, link, which, headers, callback) {
|
||||
if (typeof headers === 'function') {
|
||||
callback = headers
|
||||
headers = null
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
const requestOptions = {
|
||||
url,
|
||||
headers: applyAcceptHeader(link, headers)
|
||||
}
|
||||
|
||||
const promise = octokit.request(requestOptions)
|
||||
|
||||
if (callback) {
|
||||
promise.then(callback.bind(null, null), callback)
|
||||
return
|
||||
}
|
||||
|
||||
return promise
|
||||
}
|
||||
|
||||
function applyAcceptHeader (res, headers) {
|
||||
const previous = res.meta && res.meta['x-github-media-type']
|
||||
|
||||
if (!previous || (headers && headers.accept)) {
|
||||
return headers
|
||||
}
|
||||
headers = headers || {}
|
||||
headers.accept = `application/vnd.${previous.replace('; format=', '+')}`
|
||||
return headers
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
module.exports = getPreviousPage
|
||||
|
||||
const getPage = require('./get-page')
|
||||
|
||||
function getPreviousPage (octokit, link, headers, callback) {
|
||||
return getPage(octokit, link, 'prev', headers, callback)
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
module.exports = hasFirstPage
|
||||
|
||||
const getPageLinks = require('./get-page-links')
|
||||
|
||||
function hasFirstPage (link) {
|
||||
return getPageLinks(link).first
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
module.exports = hasLastPage
|
||||
|
||||
const getPageLinks = require('./get-page-links')
|
||||
|
||||
function hasLastPage (link) {
|
||||
return getPageLinks(link).last
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
module.exports = hasNextPage
|
||||
|
||||
const getPageLinks = require('./get-page-links')
|
||||
|
||||
function hasNextPage (link) {
|
||||
return getPageLinks(link).next
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
module.exports = hasPreviousPage
|
||||
|
||||
const getPageLinks = require('./get-page-links')
|
||||
|
||||
function hasPreviousPage (link) {
|
||||
return getPageLinks(link).prev
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
module.exports = paginationPlugin
|
||||
|
||||
function paginationPlugin (octokit) {
|
||||
octokit.getFirstPage = require('./get-first-page').bind(null, octokit)
|
||||
octokit.getLastPage = require('./get-last-page').bind(null, octokit)
|
||||
octokit.getNextPage = require('./get-next-page').bind(null, octokit)
|
||||
octokit.getPreviousPage = require('./get-previous-page').bind(null, octokit)
|
||||
octokit.hasFirstPage = require('./has-first-page')
|
||||
octokit.hasLastPage = require('./has-last-page')
|
||||
octokit.hasNextPage = require('./has-next-page')
|
||||
octokit.hasPreviousPage = require('./has-previous-page')
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
[back to `@octokit/rest`]('../..')
|
||||
|
||||
# `@octokit/rest/request`
|
||||
|
||||
> 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 octokitRestRequest = require('@octokit/rest/lib/request')
|
||||
|
||||
octokitRestRequest({
|
||||
// request options
|
||||
method: 'GET',
|
||||
url: '/orgs/:org/repos',
|
||||
// parameters
|
||||
org: 'octokit',
|
||||
type: 'private'
|
||||
}) // returns promise
|
||||
```
|
||||
|
||||
Sends a `GET` request to https://api.github.com/orgs/octokit/repos?type=private&per_page=20&page=2
|
||||
with `user-agent` and `accept` headers set.
|
||||
|
||||
It accepts the same options and has the same defaults as [`@octokit/rest/endpoint`](../endpoint)
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
'use strict'
|
||||
|
||||
const STATUS_CODES = {
|
||||
304: 'Not Modified', // See PR #673 (https://github.com/octokit/rest.js/pull/673)
|
||||
400: 'Bad Request',
|
||||
404: 'Not Found',
|
||||
500: 'Internal Server Error',
|
||||
504: 'Gateway Timeout'
|
||||
}
|
||||
|
||||
module.exports = class HttpError extends Error {
|
||||
constructor (message, code, headers) {
|
||||
super(message)
|
||||
Error.captureStackTrace(this, this.constructor)
|
||||
this.name = 'HttpError'
|
||||
this.code = code
|
||||
this.status = STATUS_CODES[code]
|
||||
this.headers = headers
|
||||
}
|
||||
|
||||
toString () {
|
||||
return this.message
|
||||
}
|
||||
|
||||
toJSON () {
|
||||
return {
|
||||
code: this.code,
|
||||
status: this.status,
|
||||
message: this.message
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
module.exports = restRequest
|
||||
|
||||
const restEndpoint = require('../endpoint')
|
||||
const request = require('./request')
|
||||
|
||||
function restRequest (endpointOptions) {
|
||||
const requestOptions = restEndpoint(endpointOptions)
|
||||
return request(requestOptions)
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = httpRequest
|
||||
|
||||
const url = require('url')
|
||||
const http = require('http')
|
||||
const https = require('https')
|
||||
|
||||
const _ = require('lodash')
|
||||
const debug = require('debug')('octokit:rest')
|
||||
const isArrayBuffer = require('is-array-buffer')
|
||||
const isStream = require('is-stream')
|
||||
|
||||
const HttpError = require('./http-error')
|
||||
|
||||
function httpRequest (requestOptions) {
|
||||
requestOptions = Object.assign(
|
||||
url.parse(requestOptions.url),
|
||||
_.pick(requestOptions, 'method', 'body', 'headers', 'ca', 'family', 'proxy', 'rejectUnauthorized', 'timeout')
|
||||
)
|
||||
debug('REQUEST:', requestOptions)
|
||||
|
||||
// calculate content length unless body is a stream, in which case the
|
||||
// content length is already set per option
|
||||
if (requestOptions.body && !isStream(requestOptions.body)) {
|
||||
// stringify body unless it’s an ArrayBuffer
|
||||
if (!isArrayBuffer(requestOptions.body) && !Buffer.isBuffer(requestOptions.body) && typeof requestOptions.body !== 'string') {
|
||||
requestOptions.body = JSON.stringify(requestOptions.body)
|
||||
}
|
||||
|
||||
_.defaults(requestOptions.headers, {
|
||||
'content-type': 'application/json; charset=utf-8',
|
||||
'content-length': Buffer.byteLength(requestOptions.body, 'utf8')
|
||||
})
|
||||
}
|
||||
|
||||
// GitHub expects "content-length: 0" header for PUT/PATCH requests without body
|
||||
if (['patch', 'put'].indexOf(requestOptions.method) >= 0 &&
|
||||
!requestOptions.headers['content-length']) {
|
||||
requestOptions.headers['content-length'] = 0
|
||||
}
|
||||
|
||||
if ('content-length' in requestOptions.headers) {
|
||||
requestOptions.headers['content-length'] = parseInt(requestOptions.headers['content-length'], 10)
|
||||
}
|
||||
|
||||
const reqModule = requestOptions.protocol === 'http:' ? http : https
|
||||
delete requestOptions.protocol
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = reqModule.request(requestOptions, (response) => {
|
||||
debug('STATUS: ' + response.statusCode)
|
||||
debug('HEADERS: ' + JSON.stringify(response.headers))
|
||||
|
||||
response.setEncoding('utf8')
|
||||
let data = ''
|
||||
response.on('data', (chunk) => {
|
||||
data += chunk
|
||||
})
|
||||
|
||||
/* istanbul ignore next */
|
||||
response.on('error', (error) => {
|
||||
reject(new HttpError(error.message, 500))
|
||||
})
|
||||
response.on('end', () => {
|
||||
if (response.statusCode !== 304 && response.statusCode >= 301 && response.statusCode <= 307) {
|
||||
requestOptions.url = response.headers.location
|
||||
httpRequest(requestOptions).then(resolve, reject)
|
||||
return
|
||||
}
|
||||
|
||||
if (response.statusCode === 304 || response.statusCode >= 400 || response.statusCode < 10) {
|
||||
reject(new HttpError(data, response.statusCode, response.headers))
|
||||
return
|
||||
}
|
||||
|
||||
const contentType = response.headers['content-type']
|
||||
if (contentType && contentType.indexOf('application/json') !== -1) {
|
||||
data = data && JSON.parse(data)
|
||||
}
|
||||
|
||||
resolve({
|
||||
meta: response.headers,
|
||||
data
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
let aborted
|
||||
request.on('error', (error) => {
|
||||
if (aborted) return
|
||||
debug('REQUEST ERROR: ' + error.message)
|
||||
reject(new HttpError(error.message, 500))
|
||||
})
|
||||
|
||||
if (requestOptions.timeout) {
|
||||
request.setTimeout(requestOptions.timeout)
|
||||
}
|
||||
request.on('timeout', () => {
|
||||
debug('REQUEST ERROR: timed out')
|
||||
request.abort()
|
||||
aborted = true
|
||||
reject(new HttpError('Request timeout', 504))
|
||||
})
|
||||
|
||||
if (requestOptions.body) {
|
||||
if (isStream(requestOptions.body)) {
|
||||
return requestOptions.body.pipe(request)
|
||||
}
|
||||
|
||||
request.write(Buffer.from(requestOptions.body))
|
||||
}
|
||||
|
||||
request.end()
|
||||
})
|
||||
}
|
||||
+10630
File diff suppressed because it is too large.
Load diff
+140
@@ -0,0 +1,140 @@
|
||||
{
|
||||
"_from": "@octokit/rest",
|
||||
"_id": "@octokit/rest@14.0.9",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-irP9phKfTXEZIcW2R+VNCtGHZJrXMWmSYp6RRfFn4BtAqtDRXF5z9JxCEQlAhNBf6X1koNi5k49tIAAAEJNlVQ==",
|
||||
"_location": "/@octokit/rest",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "tag",
|
||||
"registry": true,
|
||||
"raw": "@octokit/rest",
|
||||
"name": "@octokit/rest",
|
||||
"escapedName": "@octokit%2frest",
|
||||
"scope": "@octokit",
|
||||
"rawSpec": "",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "latest"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-14.0.9.tgz",
|
||||
"_shasum": "d5e0a00dcb78901dd7b2ef852acfc0aea7c479ef",
|
||||
"_spec": "@octokit/rest",
|
||||
"_where": "C:\\Users\\Luis\\source\\repos\\AAWebPlatform",
|
||||
"apidoc": {
|
||||
"template": {
|
||||
"withCompare": false
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "Gregor Martynus",
|
||||
"url": "https://github.com/gr2m"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/octokit/rest.js/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Mike de Boer",
|
||||
"email": "info@mikedeboer.nl"
|
||||
},
|
||||
{
|
||||
"name": "Fabian Jakobs",
|
||||
"email": "fabian@c9.io"
|
||||
},
|
||||
{
|
||||
"name": "Joe Gallo",
|
||||
"email": "joe@brassafrax.com"
|
||||
},
|
||||
{
|
||||
"name": "Gregor Martynus",
|
||||
"url": "https://github.com/gr2m"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"before-after-hook": "^1.1.0",
|
||||
"debug": "^3.1.0",
|
||||
"is-array-buffer": "^1.0.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"lodash": "^4.17.4",
|
||||
"url-template": "^2.0.8"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "GitHub REST API client for Node.js",
|
||||
"devDependencies": {
|
||||
"@octokit/fixtures": "^6.0.0",
|
||||
"apidoc": "^0.17.6",
|
||||
"chai": "^4.1.2",
|
||||
"coveralls": "^3.0.0",
|
||||
"dotenv": "^5.0.0",
|
||||
"gh-pages-with-token": "^1.0.0",
|
||||
"glob": "^7.1.2",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mocha": "^5.0.0",
|
||||
"mustache": "^2.2.1",
|
||||
"nock": "^9.1.0",
|
||||
"npm-run-all": "^4.1.1",
|
||||
"nyc": "^11.2.1",
|
||||
"proxyquire": "^1.8.0",
|
||||
"semantic-release": "^12.2.2",
|
||||
"simple-mock": "^0.8.0",
|
||||
"standard": "^10.0.3",
|
||||
"standard-markdown": "^4.0.2",
|
||||
"string-to-arraybuffer": "^1.0.0",
|
||||
"typescript": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"index.js.flow",
|
||||
"lib"
|
||||
],
|
||||
"homepage": "https://github.com/octokit/rest.js#readme",
|
||||
"keywords": [
|
||||
"octokit",
|
||||
"github",
|
||||
"rest",
|
||||
"api-client"
|
||||
],
|
||||
"license": "MIT",
|
||||
"name": "@octokit/rest",
|
||||
"nyc": {
|
||||
"ignore": [
|
||||
"examples",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/octokit/rest.js.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm-run-all build:*",
|
||||
"build:docs": "node scripts/generate-api-docs",
|
||||
"build:flow": "node scripts/generate-flow-types",
|
||||
"build:ts": "node scripts/generate-typescript-types",
|
||||
"coverage": "nyc report --reporter=html && open coverage/index.html",
|
||||
"coverage:upload": "nyc report --reporter=text-lcov | coveralls",
|
||||
"deploy-docs": "gh-pages-with-token -d doc",
|
||||
"postbuild:docs": "apidoc -i doc/ -o doc/",
|
||||
"prebuild:docs": "mkdirp doc/",
|
||||
"pretest": "standard && standard-markdown",
|
||||
"prevalidate:ts": "npm run -s build:ts",
|
||||
"semantic-release": "semantic-release",
|
||||
"test": "nyc mocha 'test/**/*-test.js'",
|
||||
"test:examples": "node test/examples.js",
|
||||
"validate:ts": "tsc --target es6 index.d.ts"
|
||||
},
|
||||
"types": "index.d.ts",
|
||||
"version": "14.0.9"
|
||||
}
|
||||
Reference in new issue
Block a user