1 | # core.js
|
2 |
|
3 | > Extendable client for GitHub's REST & GraphQL APIs
|
4 |
|
5 | [![@latest](https://img.shields.io/npm/v/@octokit/core.svg)](https://www.npmjs.com/package/@octokit/core)
|
6 | [![Build Status](https://github.com/octokit/core.js/workflows/Test/badge.svg)](https://github.com/octokit/core.js/actions?query=workflow%3ATest+branch%3Amain)
|
7 |
|
8 |
|
9 |
|
10 | - [Usage](#usage)
|
11 | - [REST API example](#rest-api-example)
|
12 | - [GraphQL example](#graphql-example)
|
13 | - [Options](#options)
|
14 | - [Defaults](#defaults)
|
15 | - [Authentication](#authentication)
|
16 | - [Logging](#logging)
|
17 | - [Hooks](#hooks)
|
18 | - [Plugins](#plugins)
|
19 | - [Build your own Octokit with Plugins and Defaults](#build-your-own-octokit-with-plugins-and-defaults)
|
20 | - [LICENSE](#license)
|
21 |
|
22 |
|
23 |
|
24 | If you need a minimalistic library to utilize GitHub's [REST API](https://developer.github.com/v3/) and [GraphQL API](https://developer.github.com/v4/) which you can extend with plugins as needed, then `@octokit/core` is a great starting point.
|
25 |
|
26 | If you don't need the Plugin API then using [`@octokit/request`](https://github.com/octokit/request.js/) or [`@octokit/graphql`](https://github.com/octokit/graphql.js/) directly is a good alternative.
|
27 |
|
28 | ## Usage
|
29 |
|
30 | <table>
|
31 | <tbody valign=top align=left>
|
32 | <tr><th>
|
33 | Browsers
|
34 | </th><td width=100%>
|
35 | Load <code>@octokit/core</code> directly from <a href="https://esm.sh">esm.sh</a>
|
36 |
|
37 | ```html
|
38 | <script type="module">
|
39 | import { Octokit } from "https://esm.sh/@octokit/core";
|
40 | </script>
|
41 | ```
|
42 |
|
43 | </td></tr>
|
44 | <tr><th>
|
45 | Node
|
46 | </th><td>
|
47 |
|
48 | Install with <code>npm install @octokit/core</code>
|
49 |
|
50 | ```js
|
51 | import { Octokit } from "@octokit/core";
|
52 | ```
|
53 |
|
54 | </td></tr>
|
55 | </tbody>
|
56 | </table>
|
57 |
|
58 | As we use [conditional exports](https://nodejs.org/api/packages.html#conditional-exports), you will need to adapt your `tsconfig.json`. See the TypeScript docs on [package.json "exports"](https://www.typescriptlang.org/docs/handbook/modules/reference.html#packagejson-exports).
|
59 |
|
60 | ### REST API example
|
61 |
|
62 | ```js
|
63 | // Create a personal access token at https://github.com/settings/tokens/new?scopes=repo
|
64 | const octokit = new Octokit({ auth: `personal-access-token123` });
|
65 |
|
66 | const response = await octokit.request("GET /orgs/{org}/repos", {
|
67 | org: "octokit",
|
68 | type: "private",
|
69 | });
|
70 | ```
|
71 |
|
72 | See [`@octokit/request`](https://github.com/octokit/request.js) for full documentation of the `.request` method.
|
73 |
|
74 | ### GraphQL example
|
75 |
|
76 | ```js
|
77 | const octokit = new Octokit({ auth: `secret123` });
|
78 |
|
79 | const response = await octokit.graphql(
|
80 | `query ($login: String!) {
|
81 | organization(login: $login) {
|
82 | repositories(privacy: PRIVATE) {
|
83 | totalCount
|
84 | }
|
85 | }
|
86 | }`,
|
87 | { login: "octokit" },
|
88 | );
|
89 | ```
|
90 |
|
91 | See [`@octokit/graphql`](https://github.com/octokit/graphql.js) for full documentation of the `.graphql` method.
|
92 |
|
93 | ## Options
|
94 |
|
95 | <table>
|
96 | <thead align=left>
|
97 | <tr>
|
98 | <th>
|
99 | name
|
100 | </th>
|
101 | <th>
|
102 | type
|
103 | </th>
|
104 | <th width=100%>
|
105 | description
|
106 | </th>
|
107 | </tr>
|
108 | </thead>
|
109 | <tbody align=left valign=top>
|
110 | <tr>
|
111 | <th>
|
112 | <code>options.authStrategy</code>
|
113 | </th>
|
114 | <td>
|
115 | <code>Function<code>
|
116 | </td>
|
117 | <td>
|
118 | Defaults to <a href="https://github.com/octokit/auth-token.js#readme"><code>@octokit/auth-token</code></a>. See <a href="#authentication">Authentication</a> below for examples.
|
119 | </td>
|
120 | </tr>
|
121 | <tr>
|
122 | <th>
|
123 | <code>options.auth</code>
|
124 | </th>
|
125 | <td>
|
126 | <code>String</code> or <code>Object</code>
|
127 | </td>
|
128 | <td>
|
129 | See <a href="#authentication">Authentication</a> below for examples.
|
130 | </td>
|
131 | </tr>
|
132 | <tr>
|
133 | <th>
|
134 | <code>options.baseUrl</code>
|
135 | </th>
|
136 | <td>
|
137 | <code>String</code>
|
138 | </td>
|
139 | <td>
|
140 |
|
141 | When using with GitHub Enterprise Server, set `options.baseUrl` to the root URL of the API. For example, if your GitHub Enterprise Server's hostname is `github.acme-inc.com`, then set `options.baseUrl` to `https://github.acme-inc.com/api/v3`. Example
|
142 |
|
143 | ```js
|
144 | const octokit = new Octokit({
|
145 | baseUrl: "https://github.acme-inc.com/api/v3",
|
146 | });
|
147 | ```
|
148 |
|
149 | </td></tr>
|
150 | <tr>
|
151 | <th>
|
152 | <code>options.previews</code>
|
153 | </th>
|
154 | <td>
|
155 | <code>Array of Strings</code>
|
156 | </td>
|
157 | <td>
|
158 |
|
159 | Some REST API endpoints require preview headers to be set, or enable
|
160 | additional features. Preview headers can be set on a per-request basis, e.g.
|
161 |
|
162 | ```js
|
163 | octokit.request("POST /repos/{owner}/{repo}/pulls", {
|
164 | mediaType: {
|
165 | previews: ["shadow-cat"],
|
166 | },
|
167 | owner,
|
168 | repo,
|
169 | title: "My pull request",
|
170 | base: "main",
|
171 | head: "my-feature",
|
172 | draft: true,
|
173 | });
|
174 | ```
|
175 |
|
176 | You can also set previews globally, by setting the `options.previews` option on the constructor. Example:
|
177 |
|
178 | ```js
|
179 | const octokit = new Octokit({
|
180 | previews: ["shadow-cat"],
|
181 | });
|
182 | ```
|
183 |
|
184 | </td></tr>
|
185 | <tr>
|
186 | <th>
|
187 | <code>options.request</code>
|
188 | </th>
|
189 | <td>
|
190 | <code>Object</code>
|
191 | </td>
|
192 | <td>
|
193 |
|
194 | Set a default request timeout (`options.request.timeout`) or an [`http(s).Agent`](https://nodejs.org/api/http.html#http_class_http_agent) e.g. for proxy usage (Node only, `options.request.agent`).
|
195 |
|
196 | There are more `options.request.*` options, see [`@octokit/request` options](https://github.com/octokit/request.js#request). `options.request` can also be set on a per-request basis.
|
197 |
|
198 | </td></tr>
|
199 | <tr>
|
200 | <th>
|
201 | <code>options.timeZone</code>
|
202 | </th>
|
203 | <td>
|
204 | <code>String</code>
|
205 | </td>
|
206 | <td>
|
207 |
|
208 | Sets the `Time-Zone` header which defines a timezone according to the [list of names from the Olson database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
|
209 |
|
210 | ```js
|
211 | const octokit = new Octokit({
|
212 | timeZone: "America/Los_Angeles",
|
213 | });
|
214 | ```
|
215 |
|
216 | The time zone header will determine the timezone used for generating the timestamp when creating commits. See [GitHub's Timezones documentation](https://developer.github.com/v3/#timezones).
|
217 |
|
218 | </td></tr>
|
219 | <tr>
|
220 | <th>
|
221 | <code>options.userAgent</code>
|
222 | </th>
|
223 | <td>
|
224 | <code>String</code>
|
225 | </td>
|
226 | <td>
|
227 |
|
228 | A custom user agent string for your app or library. Example
|
229 |
|
230 | ```js
|
231 | const octokit = new Octokit({
|
232 | userAgent: "my-app/v1.2.3",
|
233 | });
|
234 | ```
|
235 |
|
236 | </td></tr>
|
237 | </tbody>
|
238 | </table>
|
239 |
|
240 | ## Defaults
|
241 |
|
242 | You can create a new Octokit class with customized default options.
|
243 |
|
244 | ```js
|
245 | const MyOctokit = Octokit.defaults({
|
246 | auth: "personal-access-token123",
|
247 | baseUrl: "https://github.acme-inc.com/api/v3",
|
248 | userAgent: "my-app/v1.2.3",
|
249 | });
|
250 | const octokit1 = new MyOctokit();
|
251 | const octokit2 = new MyOctokit();
|
252 | ```
|
253 |
|
254 | If you pass additional options to your new constructor, the options will be merged shallowly.
|
255 |
|
256 | ```js
|
257 | const MyOctokit = Octokit.defaults({
|
258 | foo: {
|
259 | opt1: 1,
|
260 | },
|
261 | });
|
262 | const octokit = new MyOctokit({
|
263 | foo: {
|
264 | opt2: 1,
|
265 | },
|
266 | });
|
267 | // options will be { foo: { opt2: 1 }}
|
268 | ```
|
269 |
|
270 | If you need a deep or conditional merge, you can pass a function instead.
|
271 |
|
272 | ```js
|
273 | const MyOctokit = Octokit.defaults((options) => {
|
274 | return {
|
275 | foo: Object.assign({}, options.foo, { opt1: 1 }),
|
276 | };
|
277 | });
|
278 | const octokit = new MyOctokit({
|
279 | foo: { opt2: 1 },
|
280 | });
|
281 | // options will be { foo: { opt1: 1, opt2: 1 }}
|
282 | ```
|
283 |
|
284 | Be careful about mutating the `options` object in the `Octokit.defaults` callback, as it can have unforeseen consequences.
|
285 |
|
286 | ## Authentication
|
287 |
|
288 | Authentication is optional for some REST API endpoints accessing public data, but is required for GraphQL queries. Using authentication also increases your [API rate limit](https://developer.github.com/v3/#rate-limiting).
|
289 |
|
290 | By default, Octokit authenticates using the [token authentication strategy](https://github.com/octokit/auth-token.js). Pass in a token using `options.auth`. It can be a personal access token, an OAuth token, an installation access token or a JSON Web Token for GitHub App authentication. The `Authorization` header will be set according to the type of token.
|
291 |
|
292 | ```js
|
293 | import { Octokit } from "@octokit/core";
|
294 |
|
295 | const octokit = new Octokit({
|
296 | auth: "mypersonalaccesstoken123",
|
297 | });
|
298 |
|
299 | const { data } = await octokit.request("/user");
|
300 | ```
|
301 |
|
302 | To use a different authentication strategy, set `options.authStrategy`. A list of authentication strategies is available at [octokit/authentication-strategies.js](https://github.com/octokit/authentication-strategies.js/#readme).
|
303 |
|
304 | Example
|
305 |
|
306 | ```js
|
307 | import { Octokit } from "@octokit/core";
|
308 | import { createAppAuth } from "@octokit/auth-app";
|
309 |
|
310 | const appOctokit = new Octokit({
|
311 | authStrategy: createAppAuth,
|
312 | auth: {
|
313 | appId: 123,
|
314 | privateKey: process.env.PRIVATE_KEY,
|
315 | },
|
316 | });
|
317 |
|
318 | const { data } = await appOctokit.request("/app");
|
319 | ```
|
320 |
|
321 | The `.auth()` method returned by the current authentication strategy can be accessed at `octokit.auth()`. Example
|
322 |
|
323 | ```js
|
324 | const { token } = await appOctokit.auth({
|
325 | type: "installation",
|
326 | installationId: 123,
|
327 | });
|
328 | ```
|
329 |
|
330 | ## Logging
|
331 |
|
332 | There are four built-in log methods
|
333 |
|
334 | 1. `octokit.log.debug(message[, additionalInfo])`
|
335 | 1. `octokit.log.info(message[, additionalInfo])`
|
336 | 1. `octokit.log.warn(message[, additionalInfo])`
|
337 | 1. `octokit.log.error(message[, additionalInfo])`
|
338 |
|
339 | 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.
|
340 |
|
341 | This is useful if you build reusable [plugins](#plugins).
|
342 |
|
343 | If you would like to make the log level configurable using an environment variable or external option, we recommend the [console-log-level](https://github.com/watson/console-log-level) package. Example
|
344 |
|
345 | ```js
|
346 | import consoleLogLevel from "console-log-level";
|
347 | const octokit = new Octokit({
|
348 | log: consoleLogLevel({ level: "info" }),
|
349 | });
|
350 | ```
|
351 |
|
352 | ## Hooks
|
353 |
|
354 | You can customize Octokit's request lifecycle with hooks.
|
355 |
|
356 | ```js
|
357 | octokit.hook.before("request", async (options) => {
|
358 | validate(options);
|
359 | });
|
360 | octokit.hook.after("request", async (response, options) => {
|
361 | console.log(`${options.method} ${options.url}: ${response.status}`);
|
362 | });
|
363 | octokit.hook.error("request", async (error, options) => {
|
364 | if (error.status === 304) {
|
365 | return findInCache(error.response.headers.etag);
|
366 | }
|
367 |
|
368 | throw error;
|
369 | });
|
370 | octokit.hook.wrap("request", async (request, options) => {
|
371 | // add logic before, after, catch errors or replace the request altogether
|
372 | return request(options);
|
373 | });
|
374 | ```
|
375 |
|
376 | See [before-after-hook](https://github.com/gr2m/before-after-hook#readme) for more documentation on hooks.
|
377 |
|
378 | ## Plugins
|
379 |
|
380 | Octokit’s functionality can be extended using plugins. The `Octokit.plugin()` method accepts a plugin (or many) and returns a new constructor.
|
381 |
|
382 | A plugin is a function which gets two arguments:
|
383 |
|
384 | 1. the current instance
|
385 | 2. the options passed to the constructor.
|
386 |
|
387 | In order to extend `octokit`'s API, the plugin must return an object with the new methods. Please refrain from adding methods directly to the `octokit` instance, especialy if you depend on keys that do not exist in `@octokit/core`, such as `octokit.rest`.
|
388 |
|
389 | ```js
|
390 | // index.js
|
391 | import { Octokit } from "@octokit/core";
|
392 | import myPlugin from "./lib/my-plugin.js";
|
393 | import octokitPluginExample from "octokit-plugin-example";
|
394 | const MyOctokit = Octokit.plugin(
|
395 | myPlugin,
|
396 | octokitPluginExample
|
397 | );
|
398 |
|
399 | const octokit = new MyOctokit({ greeting: "Moin moin" });
|
400 | octokit.helloWorld(); // logs "Moin moin, world!"
|
401 | octokit.request("GET /"); // logs "GET / - 200 in 123ms"
|
402 |
|
403 | // lib/my-plugin.js
|
404 | const plugin = (octokit, options = { greeting: "Hello" }) => {
|
405 | // hook into the request lifecycle
|
406 | octokit.hook.wrap("request", async (request, options) => {
|
407 | const time = Date.now();
|
408 | const response = await request(options);
|
409 | console.log(
|
410 | `${options.method} ${options.url} – ${response.status} in ${Date.now() -
|
411 | time}ms`
|
412 | );
|
413 | return response;
|
414 | });
|
415 |
|
416 | // add a custom method
|
417 | return {
|
418 | helloWorld: () => console.log(`${options.greeting}, world!`);
|
419 | }
|
420 | };
|
421 | export default plugin;
|
422 | ```
|
423 |
|
424 | ## Build your own Octokit with Plugins and Defaults
|
425 |
|
426 | You can build your own Octokit class with preset default options and plugins. In fact, this is mostly how the `@octokit/<context>` modules work, such as [`@octokit/action`](https://github.com/octokit/action.js):
|
427 |
|
428 | ```js
|
429 | import { Octokit } from "@octokit/core";
|
430 | import { paginateRest } from "@octokit/plugin-paginate-rest";
|
431 | import { throttling } from "@octokit/plugin-throttling";
|
432 | import { retry } from "@octokit/plugin-retry";
|
433 | import { createActionAuth } from "@octokit/auth-action";
|
434 | const MyActionOctokit = Octokit.plugin(
|
435 | paginateRest,
|
436 | throttling,
|
437 | retry,
|
438 | ).defaults({
|
439 | throttle: {
|
440 | onAbuseLimit: (retryAfter, options) => {
|
441 | /* ... */
|
442 | },
|
443 | onRateLimit: (retryAfter, options) => {
|
444 | /* ... */
|
445 | },
|
446 | },
|
447 | authStrategy: createActionAuth,
|
448 | userAgent: `my-octokit-action/v1.2.3`,
|
449 | });
|
450 |
|
451 | const octokit = new MyActionOctokit();
|
452 | const installations = await octokit.paginate("GET /app/installations");
|
453 | ```
|
454 |
|
455 | ## LICENSE
|
456 |
|
457 | [MIT](LICENSE)
|