1 | # rest.js
|
2 |
|
3 | > GitHub REST API client for JavaScript
|
4 |
|
5 | [![@latest](https://img.shields.io/npm/v/@octokit/rest.svg)](https://www.npmjs.com/package/@octokit/rest)
|
6 | [![Build Status](https://travis-ci.org/octokit/rest.js.svg?branch=master)](https://travis-ci.org/octokit/rest.js)
|
7 | [![Coverage Status](https://coveralls.io/repos/github/octokit/rest.js/badge.svg)](https://coveralls.io/github/octokit/rest.js)
|
8 | [![Greenkeeper](https://badges.greenkeeper.io/octokit/rest.js.svg)](https://greenkeeper.io/)
|
9 |
|
10 |
|
11 |
|
12 | - [Usage](#usage)
|
13 | * [Node](#node)
|
14 | * [Browser](#browser)
|
15 | * [Client options](#client-options)
|
16 | - [Authentication](#authentication)
|
17 | - [API docs](#api-docs)
|
18 | - [API Previews](#api-previews)
|
19 | - [Custom requests](#custom-requests)
|
20 | - [Pagination](#pagination)
|
21 | - [Hooks](#hooks)
|
22 | - [Plugins](#plugins)
|
23 | - [Register custom endpoint methods](#register-custom-endpoint-methods)
|
24 | - [Throttling](#throttling)
|
25 | - [Automatic retries](#automatic-retries)
|
26 | - [Logging](#logging)
|
27 | - [Debug](#debug)
|
28 | - [Contributing](#contributing)
|
29 | - [Credits](#credits)
|
30 | - [LICENSE](#license)
|
31 |
|
32 |
|
33 |
|
34 | ## Usage
|
35 |
|
36 | ### Node
|
37 |
|
38 | Install with `npm install @octokit/rest`.
|
39 |
|
40 | ```js
|
41 | const Octokit = require('@octokit/rest')
|
42 | const octokit = new Octokit ()
|
43 |
|
44 | // Compare: https://developer.github.com/v3/repos/#list-organization-repositories
|
45 | octokit.repos.listForOrg({
|
46 | org: 'octokit',
|
47 | type: 'public'
|
48 | }).then(({ data, status, headers }) => {
|
49 | // handle data
|
50 | })
|
51 | ```
|
52 |
|
53 | ### Browser
|
54 |
|
55 | 1. Download `octokit-rest.min.js` from the latest release: https://github.com/octokit/rest.js/releases
|
56 |
|
57 | 2. Load it as script into your web application:
|
58 |
|
59 | ```html
|
60 | <script src="octokit-rest.min.js"></script>
|
61 | ```
|
62 |
|
63 | 3. Initialize `octokit`
|
64 |
|
65 | ```js
|
66 | const octokit = new Octokit()
|
67 |
|
68 | // Compare: https://developer.github.com/v3/repos/#list-organization-repositories
|
69 | octokit.repos.listForOrg({
|
70 | org: 'octokit',
|
71 | type: 'public'
|
72 | }).then(({data, headers, status}) => {
|
73 | // handle data
|
74 | })
|
75 | ```
|
76 |
|
77 | ### Client options
|
78 |
|
79 | All available client options with default values
|
80 |
|
81 | ```js
|
82 | const Octokit = require('@octokit/rest')
|
83 | const octokit = new Octokit({
|
84 | // see "Authentication" section below
|
85 | auth: undefined,
|
86 |
|
87 | // setting a user agent is required: https://developer.github.com/v3/#user-agent-required
|
88 | // v1.2.3 will be current @octokit/rest version
|
89 | userAgent: 'octokit/rest.js v1.2.3',
|
90 |
|
91 | // add list of previews you’d like to enable globally,
|
92 | // see https://developer.github.com/v3/previews/.
|
93 | // Example: ['jean-grey-preview', 'symmetra-preview']
|
94 | previews: [],
|
95 |
|
96 | // set custom URL for on-premise GitHub Enterprise installations
|
97 | baseUrl: 'https://api.github.com',
|
98 |
|
99 | // pass custom methods for debug, info, warn and error
|
100 | log: {
|
101 | debug: () => {},
|
102 | info: () => {},
|
103 | warn: console.warn,
|
104 | error: console.error
|
105 | },
|
106 |
|
107 | request: {
|
108 | // Node.js only: advanced request options can be passed as http(s) agent,
|
109 | // such as custom SSL certificate or proxy settings.
|
110 | // See https://nodejs.org/api/http.html#http_class_http_agent
|
111 | agent: undefined,
|
112 |
|
113 | // request timeout in ms. 0 means no timeout
|
114 | timeout: 0
|
115 | }
|
116 | })
|
117 | ```
|
118 |
|
119 | ## Authentication
|
120 |
|
121 | Most GitHub API calls don't require authentication. Rules of thumb:
|
122 |
|
123 | 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.
|
124 | 2. If you want to change data, you have to be authenticated.
|
125 |
|
126 | To enable authenticated requests, pass an `auth` option to the Octokit constructor:
|
127 |
|
128 | ```js
|
129 | const clientWithAuth = new Octokit({
|
130 | auth: 'token secret123'
|
131 | })
|
132 | ```
|
133 |
|
134 | The `auth` option can be
|
135 |
|
136 | 1. A string
|
137 |
|
138 | The value will be passed as value for the `Authorization` header,
|
139 | see [authentication](https://developer.github.com/v3/#authentication).
|
140 |
|
141 | ```js
|
142 | new Octokit({
|
143 | auth: 'token secret123'
|
144 | })
|
145 | ```
|
146 |
|
147 | Use this for
|
148 |
|
149 | - personal access tokens
|
150 | - OAuth access tokens
|
151 | - GitHub App bearer tokens
|
152 | - GitHub App installation tokens
|
153 |
|
154 | 2. As object with the properties `username`, `password`, `on2fa`.
|
155 |
|
156 | `on2fa` is an asynchronous function that must resolve with two-factor
|
157 | authentication code sent to the user.
|
158 |
|
159 | ```js
|
160 | new Octokit({
|
161 | auth: {
|
162 | username: 'octocat',
|
163 | password: 'secret',
|
164 | async on2fa () {
|
165 | // example: ask the user
|
166 | return prompt('Two-factor authentication Code:')
|
167 | }
|
168 | }
|
169 | })
|
170 | ```
|
171 |
|
172 | 3. An object with the properties `clientId` and `clientSecret`
|
173 |
|
174 | OAuth applications can authenticate using their `clientId` and `clientSecret`
|
175 | in order to [increase the unauthenticated rate limit](https://developer.github.com/v3/#increasing-the-unauthenticated-rate-limit-for-oauth-applications).
|
176 |
|
177 | 4. A function
|
178 |
|
179 | Must resolve with a string which then will be passed as value for the
|
180 | `Authorization` header. The function will be called before each request and
|
181 | can be asynchronous.
|
182 |
|
183 | ```js
|
184 | new Octokit({
|
185 | auth () {
|
186 | return 'token secret123'
|
187 | }
|
188 | })
|
189 | ```
|
190 |
|
191 | This is useful for GitHub apps, as installations need to renew their tokens each hour.
|
192 | Here is an example on how to implement authentication for GitHub Apps
|
193 |
|
194 | ```js
|
195 | const App = require('@octokit/app')
|
196 | const Octokit = require('@octokit/rest')
|
197 |
|
198 | const app = new App({ id: process.env.APP_ID, privateKey: process.env.PRIVATE_KEY })
|
199 | const octokit = new Octokit({
|
200 | async auth () {
|
201 | const installationAccessToken = await app.getInstallationAccessToken({
|
202 | installationId: process.env.INSTALLATION_ID
|
203 | });
|
204 | return `token ${installationAccessToken}`;
|
205 | }
|
206 | })
|
207 | ```
|
208 |
|
209 | See also: https://github.com/octokit/app.js#authenticating-as-an-installation.
|
210 |
|
211 | ## API docs
|
212 |
|
213 | Find all APIs documented at https://octokit.github.io/rest.js/.
|
214 |
|
215 | ## API Previews
|
216 |
|
217 | To enable any of [GitHub’s API Previews](https://developer.github.com/v3/previews/),
|
218 | pass the `previews` option to the GitHub constructor
|
219 |
|
220 | ```js
|
221 | const octokit = new Octokit({
|
222 | previews: [
|
223 | 'mercy-preview'
|
224 | ]
|
225 | })
|
226 | ```
|
227 |
|
228 | If you want to enable a preview for a single request, pass it as as the `accept` header
|
229 |
|
230 | ```js
|
231 | const { data: { topics } } = await octokit.repos.get({
|
232 | owner: 'octokit',
|
233 | repo: 'rest.js',
|
234 | headers: {
|
235 | accept: 'application/vnd.github.mercy-preview+json'
|
236 | }
|
237 | })
|
238 | ```
|
239 |
|
240 | Multiple preview headers can be combined by separating them with commas
|
241 |
|
242 | ```js
|
243 | const { data: { topics, codeOfConduct } } = await octokit.repos.get({
|
244 | owner: 'octokit',
|
245 | repo: 'rest.js',
|
246 | headers: {
|
247 | accept: 'application/vnd.github.mercy-preview+json,application/vnd.github.scarlet-witch-preview+json'
|
248 | }
|
249 | })
|
250 | ```
|
251 |
|
252 | ## Custom requests
|
253 |
|
254 | To send custom requests you can use the lower-level `octokit.request()` method
|
255 |
|
256 | ```js
|
257 | octokit.request('GET /')
|
258 | ```
|
259 |
|
260 | The `baseUrl`, headers and other defaults are already set. For more information
|
261 | on the `octokit.request()` API see [`@octokit/request`](https://github.com/octokit/request.js/)
|
262 |
|
263 | All the endpoint methods such as `octokit.repos.get()` are aliases of `octokit.request()`
|
264 | with pre-bound default options. So you can use the `@octokit/request` API to
|
265 | get the default options or get generic request option to use with your preferred
|
266 | request library.
|
267 |
|
268 | ```js
|
269 | const defaultOptions = octokit.repos.get.endpoint.DEFAULTS
|
270 | const requestOptions = octokit.repos.get.endpoint()
|
271 | ```
|
272 |
|
273 | ## Pagination
|
274 |
|
275 | All endpoint methods starting with `.list*` do not return all responses at once but instead return the first 30 items by default, see also [GitHub’s REST API pagination documentation](https://developer.github.com/v3/#pagination).
|
276 |
|
277 | To automatically receive all results across all pages, you can use the `octokit.paginate()` method:
|
278 |
|
279 | ```js
|
280 | octokit.paginate('GET /repos/:owner/:repo/issues', { owner: 'octokit', repo: 'rest.js' })
|
281 | .then(issues => {
|
282 | // issues is an array of all issue objects
|
283 | })
|
284 | ```
|
285 |
|
286 | `octokit.paginate()` accepts the same options as [`octokit.request()`](#customrequests). You can optionally pass an additional function to map the results from each response. The map must return a new value, usually an array with mapped data.
|
287 |
|
288 | ```js
|
289 | octokit.paginate('GET /repos/:owner/:repo/issues', { owner: 'octokit', repo: 'rest.js' }, response => response.data.map(issue => issue.title))
|
290 | .then(issueTitles => {
|
291 | // issueTitles is now an array with the titles only
|
292 | })
|
293 | ```
|
294 |
|
295 | To stop paginating early, you can call the `done()` function passed as 2nd argument to the response map function. Note that you still have to return the value you want to map the response to, otherwise the last response will be mapped to undefined.
|
296 |
|
297 | ```js
|
298 | octokit.paginate('GET /organizations', (response, done) => {
|
299 | if (response.data.find(issues => issue.body.includes('something'))) {
|
300 | done()
|
301 | }
|
302 | return response.data
|
303 | })
|
304 | ```
|
305 |
|
306 | To paginate responses for one of the registered endpoint methods such as `octokit.issues.listForRepo()` you can use the [`.endpoint.merge()`](https://github.com/octokit/endpoint.js#endpointmerge) method registered for all endpoint methods:
|
307 |
|
308 | ```js
|
309 | const options = octokit.issues.listForRepo.endpoint.merge({ owner: 'octokit', repo: 'rest.js' })
|
310 | octokit.paginate(options)
|
311 | .then(issues => {
|
312 | // issues is an array of all issue objects
|
313 | })
|
314 | ```
|
315 |
|
316 | If your runtime environment supports async iterators (such as Node 10+), you can iterate through each response
|
317 |
|
318 | ```js
|
319 | for await (const response of octokit.paginate.iterator(options)) {
|
320 | // do whatever you want with each response, break out of the loop, etc.
|
321 | }
|
322 | ```
|
323 |
|
324 | `octokit.paginate.iterator()` accepts the same options as `octokit.paginate()`.
|
325 |
|
326 | ## Hooks
|
327 |
|
328 | You can customize Octokit’s request lifecycle with hooks. Available methods are
|
329 |
|
330 | ```js
|
331 | octokit.hook.before('request', async (options) => {
|
332 | validate(options)
|
333 | })
|
334 | octokit.hook.after('request', async (response, options) => {
|
335 | console.log(`${options.method} ${options.url}: ${response.status}`)
|
336 | })
|
337 | octokit.hook.error('request', async (error, options) => {
|
338 | if (error.status === 304) {
|
339 | return findInCache(error.headers.etag)
|
340 | }
|
341 |
|
342 | throw error
|
343 | })
|
344 | octokit.hook.wrap('request', async (request, options) => {
|
345 | // add logic before, after, catch errors or replace the request altogether
|
346 | return request(options)
|
347 | })
|
348 | ```
|
349 |
|
350 | See [before-after-hook](https://github.com/gr2m/before-after-hook#readme) for more
|
351 | documentation on hooks.
|
352 |
|
353 | ## Plugins
|
354 |
|
355 | You can customize and extend Octokit’s functionality using plugins
|
356 |
|
357 | ```js
|
358 | // index.js
|
359 | const MyOctokit = require('@octokit/request')
|
360 | .plugin([
|
361 | require('./lib/my-plugin'),
|
362 | require('octokit-plugin-example')
|
363 | ])
|
364 |
|
365 | // lib/my-plugin.js
|
366 | module.exports = (octokit, options = { greeting: 'Hello' }) => {
|
367 | // add a custom method
|
368 | octokit.helloWorld = () => console.log(`${options.greeting}, world!`)
|
369 |
|
370 | // hook into the request lifecycle
|
371 | octokit.hook.wrap('request', async (request, options) => {
|
372 | const time = Date.now()
|
373 | const response = await request(options)
|
374 | octokit.log.info(`${options.method} ${options.url} – ${response.status} in ${Date.now() - time}ms`)
|
375 | return response
|
376 | })
|
377 | }
|
378 | ```
|
379 |
|
380 | `.plugin` accepts a function or an array of functions.
|
381 |
|
382 | We recommend using [Octokit’s log methods](#logging) to help users of your plugin with debugging.
|
383 |
|
384 | You can add new methods to the `octokit` instance passed as the first argument to
|
385 | the plugin function. The 2nd argument is the options object passed to the
|
386 | constructor when instantiating the `octokit` client.
|
387 |
|
388 | ```js
|
389 | const octokit = new MyOctokit({ greeting: 'Hola' })
|
390 | octokit.helloWorld()
|
391 | // Hola, world!
|
392 | ```
|
393 |
|
394 | ## Register custom endpoint methods
|
395 |
|
396 | You can register custom endpoint methods such as `octokit.repos.get()` using
|
397 | the `octokit.registerEndpoints(routes)` method
|
398 |
|
399 | ```js
|
400 | octokit.registerEndpoints({
|
401 | foo: {
|
402 | bar: {
|
403 | method: 'PATCH',
|
404 | url: '/repos/:owner/:repo/foo',
|
405 | headers: {
|
406 | accept: 'application/vnd.github.foo-bar-preview+json'
|
407 | },
|
408 | params: {
|
409 | owner: {
|
410 | required: true,
|
411 | type: 'string'
|
412 | },
|
413 | repo: {
|
414 | required: true,
|
415 | type: 'string'
|
416 | },
|
417 | baz: {
|
418 | required: true,
|
419 | type: 'string',
|
420 | enum: [
|
421 | 'qux',
|
422 | 'quux',
|
423 | 'quuz'
|
424 | ]
|
425 | }
|
426 | }
|
427 | }
|
428 | }
|
429 | })
|
430 |
|
431 | octokit.foo.bar({
|
432 | owner: 'octokit',
|
433 | repo: 'rest.js',
|
434 | baz: 'quz'
|
435 | })
|
436 | ```
|
437 |
|
438 | This is useful when you participate in private beta features and prefer the
|
439 | convenience of methods for the new endpoints instead of using [`octokit.request()`]('#customrequests').
|
440 |
|
441 | ## Throttling
|
442 |
|
443 | When you send too many requests in too little time you will likely hit errors due to quotas.
|
444 |
|
445 | In order to automatically throttle requests as recommended in the [best practices for integrators](https://developer.github.com/v3/guides/best-practices-for-integrators/), we recommend you install the [`@octokit/plugin-throttling` plugin](https://github.com/octokit/plugin-throttling.js).
|
446 |
|
447 | The `throttle.onAbuseLimit` and `throttle.onRateLimit` options are required. Return `true` to automatically retry the request after `retryAfter` seconds.
|
448 |
|
449 | ```js
|
450 | const Octokit = require('@octokit/rest')
|
451 | .plugin(require('@octokit/plugin-throttling'))
|
452 |
|
453 | const octokit = new Octokit({
|
454 | auth: 'token ' + process.env.TOKEN,
|
455 | throttle: {
|
456 | onRateLimit: (retryAfter, options) => {
|
457 | octokit.log.warn(`Request quota exhausted for request ${options.method} ${options.url}`)
|
458 |
|
459 | if (options.request.retryCount === 0) { // only retries once
|
460 | console.log(`Retrying after ${retryAfter} seconds!`)
|
461 | return true
|
462 | }
|
463 | },
|
464 | onAbuseLimit: (retryAfter, options) => {
|
465 | // does not retry, only logs a warning
|
466 | octokit.log.warn(`Abuse detected for request ${options.method} ${options.url}`)
|
467 | }
|
468 | }
|
469 | })
|
470 | ```
|
471 |
|
472 | ## Automatic retries
|
473 |
|
474 | Many common request errors can be easily remediated by retrying the request. We recommend installing the [`@octokit/plugin-retry` plugin](https://github.com/octokit/plugin-retry.js) for Automatic retries in these cases
|
475 |
|
476 | ```js
|
477 | const Octokit = require('@octokit/rest')
|
478 | .plugin(require('@octokit/plugin-retry'))
|
479 |
|
480 | const octokit = new Octokit()
|
481 |
|
482 | // all requests sent with the `octokit` instance are now retried up to 3 times for recoverable errors.
|
483 | ```
|
484 |
|
485 | ## Logging
|
486 |
|
487 | `Octokit` has 4 built in log methods
|
488 |
|
489 | 1. `octokit.log.debug(message[, additionalInfo])`
|
490 | 1. `octokit.log.info(message[, additionalInfo])`
|
491 | 1. `octokit.log.warn(message[, additionalInfo])`
|
492 | 1. `octokit.log.error(message[, additionalInfo])`
|
493 |
|
494 | They can be configured using the [`log` client option](client-options). By default, `octokit.log.debug()` and `octokit.log.info()` are no-ops, while the other two call `console.warn()` and `console.error()` respectively.
|
495 |
|
496 | This is useful if you build reusable [plugins](#plugins).
|
497 |
|
498 | ## Debug
|
499 |
|
500 | The simplest way to receive debug information is to set the [`log` client option](client-options) to `console`.
|
501 |
|
502 | ```js
|
503 | const octokit = require('@octokit/rest')({
|
504 | log: console
|
505 | })
|
506 |
|
507 | console.request('/')
|
508 | ```
|
509 |
|
510 | This will log
|
511 |
|
512 | ```
|
513 | request { method: 'GET',
|
514 | baseUrl: 'https://api.github.com',
|
515 | headers:
|
516 | { accept: 'application/vnd.github.v3+json',
|
517 | 'user-agent':
|
518 | 'octokit.js/0.0.0-semantically-released Node.js/10.15.0 (macOS Mojave; x64)' },
|
519 | request: {},
|
520 | url: '/' }
|
521 | GET / - 200 in 514ms
|
522 | ```
|
523 |
|
524 | If you like to support a configurable log level, we recommend using the [console-log-level](https://github.com/watson/console-log-level) module
|
525 |
|
526 | ```js
|
527 | const octokit = require('@octokit/rest')({
|
528 | log: require('console-log-level')({ level: 'info' })
|
529 | })
|
530 |
|
531 | console.request('/')
|
532 | ```
|
533 |
|
534 | This will only log
|
535 |
|
536 | ```
|
537 | GET / - 200 in 514ms
|
538 | ```
|
539 |
|
540 | ## Contributing
|
541 |
|
542 | We would love you to contribute to `@octokit/rest`, pull requests are very welcomed! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for more information.
|
543 |
|
544 | ## Credits
|
545 |
|
546 | `@octokit/rest` was originally created as [`node-github`](https://www.npmjs.com/package/github)
|
547 | in 2012 by Mike de Boer from Cloud9 IDE, Inc.
|
548 | It was adopted and renamed by GitHub in 2017
|
549 |
|
550 | ## LICENSE
|
551 |
|
552 | [MIT](LICENSE)
|