Repository: octokit/octokit.js
Branch: main
Commit: fd769731bee3
Files: 31
Total size: 76.8 KB
Directory structure:
gitextract_d81oa9rl/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug.yml
│ │ ├── documentation.yml
│ │ ├── feature.yml
│ │ └── maintenance.yml
│ ├── pull_request_template.md
│ ├── renovate.json
│ └── workflows/
│ ├── add_to_octokit_project.yml
│ ├── codeql.yml
│ ├── immediate-response.yml
│ ├── release.yml
│ ├── test.yml
│ └── update-prettier.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── MAINTAINING.md
├── README.md
├── SECURITY.md
├── package.json
├── scripts/
│ └── build.mjs
├── src/
│ ├── app.ts
│ ├── index.ts
│ ├── octokit.ts
│ └── version.ts
├── test/
│ ├── app.test.ts
│ ├── smoke.test.ts
│ ├── tsconfig.test.json
│ └── typescript-validate.ts
├── tsconfig.json
└── vite.config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/bug.yml
================================================
name: Bug
description: File a bug report
title: "[BUG]: "
labels: ["Type: Bug", "Status: Triage"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: textarea
id: what-happened
attributes:
label: What happened?
description: What did you do? What happened? What did you expect to happen?
placeholder: Put your description of the bug here.
validations:
required: true
- type: textarea
id: versions
attributes:
label: Versions
description: What versions of the relevant software are you running?
placeholder: Octokit.js v2.0.10, Node v16.18.0
validations:
required: true
- type: textarea
id: logs
attributes:
label: Relevant log output
description: |
Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
Please check your logs before submission to ensure sensitive information is redacted.
render: shell
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](CODE_OF_CONDUCT.md)
options:
- label: I agree to follow this project's Code of Conduct
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/documentation.yml
================================================
name: Documentation
description: Update or add documentation
title: "[DOCS]: "
labels: ["Type: Documentation", "Status: Triage"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill this out!
- type: textarea
id: describe-need
attributes:
label: Describe the need
description: What do you wish was different about our docs?
placeholder: Describe the need for documentation updates here.
validations:
required: true
- type: input
id: sdk_version
attributes:
label: SDK Version
description: Do these docs apply to a specific SDK version?
placeholder: Octokit.NET v4.0.1
validations:
required: false
- type: input
id: api_version
attributes:
label: API Version
description: Do these docs apply to a specific version of the GitHub REST API or GraphQL API?
placeholder: ex. v1.1.1
validations:
required: false
- type: textarea
id: logs
attributes:
label: Relevant log output
description: |
Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
Please check your logs before submission to ensure sensitive information is redacted.
render: shell
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](CODE_OF_CONDUCT.md)
options:
- label: I agree to follow this project's Code of Conduct
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/feature.yml
================================================
name: Feature
description: Suggest an idea for a new feature or enhancement
title: "[FEAT]: "
labels: ["Type: Feature", "Status: Triage"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill this out!
- type: textarea
id: describe-need
attributes:
label: Describe the need
description: What do you want to happen? What problem are you trying to solve?
placeholder: Describe the need for the feature.
validations:
required: true
- type: input
id: sdk_version
attributes:
label: SDK Version
description: Does this feature suggestion apply to a specific SDK version?
placeholder: Octokit.rb v6.0.0
validations:
required: false
- type: input
id: api_version
attributes:
label: API Version
description: Does this feature suggestion apply to a specific version of the GitHub REST API or GraphQL API?
placeholder: ex. v1.1.1
validations:
required: false
- type: textarea
id: logs
attributes:
label: Relevant log output
description: |
Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
Please check your logs before submission to ensure sensitive information is redacted.
render: shell
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](CODE_OF_CONDUCT.md)
options:
- label: I agree to follow this project's Code of Conduct
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/maintenance.yml
================================================
name: Maintenance
description: Dependencies, cleanup, refactoring, reworking of code
title: "[MAINT]: "
labels: ["Type: Maintenance", "Status: Triage"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill this out!
- type: textarea
id: describe-need
attributes:
label: Describe the need
description: What do you want to happen?
placeholder: Describe the maintenance need here.
validations:
required: true
- type: input
id: sdk_version
attributes:
label: SDK Version
description: Does this maintenance apply to a specific SDK version?
placeholder: terraform-provider-github v5.7.0
validations:
required: false
- type: input
id: api_version
attributes:
label: API Version
description: Does this maintenance apply to a specific version of the GitHub REST API or GraphQL API?
placeholder: ex. v1.1.1
validations:
required: false
- type: textarea
id: logs
attributes:
label: Relevant log output
description: |
Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
Please check your logs before submission to ensure sensitive information is redacted.
render: shell
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](CODE_OF_CONDUCT.md)
options:
- label: I agree to follow this project's Code of Conduct
required: true
================================================
FILE: .github/pull_request_template.md
================================================
<!-- Please refer to our contributing docs for any questions on submitting a pull request -->
<!-- Issues are required for both bug fixes and features. -->
Resolves #ISSUE_NUMBER
----
### Before the change?
<!-- Please describe the current behavior that you are modifying. -->
*
### After the change?
<!-- Please describe the behavior or changes that are being added by this PR. -->
*
### Pull request checklist
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been reviewed and added / updated if needed (for bug fixes / features)
### Does this introduce a breaking change?
<!-- If this introduces a breaking change make sure to note it here any what the impact might be -->
Please see our docs on [breaking changes](https://github.com/octokit/.github/blob/master/community/breaking_changes.md) to help!
- [ ] Yes
- [ ] No
----
================================================
FILE: .github/renovate.json
================================================
{
"extends": [
"github>octokit/.github"
]
}
================================================
FILE: .github/workflows/add_to_octokit_project.yml
================================================
name: Add PRs and issues to Octokit org project
on:
issues:
types: [reopened, opened]
pull_request_target:
types: [reopened, opened]
jobs:
add-to-project:
name: Add issue to project
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/add-to-project@v1.0.2
with:
project-url: https://github.com/orgs/octokit/projects/10
github-token: ${{ secrets.OCTOKITBOT_PROJECT_ACTION_TOKEN }}
labeled: "Status: Stale"
label-operator: NOT
================================================
FILE: .github/workflows/codeql.yml
================================================
name: "CodeQL"
on:
push:
branches: [ "main", beta ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '19 5 * * 1'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"
================================================
FILE: .github/workflows/immediate-response.yml
================================================
name: Issue/PR response
permissions:
issues: write
pull-requests: write
on:
issues:
types:
- opened
pull_request_target:
types:
- opened
jobs:
respond-to-issue:
if: ${{ github.actor != 'dependabot[bot]' && github.actor != 'renovate[bot]' && github.actor != 'githubactions[bot]' && github.actor != 'octokitbot' }}
runs-on: ubuntu-latest
steps:
- name: Determine issue or PR number
id: extract
run: echo "NUMBER=${{ github.event.issue.number || github.event.pull_request.number }}" >> "$GITHUB_OUTPUT"
- name: Respond to issue or PR
uses: peter-evans/create-or-update-comment@v5
with:
issue-number: ${{ steps.extract.outputs.NUMBER }}
body: >
👋 Hi! Thank you for this contribution! Just to let you know, our GitHub SDK team does a round of issue and PR reviews twice a week, every Monday and Friday!
We have a [process in place](https://github.com/octokit/.github/blob/main/community/prioritization_response.md#overview) for prioritizing and responding to your input.
Because you are a part of this community please feel free to comment, add to, or pick up any issues/PRs that are labeled with `Status: Up for grabs`.
You & others like you are the reason all of this works! So thank you & happy coding! 🚀
================================================
FILE: .github/workflows/release.yml
================================================
name: Release
"on":
push:
branches:
- main
- next
- beta
- "*.x"
- debug
# These are recommended by the semantic-release docs: https://github.com/semantic-release/npm#npm-provenance
permissions:
contents: write # to be able to publish a GitHub release
issues: write # to be able to comment on released issues
pull-requests: write # to be able to comment on released pull requests
id-token: write # to enable use of OIDC for npm provenance
jobs:
release:
name: release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: lts/*
cache: npm
- run: npm ci
- run: npm run build
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.OCTOKITBOT_NPM_TOKEN }}
================================================
FILE: .github/workflows/test.yml
================================================
name: Test
"on":
push:
branches:
- main
pull_request:
types:
- opened
- synchronize
jobs:
test_matrix:
runs-on: ubuntu-latest
strategy:
matrix:
node_version:
- 20
- 22
- 24
steps:
- uses: actions/checkout@v6
- name: Use Node.js ${{ matrix.node_version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node_version }}
cache: npm
- run: npm ci
- run: npm test
test:
runs-on: ubuntu-latest
needs: test_matrix
steps:
- run: exit 1
if: ${{ needs.test_matrix.result != 'success' }}
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: "lts/*"
cache: npm
- run: npm ci
- run: npm run test:typescript
- run: npm run lint
- run: npm run build
if: ${{ always() }}
================================================
FILE: .github/workflows/update-prettier.yml
================================================
name: Update Prettier
"on":
push:
branches:
- renovate/prettier-*
workflow_dispatch: {}
jobs:
update_prettier:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
cache: npm
node-version: lts/*
- run: npm ci
- run: npm run lint:fix
- uses: gr2m/create-or-update-pull-request-action@v1.x
env:
GITHUB_TOKEN: ${{ secrets.OCTOKITBOT_PAT }}
with:
title: Prettier updated
body: An update to prettier required updates to your code.
branch: ${{ github.ref }}
commit-message: "style: prettier"
================================================
FILE: .gitignore
================================================
coverage/
node_modules/
pkg/
.idea/
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or
advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic
address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at opensource+octokit@github.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [https://contributor-covenant.org/version/1/4][version]
[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/4/
================================================
FILE: CONTRIBUTING.md
================================================
# How to contribute
Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md).
By participating in this project you agree to abide by its terms.
We appreciate you taking the time to contribute to `octokit` or any of the projects in Octokit's ecosystem. Especially as a new contributor, you have a valuable perspective that we lost a long time ago: you will find things confusing and run into problems that no longer occur to us. Please share them with us, so we can make the experience for future contributors the best it could be.
Thank you 💖
## Creating an Issue
Before you create a new Issue:
1. Please make sure there is no open issue in the **Issues Section** of the repository you are working on yet. i.e. <https://github.com/octokit/octokit.js/issues?utf8=%E2%9C%93&q=is%3Aissue>
2. If it is a bug report, include the steps to reproduce the issue, and please create a reproducible test case on [runkit.com](https://runkit.com/). Example: <https://runkit.com/gr2m/octokit-rest-js-1808>
3. If it is a feature request, please share the motivation for the new feature, what alternatives you tried, and how you would implement it.
4. Please include links to the corresponding GitHub documentation.
## Set up the repository locally
First, fork the repository.
Set up the repository locally. Replace `<your account name>` with the name of the account you forked to and `<repository name>` with the repository name you forked.
```shell
git clone https://github.com/<your account name>/<repository name>.git
cd <repository name>
npm install
```
Run the tests before making changes to make sure the local setup is working as expected
```shell
npm test
```
## Submitting the Pull Request
- Create a new branch locally.
- Make your changes in that branch and push them to your fork
- Submit a pull request from your topic branch to the main branch on the `octokit/<repository name>` repository.
- Be sure to tag any issues your pull request is taking care of / contributing to. Adding "Closes #123" to a pull request description will automatically close the issue once the pull request is merged in.
## Testing a pull request from GitHub repo locally
You can install `@octokit/<repository name>` from each pull request. Replace `[PULL REQUEST NUMBER]`:
```
npm install https://github.pika.dev/octokit/<repository name>/pr/[PULL REQUEST NUMBER]
```
Once you are done testing, you can revert to the default module `@octokit/<repository name>` from npm with `npm install @octokit/<repository name>`
## Maintainers
See [MAINTAINING.md](MAINTAINING.md)
================================================
FILE: LICENSE
================================================
The MIT License
Copyright (c) 2023 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.
================================================
FILE: MAINTAINING.md
================================================
# Maintenance releases
## Merging the Pull Request & releasing a new version
Releases are automated using [semantic-release](https://github.com/semantic-release/semantic-release).
The following commit message conventions determine which version is released:
1. `fix: ...` or `fix(scope name): ...` prefix in subject: bumps fix version, e.g. `1.2.3` → `1.2.4`
2. `feat: ...` or `feat(scope name): ...` prefix in subject: bumps feature version, e.g. `1.2.3` → `1.3.0`
3. `BREAKING CHANGE:` in body: bumps breaking version, e.g. `1.2.3` → `2.0.0`
Only one version number is bumped at a time, the highest version change trumps the others.
Besides, publishing a new version to npm, semantic-release also creates a git tag and release
on GitHub, generates changelogs from the commit messages and puts them into the release notes.
Before the publish it runs the `npm run build` script which creates a `pkg/` folder with distributions for browsers, node and Typescript definitions. The contents of the `pkg/` folder are published to the npm registry.
If the pull request looks good but does not follow the commit conventions, use the <kbd>Squash & merge</kbd> button.
> ⚠️ making sure the message is semantic-release compliant before clicking <kbd>Confirm squash and merge</kbd>:
]
## Breaking changes
When merging a breaking change using the PR body as specified above, extra care must be taken. Breaking changes must first be merged into the `beta` branch, where further testing may be conducted and additional breaking changes may be combined before cutting a release. The `beta` branch should be created for this purpose and based on `main`. Once the first commit to the branch is landed, a draft PR should be created from `beta` to `main` with the title vX, where X is the next major version. After changes are combined and tested, mark the PR as ready for review, get it reviewed, and merge the `beta` branch into `main` as documented above. `beta` branches are intended to be short-lived.
Note the repository for the change: if it's dependent on other repos where the same change must be made, merge the leaf nodes first before the nodes higher up the tree. Your merge order should look something like:
1. octokit/types (when type changes are required)
1. endpoint
1. request
1. plugins
1. auth strategies
1. core
1. \*-methods
1. oauth-app
1. webhooks
1. app
1. octokit/octokit.js
1. octokit/rest.js
## Maintenance releases
### 0. Requirements
`semantic-release` is configured in the `package.json` of each repository. If `release.branches` is set, make sure that it includes the line for maintenance releases, for example
```js
"release": {
"branches": [
"+([0-9]).x",
"main",
"beta"
],
```
`semantic-release` is run in the`.github/workflows/release.yml` GitHub Action workflow. Make sure it's triggered on push in the `*.x` release branches.
```yml
name: Release
"on":
push:
branches:
- main
- next
- beta
- "*.x"
```
### 1. Create a branch for the maintenance version
Find the latest version that was released on the maintenance version. For example, if the current version is 3.1, and you want to release maintenance versions for 2.x, then find the latest 2.x version. Say that's 2.10.9. In that example, create a branch based on this tag
```
git checkout -b 2.x v2.10.9
```
Then push the new `2.x` branch to GitHub
```
git push -u origin HEAD
```
### 2. Create a pull request with the changes for the new maintenance release
Checkout a branch based on the latest maintenance branch, for example
```
git checkout -b 2.x-my-fix 2.x
```
Commit your changes, then push the branch to GitHub and create a pull request with the maintenance branch as base.
### 3. Merge the pull request with the correct commit message
Note that maintenance versions only support `fix: ...` and `feat: ...` commits, no breaking versions can be released from a maintenance release.
The `.github/workflows/release.yml` action should pick up the commit and release the correct version to both GitHub and npm. The npm release will use a `@release-*.x` tag so that the new release is not picked up as `@latest`.
## Troubleshooting
<details>
<summary>What can I do if I <i>squashed and merged</i> with a commit message which is not <a href="https://github.com/semantic-release/semantic-release">semantic-release</a> compliant?</summary>
1. After merging, do a follow up on `https://github.com/octokit/<repository name>/actions/workflows/release.yml` to assure your commit is not triggering any release. You can find an example of a commit squashed and merged with a non semantic-release commit message [here](https://github.com/octokit/plugin-throttling.js/runs/5390685684?check_suite_focus=true)
2. Mention (`@username`) the maintainers of the project in your merged _Pull Request_ to let them know there was an issue with your merged _Pull Request_. We need to make sure no _Pull Request_ is merged until this issue is addressed.
3. Open a new _Pull Request_ with an [empty commit](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---allow-empty). In the description, link to the previous merged _Pull Request_ to give context to the reviewers and request a Review from the maintainers. This time make sure the message is [semantic-release](https://github.com/semantic-release/semantic-release) compliant.
</details>
================================================
FILE: README.md
================================================
# octokit.js
> The all-batteries-included GitHub SDK for Browsers, Node.js, and Deno.
The `octokit` package integrates the three main Octokit libraries
1. **API client** (REST API requests, GraphQL API queries, Authentication)
2. **App client** (GitHub App & installations, Webhooks, OAuth)
3. **Action client** (Pre-authenticated API client for single repository)
## Table of contents <!-- omit in toc -->
<!-- toc -->
- [octokit.js](#octokitjs)
- [Features](#features)
- [Usage](#usage)
- [`Octokit` API Client](#octokit-api-client)
- [Constructor options](#constructor-options)
- [Authentication](#authentication)
- [Proxy Servers (Node.js only)](#proxy-servers-nodejs-only)
- [Fetch missing](#fetch-missing)
- [REST API](#rest-api)
- [`octokit.rest` endpoint methods](#octokitrest-endpoint-methods)
- [`octokit.request()`](#octokitrequest)
- [Pagination](#pagination)
- [Media Type formats](#media-type-formats)
- [Request error handling](#request-error-handling)
- [GraphQL API queries](#graphql-api-queries)
- [Pagination](#pagination-1)
- [Schema previews](#schema-previews)
- [App client](#app-client)
- [GitHub App](#github-app)
- [Webhooks](#webhooks)
- [OAuth](#oauth)
- [App Server](#app-server)
- [OAuth for browser apps](#oauth-for-browser-apps)
- [Action client](#action-client)
- [LICENSE](#license)
<!-- tocstop -->
## Features
- **Complete**. All features of GitHub's platform APIs are covered.
- **Prescriptive**. All recommended best practices are implemented.
- **Universal**. Works in all modern browsers, [Node.js](https://nodejs.org/), and [Deno](https://deno.land/).
- **Tested**. All libraries have a 100% test coverage.
- **Typed**. All libraries have extensive TypeScript declarations.
- **Decomposable**. Use only the code you need. You can build your own Octokit in only a few lines of code or use the underlying static methods. Make your own tradeoff between functionality and bundle size.
- **Extendable**. A feature missing? Add functionalities with plugins, hook into the request or webhook lifecycle or implement your own authentication strategy.
## Usage
<table>
<tbody valign=top align=left>
<tr><th>
Browsers
</th><td width=100%>
Load <code>octokit</code> directly from <a href="https://esm.sh">esm.sh</a>
```html
<script type="module">
import { Octokit, App } from "https://esm.sh/octokit";
</script>
```
</td></tr>
<tr><th>
Deno
</th><td width=100%>
Load <code>octokit</code> directly from <a href="https://esm.sh">esm.sh</a>
```ts
import { Octokit, App } from "https://esm.sh/octokit?dts";
```
</td></tr>
<tr><th>
Node
</th><td>
Install with <code>npm/pnpm install octokit</code>, or <code>yarn add octokit</code>
```js
import { Octokit, App } from "octokit";
```
</td></tr>
</tbody>
</table>
> [!IMPORTANT]
> As we use [conditional exports](https://nodejs.org/api/packages.html#conditional-exports), you will need to adapt your `tsconfig.json` by setting `"moduleResolution": "node16", "module": "node16"`.
>
> See the TypeScript docs on [package.json "exports"](https://www.typescriptlang.org/docs/handbook/modules/reference.html#packagejson-exports).<br>
> See this [helpful guide on transitioning to ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) from [@sindresorhus](https://github.com/sindresorhus)
## `Octokit` API Client
**standalone minimal Octokit**: [`@octokit/core`](https://github.com/octokit/core.js/#readme).
The `Octokit` client can be used to send requests to [GitHub's REST API](https://docs.github.com/rest/) and queries to [GitHub's GraphQL API](https://docs.github.com/graphql).
**Example**: Get the username for the authenticated user.
```js
// Create a personal access token at https://github.com/settings/tokens/new?scopes=repo
const octokit = new Octokit({ auth: `personal-access-token123` });
// Compare: https://docs.github.com/en/rest/reference/users#get-the-authenticated-user
const {
data: { login },
} = await octokit.rest.users.getAuthenticated();
console.log("Hello, %s", login);
```
### Constructor options
The most commonly used options are
<table>
<thead align=left>
<tr>
<th>
name
</th>
<th>
type
</th>
<th width=100%>
description
</th>
</tr>
</thead>
<tbody align=left valign=top>
<tr>
<th>
<code>userAgent</code>
</th>
<td>
<code>String</code>
</td>
<td>
Setting a user agent is required for all requests sent to GitHub's Platform APIs. The user agent defaults to something like this: `octokit.js/v1.2.3 Node.js/v8.9.4 (macOS High Sierra; x64)`. It is recommend to set your own user agent, which will prepend the default one.
```js
const octokit = new Octokit({
userAgent: "my-app/v1.2.3",
});
```
</td>
</tr>
<tr>
<th>
<code>authStrategy</code>
</th>
<td>
<code>Function</code>
</td>
<td>
Defaults to [`@octokit/auth-token`](https://github.com/octokit/auth-token.js#readme).
See [Authentication](#authentication) below.
</td>
</tr>
<tr>
<th>
<code>auth</code>
</th>
<td>
<code>String</code> or <code>Object</code>
</td>
<td>
Set to a [personal access token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) unless you changed the `authStrategy` option.
See [Authentication](#authentication) below.
</td>
</tr>
<tr>
<th>
<code>baseUrl</code>
</th>
<td>
<code>String</code>
</td>
<td>
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
```js
const octokit = new Octokit({
baseUrl: "https://github.acme-inc.com/api/v3",
});
```
</td>
</tr>
</tbody>
</table>
Advanced options
<table>
<thead align=left>
<tr>
<th>
name
</th>
<th>
type
</th>
<th width=100%>
description
</th>
</tr>
</thead>
<tbody align=left valign=top>
<tr>
<th>
<code>request</code>
</th>
<td>
<code>Object</code>
</td>
<td>
- `request.signal`: Use an [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) instance to cancel a request. [`abort-controller`](https://www.npmjs.com/package/abort-controller) is an implementation for Node.
- `request.fetch`: Replacement for [built-in fetch method](<https://nodejs.org/en/blog/announcements/v18-release-announce#fetch-(experimental)>).
Node only
- `request.timeout` sets a request timeout, defaults to 0
The `request` option can also be set on a per-request basis.
</td></tr>
<tr>
<th>
<code>timeZone</code>
</th>
<td>
<code>String</code>
</td>
<td>
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).
```js
const octokit = new Octokit({
timeZone: "America/Los_Angeles",
});
```
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).
</td>
</tr>
<tr>
<th>
<code>throttle</code>
</th>
<td>
<code>Object</code>
</td>
<td>
`Octokit` implements request throttling using [`@octokit/plugin-throttling`](https://github.com/octokit/plugin-throttling.js/#readme)
By default, requests are retried once and warnings are logged in case of hitting a rate or secondary rate limit.
```js
{
onRateLimit: (retryAfter, options, octokit) => {
octokit.log.warn(
`Request quota exhausted for request ${options.method} ${options.url}`
);
if (options.request.retryCount === 0) {
// only retries once
octokit.log.info(`Retrying after ${retryAfter} seconds!`);
return true;
}
},
onSecondaryRateLimit: (retryAfter, options, octokit) => {
octokit.log.warn(
`SecondaryRateLimit detected for request ${options.method} ${options.url}`
);
if (options.request.retryCount === 0) {
// only retries once
octokit.log.info(`Retrying after ${retryAfter} seconds!`);
return true;
}
},
};
```
To opt-out of this feature:
```js
new Octokit({ throttle: { enabled: false } });
```
Throttling in a cluster is supported using a Redis backend. See [`@octokit/plugin-throttling` Clustering](https://github.com/octokit/plugin-throttling.js/#clustering)
</td>
</tr>
<tr>
<th>
<code>retry</code>
</th>
<td>
<code>Object</code>
</td>
<td>
`Octokit` implements request retries using [`@octokit/plugin-retry`](https://github.com/octokit/plugin-retry.js/#readme)
To opt-out of this feature:
```js
new Octokit({ retry: { enabled: false } });
```
</td>
</tr>
</tbody>
</table>
### Authentication
By default, the `Octokit` API client supports authentication using a static token.
There are different means of authentication that are supported by GitHub, that are described in detail at [octokit/authentication-strategies.js](https://github.com/octokit/authentication-strategies.js/#readme). You can set each of them as the `authStrategy` constructor option, and pass the strategy options as the `auth` constructor option.
For example, in order to authenticate as a GitHub App Installation:
```js
import { createAppAuth } from "@octokit/auth-app";
const octokit = new Octokit({
authStrategy: createAppAuth,
auth: {
appId: 1,
privateKey: "-----BEGIN PRIVATE KEY-----\n...",
installationId: 123,
},
});
// authenticates as app based on request URLs
const {
data: { slug },
} = await octokit.rest.apps.getAuthenticated();
// creates an installation access token as needed
// assumes that installationId 123 belongs to @octocat, otherwise the request will fail
await octokit.rest.issues.create({
owner: "octocat",
repo: "hello-world",
title: "Hello world from " + slug,
});
```
You can use the [`App`](#github-app) or [`OAuthApp`](#oauth-app) SDKs which provide APIs and internal wiring to cover most use cases.
For example, to implement the above using `App`
```js
const app = new App({ appId, privateKey });
const { data: slug } = await app.octokit.rest.apps.getAuthenticated();
const octokit = await app.getInstallationOctokit(123);
await octokit.rest.issues.create({
owner: "octocat",
repo: "hello-world",
title: "Hello world from " + slug,
});
```
Learn more about [how authentication strategies work](https://github.com/octokit/authentication-strategies.js/#how-authentication-strategies-work) or how to [create your own](https://github.com/octokit/authentication-strategies.js/#create-your-own-octokit-authentication-strategy-module).
### Proxy Servers (Node.js only)
By default, the `Octokit` API client does not make use of the standard proxy server environment variables. To add support for proxy servers you will need to provide an https client that supports them such as [`undici.ProxyAgent()`](https://undici.nodejs.org/#/docs/api/ProxyAgent).
For example, this would use a `ProxyAgent` to make requests through a proxy server:
```js
import { fetch as undiciFetch, ProxyAgent } from 'undici';
const myFetch = (url, options) => {
return undiciFetch(url, {
...options,
dispatcher: new ProxyAgent(<your_proxy_url>)
})
}
const octokit = new Octokit({
request: {
fetch: myFetch
},
});
```
If you are writing a module that uses `Octokit` and is designed to be used by other people, you should ensure that consumers can provide an alternative agent for your `Octokit` or as a parameter to specific calls such as:
```js
import { fetch as undiciFetch, ProxyAgent } from 'undici';
const myFetch = (url, options) => {
return undiciFetch(url, {
...options,
dispatcher: new ProxyAgent(<your_proxy_url>)
})
}
octokit.rest.repos.get({
owner,
repo,
request: {
fetch: myFetch
},
});
```
#### Fetch missing
If you get the following error:
> fetch is not set. Please pass a fetch implementation as new Octokit({ request: { fetch }}).
It probably means you are trying to run Octokit with an unsupported version of NodeJS. Octokit requires Node 18 or higher, [which includes a native fetch API](<https://nodejs.org/en/blog/announcements/v18-release-announce#fetch-(experimental)>).
To bypass this problem you can provide your own `fetch` implementation (or a built-in version like `node-fetch`) like this:
```js
import fetch from "node-fetch";
const octokit = new Octokit({
request: {
fetch: fetch,
},
});
```
### REST API
There are two ways of using the GitHub REST API, the [`octokit.rest.*` endpoint methods](#octokitrest-endpoint-methods) and [`octokit.request`](#octokitrequest). Both act the same way, the `octokit.rest.*` methods are just added for convenience, they use `octokit.request` internally.
For example
```js
await octokit.rest.issues.create({
owner: "octocat",
repo: "hello-world",
title: "Hello, world!",
body: "I created this issue using Octokit!",
});
```
Is the same as
```js
await octokit.request("POST /repos/{owner}/{repo}/issues", {
owner: "octocat",
repo: "hello-world",
title: "Hello, world!",
body: "I created this issue using Octokit!",
});
```
In both cases a given request is authenticated, retried, and throttled transparently by the `octokit` instance which also manages the `accept` and `user-agent` headers as needed.
`octokit.request` can be used to send requests to other domains by passing a full URL and to send requests to endpoints that are not (yet) documented in [GitHub's REST API documentation](https://docs.github.com/rest).
#### `octokit.rest` endpoint methods
Every GitHub REST API endpoint has an associated `octokit.rest` endpoint method for better code readability and developer convenience. See [`@octokit/plugin-rest-endpoint-methods`](https://github.com/octokit/plugin-rest-endpoint-methods.js/#readme) for full details.
Example: [Create an issue](https://docs.github.com/en/rest/reference/issues#create-an-issue)
```js
await octokit.rest.issues.create({
owner: "octocat",
repo: "hello-world",
title: "Hello, world!",
body: "I created this issue using Octokit!",
});
```
The `octokit.rest` endpoint methods are generated automatically from [GitHub's OpenAPI specification](https://github.com/github/rest-api-description/). We track operation ID and parameter name changes in order to implement deprecation warnings and reduce the frequency of breaking changes.
Under the covers, every endpoint method is just `octokit.request` with defaults set, so it supports the same parameters as well as the `.endpoint()` API.
#### `octokit.request()`
You can call the GitHub REST API directly using `octokit.request`. The `request` API matches GitHub's REST API documentation 1:1 so anything you see there, you can call using `request`. See [`@octokit/request`](https://github.com/octokit/request.js#readme) for all the details.
Example: [Create an issue](https://docs.github.com/en/rest/reference/issues#create-an-issue)
[](https://docs.github.com/en/rest/reference/issues#create-an-issue)
The `octokit.request` API call corresponding to that issue creation documentation looks like this:
```js
// https://docs.github.com/en/rest/reference/issues#create-an-issue
await octokit.request("POST /repos/{owner}/{repo}/issues", {
owner: "octocat",
repo: "hello-world",
title: "Hello, world!",
body: "I created this issue using Octokit!",
});
```
The 1st argument is the REST API route as listed in GitHub's API documentation. The 2nd argument is an object with all parameters, independent of whether they are used in the path, query, or body.
#### Pagination
All REST API endpoints that paginate return the first 30 items by default. If you want to retrieve all items, you can use the pagination API. The pagination API expects the REST API route as first argument, but you can also pass any of the `octokit.rest.*.list*` methods for convenience and better code readability.
Example: iterate through all issues in a repository
```js
const iterator = octokit.paginate.iterator(octokit.rest.issues.listForRepo, {
owner: "octocat",
repo: "hello-world",
per_page: 100,
});
// iterate through each response
for await (const { data: issues } of iterator) {
for (const issue of issues) {
console.log("Issue #%d: %s", issue.number, issue.title);
}
}
```
Using the [async iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of) is the most memory efficient way to iterate through all items. But you can also retrieve all items in a single call
```js
const issues = await octokit.paginate(octokit.rest.issues.listForRepo, {
owner: "octocat",
repo: "hello-world",
per_page: 100,
});
```
#### Media Type formats
Media type formats can be set using `mediaType: { format }` on every request.
Example: retrieve the raw content of a `package.json` file
```js
const { data } = await octokit.rest.repos.getContent({
mediaType: {
format: "raw",
},
owner: "octocat",
repo: "hello-world",
path: "package.json",
});
console.log("package name: %s", JSON.parse(data).name);
```
Learn more about [Media type formats](https://docs.github.com/en/rest/overview/media-types).
#### Request error handling
**Standalone module:** [`@octokit/request-error`](https://github.com/octokit/request-error.js/#readme)
For request error handling, import `RequestError` and use `try...catch` statement.
```typescript
import { RequestError } from "octokit";
```
```typescript
try {
// your code here that sends at least one Octokit request
await octokit.request("GET /");
} catch (error) {
// Octokit errors are instances of RequestError, so they always have an `error.status` property containing the HTTP response code.
if (error instanceof RequestError) {
// handle Octokit error
// error.message; // Oops
// error.status; // 500
// error.request; // { method, url, headers, body }
// error.response; // { url, status, headers, data }
} else {
// handle all other errors
throw error;
}
}
```
### GraphQL API queries
Octokit also supports GitHub's GraphQL API directly -- you can use the same queries shown in the documentation and available in the GraphQL explorer in your calls with `octokit.graphql`.
Example: get the login of the authenticated user
```js
const {
viewer: { login },
} = await octokit.graphql(`{
viewer {
login
}
}`);
```
Variables can be passed as 2nd argument
```js
const { lastIssues } = await octokit.graphql(
`
query lastIssues($owner: String!, $repo: String!, $num: Int = 3) {
repository(owner: $owner, name: $repo) {
issues(last: $num) {
edges {
node {
title
}
}
}
}
}
`,
{
owner: "octokit",
repo: "graphql.js",
},
);
```
#### Pagination
GitHub's GraphQL API returns a maximum of 100 items. If you want to retrieve all items, you can use the pagination API.
Example: get all issues
```js
const { allIssues } = await octokit.graphql.paginate(
`
query allIssues($owner: String!, $repo: String!, $num: Int = 10, $cursor: String) {
repository(owner: $owner, name: $repo) {
issues(first: $num, after: $cursor) {
edges {
node {
title
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
`,
{
owner: "octokit",
repo: "graphql.js",
},
);
```
Learn more about [GitHub's GraphQL Pagination](https://github.com/octokit/plugin-paginate-graphql.js#readme) usage.
#### Schema previews
Previews can be enabled using the `{mediaType: previews: [] }` option.
Example: create a label
```js
await octokit.graphql(
`mutation createLabel($repositoryId:ID!,name:String!,color:String!) {
createLabel(input:{repositoryId:$repositoryId,name:$name}) {
label: {
id
}
}
}`,
{
repositoryId: 1,
name: "important",
color: "cc0000",
mediaType: {
previews: ["bane"],
},
},
);
```
Learn more about [GitHub's GraphQL schema previews](https://docs.github.com/en/graphql/overview/schema-previews)
## App client
The `App` client combines features for GitHub Apps, Webhooks, and OAuth
### GitHub App
**Standalone module**: [`@octokit/app`](https://github.com/octokit/app.js/#readme)
For integrators, GitHub Apps are a means of authentication and authorization. A GitHub app can be registered on a GitHub user or organization account. A GitHub App registration defines a set of permissions and webhooks events it wants to receive and provides a set of credentials in return. Users can grant access to repositories by installing them.
Some API endpoints require the GitHub app to authenticate as itself using a JSON Web Token (JWT). For requests affecting an installation, an installation access token has to be created using the app's credentials and the installation ID.
The `App` client takes care of all that for you.
Example: Dispatch a repository event in every repository the app is installed on
```js
import { App } from "octokit";
const app = new App({ appId, privateKey });
for await (const { octokit, repository } of app.eachRepository.iterator()) {
// https://docs.github.com/en/rest/reference/repos#create-a-repository-dispatch-event
await octokit.rest.repos.createDispatchEvent({
owner: repository.owner.login,
repo: repository.name,
event_type: "my_event",
client_payload: {
foo: "bar",
},
});
console.log("Event dispatched for %s", repository.full_name);
}
```
Example: Get an `octokit` instance authenticated as an installation
```js
const octokit = await app.getInstallationOctokit(123);
```
Learn more about [apps](https://docs.github.com/apps).
### Webhooks
**Standalone module**: [`@octokit/webhooks`](https://github.com/octokit/webhooks.js/#readme)
When installing an app, events that the app registration requests will be sent as requests to the webhook URL set in the app's registration.
Webhook event requests are signed using the webhook secret, which is also part of the app's registration. You must verify that secret before handling the request payload.
The `app.webhooks.*` APIs provide methods to receiving, verifying, and handling webhook events.
Example: create a comment on new issues
```js
import { createServer } from "node:http";
import { App, createNodeMiddleware } from "octokit";
const app = new App({
appId,
privateKey,
webhooks: { secret },
});
app.webhooks.on("issues.opened", ({ octokit, payload }) => {
return octokit.rest.issues.createComment({
owner: payload.repository.owner.login,
repo: payload.repository.name,
issue_number: payload.issue.number,
body: "Hello, World!",
});
});
// Your app can now receive webhook events at `/api/github/webhooks`
createServer(createNodeMiddleware(app)).listen(3000);
```
For serverless environments, you can explicitly verify and receive an event
```js
await app.webhooks.verifyAndReceive({
id: request.headers["x-github-delivery"],
name: request.headers["x-github-event"],
signature: request.headers["x-hub-signature-256"],
payload: request.body,
});
```
Learn more about [GitHub webhooks](https://docs.github.com/webhooks).
### OAuth
**Standalone module:** [`@octokit/oauth-app`](https://github.com/octokit/oauth-app.js/#readme)
Both OAuth Apps and GitHub Apps support authenticating GitHub users using OAuth, see [Authorizing OAuth Apps](https://docs.github.com/en/developers/apps/authorizing-oauth-apps) and [Identifying and authorizing users for GitHub Apps](https://docs.github.com/en/developers/apps/identifying-and-authorizing-users-for-github-apps).
There are some differences:
- Only OAuth Apps support scopes. GitHub apps have permissions, and access is granted via installations of the app on repositories.
- Only GitHub Apps support expiring user tokens
- Only GitHub Apps support creating a scoped token to reduce the permissions and repository access
`App` is for GitHub Apps. If you need OAuth App-specific functionality, use [`OAuthApp` instead](https://github.com/octokit/oauth-app.js/).
Example: Watch a repository when a user logs in using the OAuth web flow
```js
import { createServer } from "node:http";
import { App, createNodeMiddleware } from "octokit";
const app = new App({
oauth: { clientId, clientSecret },
});
app.oauth.on("token.created", async ({ token, octokit }) => {
await octokit.rest.activity.setRepoSubscription({
owner: "octocat",
repo: "hello-world",
subscribed: true,
});
});
// Your app can receive the OAuth redirect at /api/github/oauth/callback
// Users can initiate the OAuth web flow by opening /api/github/oauth/login
createServer(createNodeMiddleware(app)).listen(3000);
```
For serverless environments, you can explicitly exchange the `code` from the OAuth web flow redirect for an access token.
`app.oauth.createToken()` returns an authentication object and emits the "token.created" event.
```js
const { token } = await app.oauth.createToken({
code: request.query.code,
});
```
Example: create a token using the device flow.
```js
const { token } = await app.oauth.createToken({
async onVerification(verification) {
await sendMessageToUser(
request.body.phoneNumber,
`Your code is ${verification.user_code}. Enter it at ${verification.verification_uri}`,
);
},
});
```
Example: Create an OAuth App Server with default scopes
```js
import { createServer } from "node:http";
import { OAuthApp, createNodeMiddleware } from "octokit";
const app = new OAuthApp({
clientId,
clientSecret,
defaultScopes: ["repo", "gist"],
});
app.oauth.on("token", async ({ token, octokit }) => {
await octokit.rest.gists.create({
description: "I created this gist using Octokit!",
public: true,
files: {
"example.js": `/* some code here */`,
},
});
});
// Your app can receive the OAuth redirect at /api/github/oauth/callback
// Users can initiate the OAuth web flow by opening /api/oauth/login
createServer(createNodeMiddleware(app)).listen(3000);
```
### App Server
After registering your GitHub app, you need to create and deploy a server which can retrieve the webhook event requests from GitHub as well as accept redirects from the OAuth user web flow.
The simplest way to create such a server is to use `createNodeMiddleware()`, it works with both, Node's [`http.createServer()`](https://nodejs.org/api/http.html#http_http_createserver_options_requestlistener) method as well as an [Express middleware](https://expressjs.com/en/guide/using-middleware.html).
The default routes that the middleware exposes are
| Route | Route Description |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `POST /api/github/webhooks` | Endpoint to receive GitHub Webhook Event requests |
| `GET /api/github/oauth/login` | Redirects to GitHub's authorization endpoint. Accepts optional `?state` and `?scopes` query parameters. `?scopes` is a comma-separated list of [supported OAuth scope names](https://docs.github.com/en/developers/apps/scopes-for-oauth-apps#available-scopes) |
| `GET /api/github/oauth/callback` | The client's redirect endpoint. This is where the `token` event gets triggered |
| `POST /api/github/oauth/token` | Exchange an authorization code for an OAuth Access token. If successful, the `token` event gets triggered. |
| `GET /api/github/oauth/token` | Check if token is valid. Must authenticate using token in `Authorization` header. Uses GitHub's [`POST /applications/{client_id}/token`](https://docs.github.com/en/rest/reference/apps#check-a-token) endpoint |
| `PATCH /api/github/oauth/token` | Resets a token (invalidates current one, returns new token). Must authenticate using token in `Authorization` header. Uses GitHub's [`PATCH /applications/{client_id}/token`](https://docs.github.com/en/rest/reference/apps#reset-a-token) endpoint. |
| `PATCH /api/github/oauth/refresh-token` | Refreshes an expiring token (invalidates current one, returns new access token and refresh token). Must authenticate using token in `Authorization` header. Uses GitHub's [`POST https://github.com/login/oauth/access_token`](https://docs.github.com/en/developers/apps/refreshing-user-to-server-access-tokens#renewing-a-user-token-with-a-refresh-token) OAuth endpoint. |
| `POST /api/github/oauth/token/scoped` | Creates a scoped token (does not invalidate the current one). Must authenticate using token in `Authorization` header. Uses GitHub's [`POST /applications/{client_id}/token/scoped`](https://docs.github.com/en/rest/reference/apps#create-a-scoped-access-token) endpoint. |
| `DELETE /api/github/oauth/token` | Invalidates current token, basically the equivalent of a logout. Must authenticate using token in `Authorization` header. |
| `DELETE /api/github/oauth/grant` | Revokes the user's grant, basically the equivalent of an uninstall. must authenticate using token in `Authorization` header. |
Example: create a GitHub server with express
```js
import express from "express";
import { App, createNodeMiddleware } from "octokit";
const expressApp = express();
const octokitApp = new App({
appId,
privateKey,
webhooks: { secret },
oauth: { clientId, clientSecret },
});
expressApp.use(createNodeMiddleware(app));
expressApp.listen(3000, () => {
console.log(`Example app listening at http://localhost:3000`);
});
```
### OAuth for browser apps
You must not expose your app's client secret to the user, so you cannot use the `App` constructor. Instead, you have to create a server using the `App` constructor which exposes the `/api/github/oauth/*` routes, through which you can safely implement an OAuth login for apps running in a web browser.
If you set `(User) Authorization callback URL` to your own app, than you need to read out the `?code=...&state=...` query parameters, compare the `state` parameter to the value returned by `app.oauthLoginUrl()` earlier to protect against forgery attacks, then exchange the `code` for an OAuth Authorization token.
If you run an [app server](#app-server) as described above, the default route to do that is `POST /api/github/oauth/token`.
Once you successfully retrieved the token, it is also recommended to remove the `?code=...&state=...` query parameters from the browser's URL
```js
const code = new URL(location.href).searchParams.get("code");
if (code) {
// remove ?code=... from URL
const path =
location.pathname +
location.search.replace(/\b(code|state)=\w+/g, "").replace(/[?&]+$/, "");
history.replaceState({}, "", path);
// exchange the code for a token with your backend.
// If you use https://github.com/octokit/oauth-app.js
// the exchange would look something like this
const response = await fetch("/api/github/oauth/token", {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify({ code }),
});
const { token } = await response.json();
// `token` is the OAuth Access Token that can be use
const { Octokit } = await import("https://esm.sh/@octokit/core");
const octokit = new Octokit({ auth: token });
const {
data: { login },
} = await octokit.request("GET /user");
alert("Hi there, " + login);
}
```
🚧 We are working on [`@octokit/auth-oauth-user-client`](https://github.com/octokit/auth-oauth-user-client.js#readme) to provide a simple API for all methods related to OAuth user tokens.
The plan is to add an new `GET /api/github/oauth/octokit.js` route to the node middleware which will return a JavaScript file that can be imported into an HTML file. It will make a pre-authenticated `octokit` Instance available.
## Action client
**standalone module:** [`@octokit/action`](https://github.com/octokit/action.js#readme)
🚧 A fully fledged `Action` client is pending. You can use [`@actions/github`](https://github.com/actions/toolkit/tree/main/packages/github) for the time being
## LICENSE
[MIT](LICENSE)
================================================
FILE: SECURITY.md
================================================
# Security Policy
Thanks for helping make GitHub Open Source Software safe for everyone.
GitHub takes the security of our software products and services seriously, including all of the open source code repositories managed through our GitHub organizations, such as [Octokit](https://github.com/octokit).
Even though [open source repositories are outside of the scope of our bug bounty program](https://bounty.github.com/index.html#scope) and therefore not eligible for bounty rewards, we want to make sure that your finding gets passed along to the maintainers of this project for remediation.
## Reporting a Vulnerability
Since this source is part of [Octokit](https://github.com/octokit) (a GitHub organization) we ask that you follow the guidelines [here](https://github.com/github/.github/blob/master/SECURITY.md#reporting-security-issues) to report anything that you might've found.
================================================
FILE: package.json
================================================
{
"name": "octokit",
"version": "0.0.0-development",
"type": "module",
"description": "The all-batteries-included GitHub SDK for Browsers, Node.js, and Deno",
"keywords": [
"github",
"api",
"sdk",
"octokit"
],
"author": "Gregor Martynus (https://github.com/gr2m)",
"repository": "github:octokit/octokit.js",
"license": "MIT",
"scripts": {
"build": "node scripts/build.mjs && tsc -p tsconfig.json",
"lint": "prettier --check \"{src,test,scripts}/**/*.{js,json,ts}\" \"*.{md,json}\"",
"lint:fix": "prettier --write \"{src,test,scripts}/**/*.{js,json,ts,mjs}\" \"*.{md,json}\"",
"pretest": "npm run -s lint",
"test": "vitest run --coverage",
"test:typescript": "npx tsc --noEmit --declaration --noUnusedLocals --esModuleInterop --module node16 --strict --allowImportingTsExtensions --exactOptionalPropertyTypes test/typescript-validate.ts"
},
"dependencies": {
"@octokit/app": "^16.1.2",
"@octokit/core": "^7.0.6",
"@octokit/oauth-app": "^8.0.3",
"@octokit/plugin-paginate-graphql": "^6.0.0",
"@octokit/plugin-paginate-rest": "^14.0.0",
"@octokit/plugin-rest-endpoint-methods": "^17.0.0",
"@octokit/plugin-retry": "^8.0.3",
"@octokit/plugin-throttling": "^11.0.3",
"@octokit/request-error": "^7.0.2",
"@octokit/types": "^16.0.0",
"@octokit/webhooks": "^14.0.0"
},
"devDependencies": {
"@octokit/tsconfig": "^4.0.0",
"@types/node": "^24.0.0",
"@vitest/coverage-v8": "^4.0.0",
"esbuild": "^0.27.0",
"mockdate": "^3.0.5",
"nock": "^14.0.10",
"prettier": "3.7.4",
"semantic-release-plugin-update-version-in-files": "^2.0.0",
"tinyglobby": "^0.2.15",
"typescript": "^5.0.0",
"vitest": "^4.0.0"
},
"release": {
"branches": [
"+([0-9]).x",
"main",
"next",
{
"name": "beta",
"prerelease": true
},
{
"name": "debug",
"prerelease": true
}
],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/github",
[
"@semantic-release/npm",
{
"pkgRoot": "./pkg"
}
],
[
"semantic-release-plugin-update-version-in-files",
{
"files": [
"pkg/dist-web/*",
"pkg/dist-node/*",
"pkg/*/version.*"
]
}
]
]
},
"engines": {
"node": ">= 20"
},
"publishConfig": {
"provenance": true
}
}
================================================
FILE: scripts/build.mjs
================================================
// @ts-check
import esbuild from "esbuild";
import { copyFile, readFile, writeFile, rm } from "node:fs/promises";
import { glob } from "tinyglobby";
/**
* @type {esbuild.BuildOptions}
*/
const sharedOptions = {
sourcemap: "external",
sourcesContent: true,
minify: false,
allowOverwrite: true,
packages: "external",
platform: "neutral",
format: "esm",
target: "es2022",
};
async function main() {
// Start with a clean slate
await rm("pkg", { recursive: true, force: true });
// Build the source code for a neutral platform as ESM
await esbuild.build({
entryPoints: await glob(["./src/*.ts", "./src/**/*.ts"]),
outdir: "pkg/dist-src",
bundle: false,
...sharedOptions,
sourcemap: false,
});
// Remove the types file from the dist-src folder
const typeFiles = await glob([
"./pkg/dist-src/**/types.js.map",
"./pkg/dist-src/**/types.js",
]);
for (const typeFile of typeFiles) {
await rm(typeFile);
}
const entryPoints = ["./pkg/dist-src/index.js"];
// Build an ESM bundle
await esbuild.build({
entryPoints,
outdir: "pkg/dist-bundle",
bundle: true,
...sharedOptions,
});
// Copy the README, LICENSE to the pkg folder
await copyFile("LICENSE", "pkg/LICENSE");
await copyFile("README.md", "pkg/README.md");
// Handle the package.json
let pkg = JSON.parse((await readFile("package.json", "utf8")).toString());
// Remove unnecessary fields from the package.json
delete pkg.scripts;
delete pkg.prettier;
delete pkg.release;
delete pkg.jest;
await writeFile(
"pkg/package.json",
JSON.stringify(
{
...pkg,
files: ["dist-*/**", "bin/**"],
types: "./dist-types/index.d.ts",
exports: {
".": {
types: "./dist-types/index.d.ts",
import: "./dist-bundle/index.js",
default: "./dist-bundle/index.js",
},
},
sideEffects: false,
},
null,
2,
),
);
}
main();
================================================
FILE: src/app.ts
================================================
import { App as DefaultApp } from "@octokit/app";
import { OAuthApp as DefaultOAuthApp } from "@octokit/oauth-app";
import { Octokit } from "./octokit.js";
export const App = DefaultApp.defaults({ Octokit });
export type App = InstanceType<typeof App>;
export const OAuthApp = DefaultOAuthApp.defaults({ Octokit });
export type OAuthApp = InstanceType<typeof OAuthApp>;
export { createNodeMiddleware } from "@octokit/app";
================================================
FILE: src/index.ts
================================================
export { Octokit, RequestError } from "./octokit.js";
export type { PageInfoForward, PageInfoBackward } from "./octokit.js";
export { App, OAuthApp, createNodeMiddleware } from "./app.js";
================================================
FILE: src/octokit.ts
================================================
import { Octokit as OctokitCore } from "@octokit/core";
import { paginateRest } from "@octokit/plugin-paginate-rest";
import { paginateGraphQL } from "@octokit/plugin-paginate-graphql";
import { restEndpointMethods } from "@octokit/plugin-rest-endpoint-methods";
import { retry } from "@octokit/plugin-retry";
import { throttling } from "@octokit/plugin-throttling";
import { VERSION } from "./version.js";
import type { EndpointDefaults } from "@octokit/types";
export { RequestError } from "@octokit/request-error";
export type {
PageInfoForward,
PageInfoBackward,
} from "@octokit/plugin-paginate-graphql";
export const Octokit = OctokitCore.plugin(
restEndpointMethods,
paginateRest,
paginateGraphQL,
retry,
throttling,
).defaults({
userAgent: `octokit.js/${VERSION}`,
throttle: {
onRateLimit,
onSecondaryRateLimit,
},
});
export type Octokit = InstanceType<typeof Octokit>;
/* v8 ignore next no need to test internals of the throttle plugin -- @preserve */
function onRateLimit(
retryAfter: number,
options: Required<EndpointDefaults>,
octokit: InstanceType<typeof OctokitCore>,
) {
octokit.log.warn(
`Request quota exhausted for request ${options.method} ${options.url}`,
);
if (options.request.retryCount === 0) {
// only retries once
octokit.log.info(`Retrying after ${retryAfter} seconds!`);
return true;
}
}
/* v8 ignore next no need to test internals of the throttle plugin -- @preserve */
function onSecondaryRateLimit(
retryAfter: number,
options: Required<EndpointDefaults>,
octokit: InstanceType<typeof OctokitCore>,
) {
octokit.log.warn(
`SecondaryRateLimit detected for request ${options.method} ${options.url}`,
);
if (options.request.retryCount === 0) {
// only retries once
octokit.log.info(`Retrying after ${retryAfter} seconds!`);
return true;
}
}
================================================
FILE: src/version.ts
================================================
export const VERSION = "0.0.0-development";
================================================
FILE: test/app.test.ts
================================================
import { beforeEach, describe, expect, test } from "vitest";
import { createServer } from "node:http";
import nock from "nock";
import MockDate from "mockdate";
import { App, Octokit, createNodeMiddleware } from "../src/index.ts";
const APP_ID = 1;
const PRIVATE_KEY = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA1c7+9z5Pad7OejecsQ0bu3aozN3tihPmljnnudb9G3HECdnH
lWu2/a1gB9JW5TBQ+AVpum9Okx7KfqkfBKL9mcHgSL0yWMdjMfNOqNtrQqKlN4kE
p6RD++7sGbzbfZ9arwrlD/HSDAWGdGGJTSOBM6pHehyLmSC3DJoR/CTu0vTGTWXQ
rO64Z8tyXQPtVPb/YXrcUhbBp8i72b9Xky0fD6PkEebOy0Ip58XVAn2UPNlNOSPS
ye+Qjtius0Md4Nie4+X8kwVI2Qjk3dSm0sw/720KJkdVDmrayeljtKBx6AtNQsSX
gzQbeMmiqFFkwrG1+zx6E7H7jqIQ9B6bvWKXGwIDAQABAoIBAD8kBBPL6PPhAqUB
K1r1/gycfDkUCQRP4DbZHt+458JlFHm8QL6VstKzkrp8mYDRhffY0WJnYJL98tr4
4tohsDbqFGwmw2mIaHjl24LuWXyyP4xpAGDpl9IcusjXBxLQLp2m4AKXbWpzb0OL
Ulrfc1ZooPck2uz7xlMIZOtLlOPjLz2DuejVe24JcwwHzrQWKOfA11R/9e50DVse
hnSH/w46Q763y4I0E3BIoUMsolEKzh2ydAAyzkgabGQBUuamZotNfvJoDXeCi1LD
8yNCWyTlYpJZJDDXooBU5EAsCvhN1sSRoaXWrlMSDB7r/E+aQyKua4KONqvmoJuC
21vSKeECgYEA7yW6wBkVoNhgXnk8XSZv3W+Q0xtdVpidJeNGBWnczlZrummt4xw3
xs6zV+rGUDy59yDkKwBKjMMa42Mni7T9Fx8+EKUuhVK3PVQyajoyQqFwT1GORJNz
c/eYQ6VYOCSC8OyZmsBM2p+0D4FF2/abwSPMmy0NgyFLCUFVc3OECpkCgYEA5OAm
I3wt5s+clg18qS7BKR2DuOFWrzNVcHYXhjx8vOSWV033Oy3yvdUBAhu9A1LUqpwy
Ma+unIgxmvmUMQEdyHQMcgBsVs10dR/g2xGjMLcwj6kn+xr3JVIZnbRT50YuPhf+
ns1ScdhP6upo9I0/sRsIuN96Gb65JJx94gQ4k9MCgYBO5V6gA2aMQvZAFLUicgzT
u/vGea+oYv7tQfaW0J8E/6PYwwaX93Y7Q3QNXCoCzJX5fsNnoFf36mIThGHGiHY6
y5bZPPWFDI3hUMa1Hu/35XS85kYOP6sGJjf4kTLyirEcNKJUWH7CXY+00cwvTkOC
S4Iz64Aas8AilIhRZ1m3eQKBgQCUW1s9azQRxgeZGFrzC3R340LL530aCeta/6FW
CQVOJ9nv84DLYohTVqvVowdNDTb+9Epw/JDxtDJ7Y0YU0cVtdxPOHcocJgdUGHrX
ZcJjRIt8w8g/s4X6MhKasBYm9s3owALzCuJjGzUKcDHiO2DKu1xXAb0SzRcTzUCn
7daCswKBgQDOYPZ2JGmhibqKjjLFm0qzpcQ6RPvPK1/7g0NInmjPMebP0K6eSPx0
9/49J6WTD++EajN7FhktUSYxukdWaCocAQJTDNYP0K88G4rtC2IYy5JFn9SWz5oh
x//0u+zd/R/QRUzLOw4N72/Hu+UG6MNt5iDZFCtapRaKt6OvSBwy8w==
-----END RSA PRIVATE KEY-----`;
const CLIENT_ID = "lv1.1234567890abcdef";
const CLIENT_SECRET = "1234567890abcdef1234567890abcdef12345678";
const WEBHOOK_SECRET = "secret";
// see https://runkit.com/gr2m/reproducable-jwt
const BEARER =
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOi0zMCwiZXhwIjo1NzAsImlzcyI6MX0.q3foRa78U3WegM5PrWLEh5N0bH1SD62OqW66ZYzArp95JBNiCbo8KAlGtiRENCIfBZT9ibDUWy82cI4g3F09mdTq3bD1xLavIfmTksIQCz5EymTWR5v6gL14LSmQdWY9lSqkgUG0XCFljWUglEP39H4yeHbFgdjvAYg3ifDS12z9oQz2ACdSpvxPiTuCC804HkPVw8Qoy0OSXvCkFU70l7VXCVUxnuhHnk8-oCGcKUspmeP6UdDnXk-Aus-eGwDfJbU2WritxxaXw6B4a3flTPojkYLSkPBr6Pi0H2-mBsW_Nvs0aLPVLKobQd4gqTkosX3967DoAG8luUMhrnxe8Q";
describe("App", () => {
let app: InstanceType<typeof App>;
const mock = nock("https://api.github.com");
beforeEach(() => {
MockDate.set(0);
nock.cleanAll();
app = new App({
appId: APP_ID,
privateKey: PRIVATE_KEY,
oauth: {
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
},
webhooks: {
secret: WEBHOOK_SECRET,
},
Octokit: Octokit.defaults({
throttle: { enabled: false },
}),
});
});
test("Readme example: `app.eachRepository.iterator`", async () => {
mock
.get("/app/installations", undefined, {
reqheaders: { authorization: `bearer ${BEARER}` },
})
.reply(200, [{ id: 123 }]);
mock
.post("/app/installations/123/access_tokens", undefined, {
reqheaders: { authorization: `bearer ${BEARER}` },
})
.reply(200, {
token: "secret123",
expires_at: "1970-01-01T01:00:00.000Z",
permissions: {
metadata: "read",
},
repository_selection: "all",
});
mock.get("/installation/repositories").reply(200, {
total_count: 1,
repositories: [
{
owner: { login: "octokit" },
name: "octokit.js",
full_name: "octokit/octokit.js",
},
],
});
mock
.post("/repos/octokit/octokit.js/dispatches", {
event_type: "my_event",
client_payload: { foo: "bar" },
})
.reply(204);
for await (const { octokit, repository } of app.eachRepository.iterator()) {
// https://docs.github.com/en/rest/reference/repos#create-a-repository-dispatch-event
await octokit.request("POST /repos/{owner}/{repo}/dispatches", {
owner: repository.owner.login,
repo: repository.name,
event_type: "my_event",
client_payload: {
foo: "bar",
},
});
expect(repository.full_name).toEqual("octokit/octokit.js");
}
expect(mock.isDone()).toBe(true);
});
test("README example: app.getInstallationOctokit", async () => {
mock
.post("/app/installations/123/access_tokens", undefined, {
reqheaders: { authorization: `bearer ${BEARER}` },
})
.reply(200, {
token: "secret123",
expires_at: "1970-01-01T01:00:00.000Z",
permissions: {
metadata: "read",
},
repository_selection: "all",
});
mock
.post("/repos/octokit/octokit.js/issues", { title: "Hello, world!" })
.reply(201, { id: 1 });
const octokit = await app.getInstallationOctokit(123);
// https://docs.github.com/en/rest/reference/issues#create-an-issue
await octokit.request("POST /repos/{owner}/{repo}/issues", {
owner: "octokit",
repo: "octokit.js",
title: "Hello, world!",
});
expect(mock.isDone()).toBe(true);
});
test("README example: createNodeMiddleware(app)", async () => {
expect.assertions(3);
mock
.post("/app/installations/123/access_tokens", undefined, {
reqheaders: { authorization: `bearer ${BEARER}` },
})
.reply(200, {
token: "secret123",
expires_at: "1970-01-01T01:00:00.000Z",
permissions: {
metadata: "read",
},
repository_selection: "all",
});
mock
.post("/repos/octokit/octokit.js/issues/1/comments", {
body: "Hello, World!",
})
.reply(200, { body: 1 });
app.webhooks.on("issues.opened", async ({ octokit, payload }) => {
await octokit.rest.issues.createComment({
owner: payload.repository.owner.login,
repo: payload.repository.name,
issue_number: payload.issue.number,
body: "Hello, World!",
});
expect(mock.isDone()).toBe(true);
});
// Your app can now receive webhook events at `/api/github/webhooks`
const server = createServer(createNodeMiddleware(app)).listen();
// @ts-expect-error - port is typed as undefined
const port = server.address().port;
const issuePayload = JSON.stringify({
repository: {
owner: {
login: "octokit",
},
name: "octokit.js",
},
action: "opened",
installation: { id: 123 },
issue: { number: 1 },
});
const response = await fetch(
`http://localhost:${port}/api/github/webhooks`,
{
method: "POST",
headers: {
"content-type": "application/json",
"x-github-event": "issues",
"x-github-delivery": "1",
"x-hub-signature-256": await app.webhooks.sign(issuePayload),
},
body: issuePayload,
},
);
expect(await response.text()).toEqual("ok\n");
expect(response.status).toEqual(200);
server.close();
});
});
================================================
FILE: test/smoke.test.ts
================================================
import { describe, expect, it } from "vitest";
import { Octokit, App, OAuthApp, RequestError } from "../src/index.ts";
describe("Smoke tests", () => {
it("Octokit is a function", () => {
expect(Octokit).toBeInstanceOf(Function);
expect(() => new Octokit()).not.toThrow();
});
it("Octokit can be used as a type", () => {
let octokit: Octokit;
octokit = new Octokit();
expect(octokit.rest.repos.get).toBeInstanceOf(Function);
});
it("App is a function", () => {
expect(App).toBeInstanceOf(Function);
expect(
() =>
new App({
appId: 123,
privateKey: "private key here",
}),
).not.toThrow();
});
it("App can be used as a type", () => {
let app: App;
app = new App({
appId: 123,
privateKey: "private key here",
});
expect(app.octokit.request).toBeInstanceOf(Function);
});
it("OAuthApp is a function", () => {
expect(OAuthApp).toBeInstanceOf(Function);
expect(
() =>
new OAuthApp({
clientId: "",
clientSecret: "",
}),
).not.toThrow();
});
it("OAuthApp can be used as a type", () => {
let app: OAuthApp;
app = new OAuthApp({
clientId: "",
clientSecret: "",
});
expect(app.octokit.request).toBeInstanceOf(Function);
});
it("RequestError inherits from Error", () => {
const error = new RequestError("test", 123, {
request: {
method: "GET",
url: "https://api.github.com/",
headers: {},
},
});
expect(error).toBeInstanceOf(RequestError);
});
});
================================================
FILE: test/tsconfig.test.json
================================================
{
"extends": "../tsconfig.json",
"compilerOptions": {
"emitDeclarationOnly": false,
"noEmit": true,
"verbatimModuleSyntax": false,
"allowImportingTsExtensions": true
},
"include": ["src/**/*"]
}
================================================
FILE: test/typescript-validate.ts
================================================
// ************************************************************
// THIS CODE IS NOT EXECUTED. IT IS JUST FOR TYPECHECKING
// ************************************************************
import { App, OAuthApp, Octokit, RequestError } from "../src/index.ts";
function expect<T>(what: T) {}
export async function OctokitTest() {
const app = new App({
appId: 1,
privateKey: "",
});
expect<Octokit>(app.octokit);
const oauthApp = new OAuthApp({
clientId: "",
clientSecret: "",
});
expect<Octokit>(oauthApp.octokit);
const installationOctokit = await app.getInstallationOctokit(1);
const issues = await installationOctokit.paginate(
installationOctokit.rest.issues.listForRepo,
{
owner: "",
repo: "",
},
);
expect<number>(issues[0].id);
const error = new RequestError("test", 123, {
request: {
method: "GET",
url: "https://api.github.com/",
headers: {},
},
});
expect<RequestError>(error);
}
================================================
FILE: tsconfig.json
================================================
{
"extends": "@octokit/tsconfig",
"include": ["src/**/*"],
"compilerOptions": {
"esModuleInterop": true,
"declaration": true,
"outDir": "pkg/dist-types",
"emitDeclarationOnly": true,
"sourceMap": true
}
}
================================================
FILE: vite.config.js
================================================
import { defineConfig } from "vite";
export default defineConfig({
test: {
coverage: {
include: ["src/**/*.ts"],
reporter: ["html"],
thresholds: {
100: true,
},
},
},
});
gitextract_d81oa9rl/ ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug.yml │ │ ├── documentation.yml │ │ ├── feature.yml │ │ └── maintenance.yml │ ├── pull_request_template.md │ ├── renovate.json │ └── workflows/ │ ├── add_to_octokit_project.yml │ ├── codeql.yml │ ├── immediate-response.yml │ ├── release.yml │ ├── test.yml │ └── update-prettier.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── MAINTAINING.md ├── README.md ├── SECURITY.md ├── package.json ├── scripts/ │ └── build.mjs ├── src/ │ ├── app.ts │ ├── index.ts │ ├── octokit.ts │ └── version.ts ├── test/ │ ├── app.test.ts │ ├── smoke.test.ts │ ├── tsconfig.test.json │ └── typescript-validate.ts ├── tsconfig.json └── vite.config.js
SYMBOL INDEX (15 symbols across 6 files)
FILE: scripts/build.mjs
function main (line 20) | async function main() {
FILE: src/app.ts
type App (line 7) | type App = InstanceType<typeof App>;
type OAuthApp (line 10) | type OAuthApp = InstanceType<typeof OAuthApp>;
FILE: src/octokit.ts
type Octokit (line 31) | type Octokit = InstanceType<typeof Octokit>;
function onRateLimit (line 34) | function onRateLimit(
function onSecondaryRateLimit (line 51) | function onSecondaryRateLimit(
FILE: src/version.ts
constant VERSION (line 1) | const VERSION = "0.0.0-development";
FILE: test/app.test.ts
constant APP_ID (line 9) | const APP_ID = 1;
constant PRIVATE_KEY (line 10) | const PRIVATE_KEY = `-----BEGIN RSA PRIVATE KEY-----
constant CLIENT_ID (line 37) | const CLIENT_ID = "lv1.1234567890abcdef";
constant CLIENT_SECRET (line 38) | const CLIENT_SECRET = "1234567890abcdef1234567890abcdef12345678";
constant WEBHOOK_SECRET (line 39) | const WEBHOOK_SECRET = "secret";
constant BEARER (line 41) | const BEARER =
FILE: test/typescript-validate.ts
function expect (line 7) | function expect<T>(what: T) {}
function OctokitTest (line 9) | async function OctokitTest() {
Condensed preview — 31 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (83K chars).
[
{
"path": ".github/ISSUE_TEMPLATE/bug.yml",
"chars": 1358,
"preview": "name: Bug\ndescription: File a bug report\ntitle: \"[BUG]: \"\nlabels: [\"Type: Bug\", \"Status: Triage\"]\nbody:\n - type: markdo"
},
{
"path": ".github/ISSUE_TEMPLATE/documentation.yml",
"chars": 1603,
"preview": "name: Documentation\ndescription: Update or add documentation\ntitle: \"[DOCS]: \"\nlabels: [\"Type: Documentation\", \"Status: "
},
{
"path": ".github/ISSUE_TEMPLATE/feature.yml",
"chars": 1645,
"preview": "name: Feature\ndescription: Suggest an idea for a new feature or enhancement\ntitle: \"[FEAT]: \"\nlabels: [\"Type: Feature\", "
},
{
"path": ".github/ISSUE_TEMPLATE/maintenance.yml",
"chars": 1623,
"preview": "name: Maintenance\ndescription: Dependencies, cleanup, refactoring, reworking of code\ntitle: \"[MAINT]: \"\nlabels: [\"Type: "
},
{
"path": ".github/pull_request_template.md",
"chars": 880,
"preview": "<!-- Please refer to our contributing docs for any questions on submitting a pull request -->\n<!-- Issues are required f"
},
{
"path": ".github/renovate.json",
"chars": 52,
"preview": "{\n \"extends\": [\n \"github>octokit/.github\"\n ]\n}\n"
},
{
"path": ".github/workflows/add_to_octokit_project.yml",
"chars": 529,
"preview": "name: Add PRs and issues to Octokit org project\n\non:\n issues:\n types: [reopened, opened]\n pull_request_target:\n "
},
{
"path": ".github/workflows/codeql.yml",
"chars": 853,
"preview": "name: \"CodeQL\"\n\non:\n push:\n branches: [ \"main\", beta ]\n pull_request:\n # The branches below must be a subset of "
},
{
"path": ".github/workflows/immediate-response.yml",
"chars": 1359,
"preview": "name: Issue/PR response\npermissions:\n issues: write\n pull-requests: write\non:\n issues:\n types:\n - opened\n pu"
},
{
"path": ".github/workflows/release.yml",
"chars": 903,
"preview": "name: Release\n\"on\":\n push:\n branches:\n - main\n - next\n - beta\n - \"*.x\"\n - debug\n# These are"
},
{
"path": ".github/workflows/test.yml",
"chars": 936,
"preview": "name: Test\n\"on\":\n push:\n branches:\n - main\n pull_request:\n types:\n - opened\n - synchronize\njobs:\n"
},
{
"path": ".github/workflows/update-prettier.yml",
"chars": 675,
"preview": "name: Update Prettier\n\"on\":\n push:\n branches:\n - renovate/prettier-*\n workflow_dispatch: {}\njobs:\n update_pre"
},
{
"path": ".gitignore",
"chars": 36,
"preview": "coverage/\nnode_modules/\npkg/\n.idea/\n"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 3242,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
},
{
"path": "CONTRIBUTING.md",
"chars": 2604,
"preview": "# How to contribute\n\nPlease note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md)."
},
{
"path": "LICENSE",
"chars": 1081,
"preview": "The MIT License\n\nCopyright (c) 2023 Octokit contributors\n\nPermission is hereby granted, free of charge, to any person ob"
},
{
"path": "MAINTAINING.md",
"chars": 5495,
"preview": "# Maintenance releases\n\n## Merging the Pull Request & releasing a new version\n\nReleases are automated using [semantic-re"
},
{
"path": "README.md",
"chars": 35228,
"preview": "# octokit.js\n\n> The all-batteries-included GitHub SDK for Browsers, Node.js, and Deno.\n\nThe `octokit` package integrates"
},
{
"path": "SECURITY.md",
"chars": 893,
"preview": "# Security Policy\n\nThanks for helping make GitHub Open Source Software safe for everyone.\n\nGitHub takes the security of "
},
{
"path": "package.json",
"chars": 2535,
"preview": "{\n \"name\": \"octokit\",\n \"version\": \"0.0.0-development\",\n \"type\": \"module\",\n \"description\": \"The all-batteries-include"
},
{
"path": "scripts/build.mjs",
"chars": 2000,
"preview": "// @ts-check\nimport esbuild from \"esbuild\";\nimport { copyFile, readFile, writeFile, rm } from \"node:fs/promises\";\nimport"
},
{
"path": "src/app.ts",
"chars": 427,
"preview": "import { App as DefaultApp } from \"@octokit/app\";\nimport { OAuthApp as DefaultOAuthApp } from \"@octokit/oauth-app\";\n\nimp"
},
{
"path": "src/index.ts",
"chars": 189,
"preview": "export { Octokit, RequestError } from \"./octokit.js\";\nexport type { PageInfoForward, PageInfoBackward } from \"./octokit."
},
{
"path": "src/octokit.ts",
"chars": 1866,
"preview": "import { Octokit as OctokitCore } from \"@octokit/core\";\nimport { paginateRest } from \"@octokit/plugin-paginate-rest\";\nim"
},
{
"path": "src/version.ts",
"chars": 44,
"preview": "export const VERSION = \"0.0.0-development\";\n"
},
{
"path": "test/app.test.ts",
"chars": 7377,
"preview": "import { beforeEach, describe, expect, test } from \"vitest\";\nimport { createServer } from \"node:http\";\n\nimport nock from"
},
{
"path": "test/smoke.test.ts",
"chars": 1605,
"preview": "import { describe, expect, it } from \"vitest\";\nimport { Octokit, App, OAuthApp, RequestError } from \"../src/index.ts\";\n\n"
},
{
"path": "test/tsconfig.test.json",
"chars": 219,
"preview": "{\n \"extends\": \"../tsconfig.json\",\n \"compilerOptions\": {\n \"emitDeclarationOnly\": false,\n \"noEmit\": true,\n \"ver"
},
{
"path": "test/typescript-validate.ts",
"chars": 988,
"preview": "// ************************************************************\n// THIS CODE IS NOT EXECUTED. IT IS JUST FOR TYPECHECKIN"
},
{
"path": "tsconfig.json",
"chars": 233,
"preview": "{\n \"extends\": \"@octokit/tsconfig\",\n \"include\": [\"src/**/*\"],\n \"compilerOptions\": {\n \"esModuleInterop\": true,\n \""
},
{
"path": "vite.config.js",
"chars": 216,
"preview": "import { defineConfig } from \"vite\";\n\nexport default defineConfig({\n test: {\n coverage: {\n include: [\"src/**/*."
}
]
About this extraction
This page contains the full source code of the octokit/octokit.js GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 31 files (76.8 KB), approximately 20.3k tokens, and a symbol index with 15 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.