コード
古い issue の一覧をチャットに通知するツールを作成しておりまして、その一環として書いたコードです。
組織(ユーザー)名、リポジトリ名はクエリパラメータに設定するなど複数パターンがあるようですが、今回は下記URLでアクセスしました。
[GET] https://api.github.com/orgs/{org}/issues
コードは下記の通りです。
import fetch from 'isomorphic-unfetch';
import { Issue, State } from './types/vendor';
export async function get_issues(
owner: string,
repository: string,
api_token: string,
state: State // `State`の方は`'open' | 'closed' | 'all'`です。
): Promise<Issue[]> {
const response = await fetch(
`https://api.github.com/repos/${owner}/${repository}/issues` +
`?state=${state}`,
{
headers: {
Authorization: `token ${api_token}`,
Accept: 'application/vnd.github.v3+json',
},
}
);
if (response.status != 200) {
throw new Error(
`GitHub API にアクセスできませんでした: ${JSON.stringify(
await response.json(),
null,
' '
)}`
);
}
return (await response.json()) as Issue[];
}
Node.js 環境でも ブラウザ環境でも動くfetchを使用するためにisomorphic-unfetch
を使用しています。
# yarn の場合
$ yarn add isomorphic-unfetch
# npm の場合
$ npm install isomorphic-unfetch
Issue
の型は QuickType でinterface
自動生成してtype
に差し替えました。
型の詳しい内容は下記の実際のソースをご確認ください。
https://github.com/sugu-sano/notify-old-issues/blob/master/src/types/vendor/isssue.ts
今回は不要でしたので設定しませんでしたが、クエリパラメータにはsort
(並び順)、since
(指定された時間以降に更新された)もありました。詳しくは下記公式ドキュメントを参照ください。
List repository issues - GitHub Docs
https://docs.github.com/en/free-pro-team@latest/rest/reference/issues#list-repository-issues
Octkit という GitHub 公式の REST クライアントが存在した
生のfetch API
でアクセスしていましたが GitHub にはOctokit
という公式クライアントがありました。
また型定義も提供されていてパラメータやレスポンスの型は自作しなくてもタイプセーフに扱うことができます。
# yarn の場合
$ yarn add @octokit/core @octokit/types
# npm の場合
$ npm install @octokit/core @octokit/types
import { Octokit } from "@octokit/core";
import { Endpoints } from "@octokit/types";
async function main() {
// 型の取得の仕方に若干クセがある
type route = "GET /repos/:owner/:repo/issues";
type Response = Endpoints[route]["response"];
type Parameters = Endpoints[route]["parameters"];
const params: Parameters = {
owner: "octocat",
repo: "hello-world",
since: "2020-11-20T00:00:00",
};
const octokit = new Octokit();
// 戻り値が `OctokitResponse<any>` にならないように型注釈
const response: Response = await octokit.request(
"GET /repos/{owner}/{repo}/issues",
params
);
console.log(response.data); // `any` でなく `IssuesListForRepoResponseData` 型になる
}
main();
実行すると下記レスポンスが確認できました。
レスポンス(長いので折りたたみ)
[
{
url: 'https://api.github.com/repos/octocat/Hello-World/issues/812',
repository_url: 'https://api.github.com/repos/octocat/Hello-World',
labels_url: 'https://api.github.com/repos/octocat/Hello-World/issues/812/labels{/name}',
comments_url: 'https://api.github.com/repos/octocat/Hello-World/issues/812/comments',
events_url: 'https://api.github.com/repos/octocat/Hello-World/issues/812/events',
html_url: 'https://github.com/octocat/Hello-World/issues/812',
id: 748885338,
node_id: 'MDU6SXNzdWU3NDg4ODUzMzg=',
number: 812,
title: 'Test title',
user: {
login: 'avihlbi',
id: 54238151,
node_id: 'MDQ6VXNlcjU0MjM4MTUx',
avatar_url: 'https://avatars0.githubusercontent.com/u/54238151?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/avihlbi',
html_url: 'https://github.com/avihlbi',
followers_url: 'https://api.github.com/users/avihlbi/followers',
following_url: 'https://api.github.com/users/avihlbi/following{/other_user}',
gists_url: 'https://api.github.com/users/avihlbi/gists{/gist_id}',
starred_url: 'https://api.github.com/users/avihlbi/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/avihlbi/subscriptions',
organizations_url: 'https://api.github.com/users/avihlbi/orgs',
repos_url: 'https://api.github.com/users/avihlbi/repos',
events_url: 'https://api.github.com/users/avihlbi/events{/privacy}',
received_events_url: 'https://api.github.com/users/avihlbi/received_events',
type: 'User',
site_admin: false
},
labels: [],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 1,
created_at: '2020-11-23T15:13:32Z',
updated_at: '2020-11-23T15:13:33Z',
closed_at: null,
author_association: 'NONE',
active_lock_reason: null,
body: 'Test description',
performed_via_github_app: null
},
{
url: 'https://api.github.com/repos/octocat/Hello-World/issues/810',
repository_url: 'https://api.github.com/repos/octocat/Hello-World',
labels_url: 'https://api.github.com/repos/octocat/Hello-World/issues/810/labels{/name}',
comments_url: 'https://api.github.com/repos/octocat/Hello-World/issues/810/comments',
events_url: 'https://api.github.com/repos/octocat/Hello-World/issues/810/events',
html_url: 'https://github.com/octocat/Hello-World/pull/810',
id: 747843269,
node_id: 'MDExOlB1bGxSZXF1ZXN0NTI0OTkzMTY0',
number: 810,
title: 'Test PR for Codespaces',
user: {
login: '2percentsilk',
id: 3174849,
node_id: 'MDQ6VXNlcjMxNzQ4NDk=',
avatar_url: 'https://avatars3.githubusercontent.com/u/3174849?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/2percentsilk',
html_url: 'https://github.com/2percentsilk',
followers_url: 'https://api.github.com/users/2percentsilk/followers',
following_url: 'https://api.github.com/users/2percentsilk/following{/other_user}',
gists_url: 'https://api.github.com/users/2percentsilk/gists{/gist_id}',
starred_url: 'https://api.github.com/users/2percentsilk/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/2percentsilk/subscriptions',
organizations_url: 'https://api.github.com/users/2percentsilk/orgs',
repos_url: 'https://api.github.com/users/2percentsilk/repos',
events_url: 'https://api.github.com/users/2percentsilk/events{/privacy}',
received_events_url: 'https://api.github.com/users/2percentsilk/received_events',
type: 'User',
site_admin: false
},
labels: [],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 0,
created_at: '2020-11-20T22:48:47Z',
updated_at: '2020-11-20T22:48:47Z',
closed_at: null,
author_association: 'NONE',
active_lock_reason: null,
pull_request: {
url: 'https://api.github.com/repos/octocat/Hello-World/pulls/810',
html_url: 'https://github.com/octocat/Hello-World/pull/810',
diff_url: 'https://github.com/octocat/Hello-World/pull/810.diff',
patch_url: 'https://github.com/octocat/Hello-World/pull/810.patch'
},
body: '',
performed_via_github_app: null
},
{
url: 'https://api.github.com/repos/octocat/Hello-World/issues/808',
repository_url: 'https://api.github.com/repos/octocat/Hello-World',
labels_url: 'https://api.github.com/repos/octocat/Hello-World/issues/808/labels{/name}',
comments_url: 'https://api.github.com/repos/octocat/Hello-World/issues/808/comments',
events_url: 'https://api.github.com/repos/octocat/Hello-World/issues/808/events',
html_url: 'https://github.com/octocat/Hello-World/issues/808',
id: 744550518,
node_id: 'MDU6SXNzdWU3NDQ1NTA1MTg=',
number: 808,
title: 'Click Here',
user: {
login: 'irfaardy',
id: 49023326,
node_id: 'MDQ6VXNlcjQ5MDIzMzI2',
avatar_url: 'https://avatars1.githubusercontent.com/u/49023326?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/irfaardy',
html_url: 'https://github.com/irfaardy',
followers_url: 'https://api.github.com/users/irfaardy/followers',
following_url: 'https://api.github.com/users/irfaardy/following{/other_user}',
gists_url: 'https://api.github.com/users/irfaardy/gists{/gist_id}',
starred_url: 'https://api.github.com/users/irfaardy/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/irfaardy/subscriptions',
organizations_url: 'https://api.github.com/users/irfaardy/orgs',
repos_url: 'https://api.github.com/users/irfaardy/repos',
events_url: 'https://api.github.com/users/irfaardy/events{/privacy}',
received_events_url: 'https://api.github.com/users/irfaardy/received_events',
type: 'User',
site_admin: false
},
labels: [],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 1,
created_at: '2020-11-17T09:09:54Z',
updated_at: '2020-11-23T09:43:57Z',
closed_at: null,
author_association: 'NONE',
active_lock_reason: null,
body: 'I love you\r\n\r\n----\r\n[Click Here](https://github.com/irfaardy)',
performed_via_github_app: null
},
{
url: 'https://api.github.com/repos/octocat/Hello-World/issues/576',
repository_url: 'https://api.github.com/repos/octocat/Hello-World',
labels_url: 'https://api.github.com/repos/octocat/Hello-World/issues/576/labels{/name}',
comments_url: 'https://api.github.com/repos/octocat/Hello-World/issues/576/comments',
events_url: 'https://api.github.com/repos/octocat/Hello-World/issues/576/events',
html_url: 'https://github.com/octocat/Hello-World/pull/576',
id: 515476262,
node_id: 'MDExOlB1bGxSZXF1ZXN0MzM0OTMzMjIy',
number: 576,
title: 'Update README',
user: {
login: 'NX007KTR',
id: 41190306,
node_id: 'MDQ6VXNlcjQxMTkwMzA2',
avatar_url: 'https://avatars3.githubusercontent.com/u/41190306?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/NX007KTR',
html_url: 'https://github.com/NX007KTR',
followers_url: 'https://api.github.com/users/NX007KTR/followers',
following_url: 'https://api.github.com/users/NX007KTR/following{/other_user}',
gists_url: 'https://api.github.com/users/NX007KTR/gists{/gist_id}',
starred_url: 'https://api.github.com/users/NX007KTR/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/NX007KTR/subscriptions',
organizations_url: 'https://api.github.com/users/NX007KTR/orgs',
repos_url: 'https://api.github.com/users/NX007KTR/repos',
events_url: 'https://api.github.com/users/NX007KTR/events{/privacy}',
received_events_url: 'https://api.github.com/users/NX007KTR/received_events',
type: 'User',
site_admin: false
},
labels: [],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 1,
created_at: '2019-10-31T14:26:43Z',
updated_at: '2020-11-29T05:03:18Z',
closed_at: null,
author_association: 'NONE',
active_lock_reason: null,
pull_request: {
url: 'https://api.github.com/repos/octocat/Hello-World/pulls/576',
html_url: 'https://github.com/octocat/Hello-World/pull/576',
diff_url: 'https://github.com/octocat/Hello-World/pull/576.diff',
patch_url: 'https://github.com/octocat/Hello-World/pull/576.patch'
},
body: '',
performed_via_github_app: null
}
]