2023-12-19 14:36:33 +00:00
|
|
|
const VERSION = "2.21.3";
|
2022-01-21 08:28:41 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Some “list” response that can be paginated have a different response structure
|
|
|
|
*
|
|
|
|
* They have a `total_count` key in the response (search also has `incomplete_results`,
|
|
|
|
* /installation/repositories also has `repository_selection`), as well as a key with
|
2023-12-19 14:36:33 +00:00
|
|
|
* the list of the items which name varies from endpoint to endpoint.
|
2022-01-21 08:28:41 +00:00
|
|
|
*
|
|
|
|
* Octokit normalizes these responses so that paginated results are always returned following
|
|
|
|
* the same structure. One challenge is that if the list response has only one page, no Link
|
|
|
|
* header is provided, so this header alone is not sufficient to check wether a response is
|
2023-12-19 14:36:33 +00:00
|
|
|
* paginated or not.
|
|
|
|
*
|
|
|
|
* We check if a "total_count" key is present in the response data, but also make sure that
|
|
|
|
* a "url" property is not, as the "Get the combined status for a specific ref" endpoint would
|
|
|
|
* otherwise match: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref
|
2022-01-21 08:28:41 +00:00
|
|
|
*/
|
2023-12-19 14:36:33 +00:00
|
|
|
function normalizePaginatedListResponse(response) {
|
|
|
|
// endpoints can respond with 204 if repository is empty
|
|
|
|
if (!response.data) {
|
|
|
|
return {
|
|
|
|
...response,
|
|
|
|
data: [],
|
|
|
|
};
|
|
|
|
}
|
|
|
|
const responseNeedsNormalization = "total_count" in response.data && !("url" in response.data);
|
2022-01-21 08:28:41 +00:00
|
|
|
if (!responseNeedsNormalization)
|
2023-12-19 14:36:33 +00:00
|
|
|
return response;
|
2022-01-21 08:28:41 +00:00
|
|
|
// keep the additional properties intact as there is currently no other way
|
|
|
|
// to retrieve the same information.
|
|
|
|
const incompleteResults = response.data.incomplete_results;
|
|
|
|
const repositorySelection = response.data.repository_selection;
|
|
|
|
const totalCount = response.data.total_count;
|
|
|
|
delete response.data.incomplete_results;
|
|
|
|
delete response.data.repository_selection;
|
|
|
|
delete response.data.total_count;
|
|
|
|
const namespaceKey = Object.keys(response.data)[0];
|
|
|
|
const data = response.data[namespaceKey];
|
|
|
|
response.data = data;
|
|
|
|
if (typeof incompleteResults !== "undefined") {
|
|
|
|
response.data.incomplete_results = incompleteResults;
|
|
|
|
}
|
|
|
|
if (typeof repositorySelection !== "undefined") {
|
|
|
|
response.data.repository_selection = repositorySelection;
|
|
|
|
}
|
|
|
|
response.data.total_count = totalCount;
|
2023-12-19 14:36:33 +00:00
|
|
|
return response;
|
2022-01-21 08:28:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function iterator(octokit, route, parameters) {
|
2023-12-19 14:36:33 +00:00
|
|
|
const options = typeof route === "function"
|
|
|
|
? route.endpoint(parameters)
|
|
|
|
: octokit.request.endpoint(route, parameters);
|
|
|
|
const requestMethod = typeof route === "function" ? route : octokit.request;
|
2022-01-21 08:28:41 +00:00
|
|
|
const method = options.method;
|
|
|
|
const headers = options.headers;
|
|
|
|
let url = options.url;
|
|
|
|
return {
|
|
|
|
[Symbol.asyncIterator]: () => ({
|
2023-12-19 14:36:33 +00:00
|
|
|
async next() {
|
|
|
|
if (!url)
|
|
|
|
return { done: true };
|
|
|
|
try {
|
|
|
|
const response = await requestMethod({ method, url, headers });
|
|
|
|
const normalizedResponse = normalizePaginatedListResponse(response);
|
2022-01-21 08:28:41 +00:00
|
|
|
// `response.headers.link` format:
|
|
|
|
// '<https://api.github.com/users/aseemk/followers?page=2>; rel="next", <https://api.github.com/users/aseemk/followers?page=2>; rel="last"'
|
|
|
|
// sets `url` to undefined if "next" URL is not present or `link` header is not set
|
2023-12-19 14:36:33 +00:00
|
|
|
url = ((normalizedResponse.headers.link || "").match(/<([^>]+)>;\s*rel="next"/) || [])[1];
|
|
|
|
return { value: normalizedResponse };
|
|
|
|
}
|
|
|
|
catch (error) {
|
|
|
|
if (error.status !== 409)
|
|
|
|
throw error;
|
|
|
|
url = "";
|
|
|
|
return {
|
|
|
|
value: {
|
|
|
|
status: 200,
|
|
|
|
headers: {},
|
|
|
|
data: [],
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}),
|
2022-01-21 08:28:41 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function paginate(octokit, route, parameters, mapFn) {
|
|
|
|
if (typeof parameters === "function") {
|
|
|
|
mapFn = parameters;
|
|
|
|
parameters = undefined;
|
|
|
|
}
|
|
|
|
return gather(octokit, [], iterator(octokit, route, parameters)[Symbol.asyncIterator](), mapFn);
|
|
|
|
}
|
|
|
|
function gather(octokit, results, iterator, mapFn) {
|
2023-12-19 14:36:33 +00:00
|
|
|
return iterator.next().then((result) => {
|
2022-01-21 08:28:41 +00:00
|
|
|
if (result.done) {
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
let earlyExit = false;
|
|
|
|
function done() {
|
|
|
|
earlyExit = true;
|
|
|
|
}
|
|
|
|
results = results.concat(mapFn ? mapFn(result.value, done) : result.value.data);
|
|
|
|
if (earlyExit) {
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
return gather(octokit, results, iterator, mapFn);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-12-19 14:36:33 +00:00
|
|
|
const composePaginateRest = Object.assign(paginate, {
|
|
|
|
iterator,
|
|
|
|
});
|
|
|
|
|
|
|
|
const paginatingEndpoints = [
|
|
|
|
"GET /app/hook/deliveries",
|
|
|
|
"GET /app/installations",
|
|
|
|
"GET /applications/grants",
|
|
|
|
"GET /authorizations",
|
|
|
|
"GET /enterprises/{enterprise}/actions/permissions/organizations",
|
|
|
|
"GET /enterprises/{enterprise}/actions/runner-groups",
|
|
|
|
"GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations",
|
|
|
|
"GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/runners",
|
|
|
|
"GET /enterprises/{enterprise}/actions/runners",
|
|
|
|
"GET /enterprises/{enterprise}/audit-log",
|
|
|
|
"GET /enterprises/{enterprise}/secret-scanning/alerts",
|
|
|
|
"GET /enterprises/{enterprise}/settings/billing/advanced-security",
|
|
|
|
"GET /events",
|
|
|
|
"GET /gists",
|
|
|
|
"GET /gists/public",
|
|
|
|
"GET /gists/starred",
|
|
|
|
"GET /gists/{gist_id}/comments",
|
|
|
|
"GET /gists/{gist_id}/commits",
|
|
|
|
"GET /gists/{gist_id}/forks",
|
|
|
|
"GET /installation/repositories",
|
|
|
|
"GET /issues",
|
|
|
|
"GET /licenses",
|
|
|
|
"GET /marketplace_listing/plans",
|
|
|
|
"GET /marketplace_listing/plans/{plan_id}/accounts",
|
|
|
|
"GET /marketplace_listing/stubbed/plans",
|
|
|
|
"GET /marketplace_listing/stubbed/plans/{plan_id}/accounts",
|
|
|
|
"GET /networks/{owner}/{repo}/events",
|
|
|
|
"GET /notifications",
|
|
|
|
"GET /organizations",
|
|
|
|
"GET /orgs/{org}/actions/cache/usage-by-repository",
|
|
|
|
"GET /orgs/{org}/actions/permissions/repositories",
|
|
|
|
"GET /orgs/{org}/actions/runner-groups",
|
|
|
|
"GET /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories",
|
|
|
|
"GET /orgs/{org}/actions/runner-groups/{runner_group_id}/runners",
|
|
|
|
"GET /orgs/{org}/actions/runners",
|
|
|
|
"GET /orgs/{org}/actions/secrets",
|
|
|
|
"GET /orgs/{org}/actions/secrets/{secret_name}/repositories",
|
|
|
|
"GET /orgs/{org}/audit-log",
|
|
|
|
"GET /orgs/{org}/blocks",
|
|
|
|
"GET /orgs/{org}/code-scanning/alerts",
|
|
|
|
"GET /orgs/{org}/codespaces",
|
|
|
|
"GET /orgs/{org}/credential-authorizations",
|
|
|
|
"GET /orgs/{org}/dependabot/secrets",
|
|
|
|
"GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories",
|
|
|
|
"GET /orgs/{org}/events",
|
|
|
|
"GET /orgs/{org}/external-groups",
|
|
|
|
"GET /orgs/{org}/failed_invitations",
|
|
|
|
"GET /orgs/{org}/hooks",
|
|
|
|
"GET /orgs/{org}/hooks/{hook_id}/deliveries",
|
|
|
|
"GET /orgs/{org}/installations",
|
|
|
|
"GET /orgs/{org}/invitations",
|
|
|
|
"GET /orgs/{org}/invitations/{invitation_id}/teams",
|
|
|
|
"GET /orgs/{org}/issues",
|
|
|
|
"GET /orgs/{org}/members",
|
|
|
|
"GET /orgs/{org}/migrations",
|
|
|
|
"GET /orgs/{org}/migrations/{migration_id}/repositories",
|
|
|
|
"GET /orgs/{org}/outside_collaborators",
|
|
|
|
"GET /orgs/{org}/packages",
|
|
|
|
"GET /orgs/{org}/packages/{package_type}/{package_name}/versions",
|
|
|
|
"GET /orgs/{org}/projects",
|
|
|
|
"GET /orgs/{org}/public_members",
|
|
|
|
"GET /orgs/{org}/repos",
|
|
|
|
"GET /orgs/{org}/secret-scanning/alerts",
|
|
|
|
"GET /orgs/{org}/settings/billing/advanced-security",
|
|
|
|
"GET /orgs/{org}/team-sync/groups",
|
|
|
|
"GET /orgs/{org}/teams",
|
|
|
|
"GET /orgs/{org}/teams/{team_slug}/discussions",
|
|
|
|
"GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments",
|
|
|
|
"GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions",
|
|
|
|
"GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions",
|
|
|
|
"GET /orgs/{org}/teams/{team_slug}/invitations",
|
|
|
|
"GET /orgs/{org}/teams/{team_slug}/members",
|
|
|
|
"GET /orgs/{org}/teams/{team_slug}/projects",
|
|
|
|
"GET /orgs/{org}/teams/{team_slug}/repos",
|
|
|
|
"GET /orgs/{org}/teams/{team_slug}/teams",
|
|
|
|
"GET /projects/columns/{column_id}/cards",
|
|
|
|
"GET /projects/{project_id}/collaborators",
|
|
|
|
"GET /projects/{project_id}/columns",
|
|
|
|
"GET /repos/{owner}/{repo}/actions/artifacts",
|
|
|
|
"GET /repos/{owner}/{repo}/actions/caches",
|
|
|
|
"GET /repos/{owner}/{repo}/actions/runners",
|
|
|
|
"GET /repos/{owner}/{repo}/actions/runs",
|
|
|
|
"GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts",
|
|
|
|
"GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs",
|
|
|
|
"GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs",
|
|
|
|
"GET /repos/{owner}/{repo}/actions/secrets",
|
|
|
|
"GET /repos/{owner}/{repo}/actions/workflows",
|
|
|
|
"GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs",
|
|
|
|
"GET /repos/{owner}/{repo}/assignees",
|
|
|
|
"GET /repos/{owner}/{repo}/branches",
|
|
|
|
"GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations",
|
|
|
|
"GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs",
|
|
|
|
"GET /repos/{owner}/{repo}/code-scanning/alerts",
|
|
|
|
"GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances",
|
|
|
|
"GET /repos/{owner}/{repo}/code-scanning/analyses",
|
|
|
|
"GET /repos/{owner}/{repo}/codespaces",
|
|
|
|
"GET /repos/{owner}/{repo}/codespaces/devcontainers",
|
|
|
|
"GET /repos/{owner}/{repo}/codespaces/secrets",
|
|
|
|
"GET /repos/{owner}/{repo}/collaborators",
|
|
|
|
"GET /repos/{owner}/{repo}/comments",
|
|
|
|
"GET /repos/{owner}/{repo}/comments/{comment_id}/reactions",
|
|
|
|
"GET /repos/{owner}/{repo}/commits",
|
|
|
|
"GET /repos/{owner}/{repo}/commits/{commit_sha}/comments",
|
|
|
|
"GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls",
|
|
|
|
"GET /repos/{owner}/{repo}/commits/{ref}/check-runs",
|
|
|
|
"GET /repos/{owner}/{repo}/commits/{ref}/check-suites",
|
|
|
|
"GET /repos/{owner}/{repo}/commits/{ref}/status",
|
|
|
|
"GET /repos/{owner}/{repo}/commits/{ref}/statuses",
|
|
|
|
"GET /repos/{owner}/{repo}/contributors",
|
|
|
|
"GET /repos/{owner}/{repo}/dependabot/secrets",
|
|
|
|
"GET /repos/{owner}/{repo}/deployments",
|
|
|
|
"GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses",
|
|
|
|
"GET /repos/{owner}/{repo}/environments",
|
|
|
|
"GET /repos/{owner}/{repo}/events",
|
|
|
|
"GET /repos/{owner}/{repo}/forks",
|
|
|
|
"GET /repos/{owner}/{repo}/git/matching-refs/{ref}",
|
|
|
|
"GET /repos/{owner}/{repo}/hooks",
|
|
|
|
"GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries",
|
|
|
|
"GET /repos/{owner}/{repo}/invitations",
|
|
|
|
"GET /repos/{owner}/{repo}/issues",
|
|
|
|
"GET /repos/{owner}/{repo}/issues/comments",
|
|
|
|
"GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions",
|
|
|
|
"GET /repos/{owner}/{repo}/issues/events",
|
|
|
|
"GET /repos/{owner}/{repo}/issues/{issue_number}/comments",
|
|
|
|
"GET /repos/{owner}/{repo}/issues/{issue_number}/events",
|
|
|
|
"GET /repos/{owner}/{repo}/issues/{issue_number}/labels",
|
|
|
|
"GET /repos/{owner}/{repo}/issues/{issue_number}/reactions",
|
|
|
|
"GET /repos/{owner}/{repo}/issues/{issue_number}/timeline",
|
|
|
|
"GET /repos/{owner}/{repo}/keys",
|
|
|
|
"GET /repos/{owner}/{repo}/labels",
|
|
|
|
"GET /repos/{owner}/{repo}/milestones",
|
|
|
|
"GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels",
|
|
|
|
"GET /repos/{owner}/{repo}/notifications",
|
|
|
|
"GET /repos/{owner}/{repo}/pages/builds",
|
|
|
|
"GET /repos/{owner}/{repo}/projects",
|
|
|
|
"GET /repos/{owner}/{repo}/pulls",
|
|
|
|
"GET /repos/{owner}/{repo}/pulls/comments",
|
|
|
|
"GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions",
|
|
|
|
"GET /repos/{owner}/{repo}/pulls/{pull_number}/comments",
|
|
|
|
"GET /repos/{owner}/{repo}/pulls/{pull_number}/commits",
|
|
|
|
"GET /repos/{owner}/{repo}/pulls/{pull_number}/files",
|
|
|
|
"GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers",
|
|
|
|
"GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews",
|
|
|
|
"GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments",
|
|
|
|
"GET /repos/{owner}/{repo}/releases",
|
|
|
|
"GET /repos/{owner}/{repo}/releases/{release_id}/assets",
|
|
|
|
"GET /repos/{owner}/{repo}/releases/{release_id}/reactions",
|
|
|
|
"GET /repos/{owner}/{repo}/secret-scanning/alerts",
|
|
|
|
"GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations",
|
|
|
|
"GET /repos/{owner}/{repo}/stargazers",
|
|
|
|
"GET /repos/{owner}/{repo}/subscribers",
|
|
|
|
"GET /repos/{owner}/{repo}/tags",
|
|
|
|
"GET /repos/{owner}/{repo}/teams",
|
|
|
|
"GET /repos/{owner}/{repo}/topics",
|
|
|
|
"GET /repositories",
|
|
|
|
"GET /repositories/{repository_id}/environments/{environment_name}/secrets",
|
|
|
|
"GET /search/code",
|
|
|
|
"GET /search/commits",
|
|
|
|
"GET /search/issues",
|
|
|
|
"GET /search/labels",
|
|
|
|
"GET /search/repositories",
|
|
|
|
"GET /search/topics",
|
|
|
|
"GET /search/users",
|
|
|
|
"GET /teams/{team_id}/discussions",
|
|
|
|
"GET /teams/{team_id}/discussions/{discussion_number}/comments",
|
|
|
|
"GET /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions",
|
|
|
|
"GET /teams/{team_id}/discussions/{discussion_number}/reactions",
|
|
|
|
"GET /teams/{team_id}/invitations",
|
|
|
|
"GET /teams/{team_id}/members",
|
|
|
|
"GET /teams/{team_id}/projects",
|
|
|
|
"GET /teams/{team_id}/repos",
|
|
|
|
"GET /teams/{team_id}/teams",
|
|
|
|
"GET /user/blocks",
|
|
|
|
"GET /user/codespaces",
|
|
|
|
"GET /user/codespaces/secrets",
|
|
|
|
"GET /user/emails",
|
|
|
|
"GET /user/followers",
|
|
|
|
"GET /user/following",
|
|
|
|
"GET /user/gpg_keys",
|
|
|
|
"GET /user/installations",
|
|
|
|
"GET /user/installations/{installation_id}/repositories",
|
|
|
|
"GET /user/issues",
|
|
|
|
"GET /user/keys",
|
|
|
|
"GET /user/marketplace_purchases",
|
|
|
|
"GET /user/marketplace_purchases/stubbed",
|
|
|
|
"GET /user/memberships/orgs",
|
|
|
|
"GET /user/migrations",
|
|
|
|
"GET /user/migrations/{migration_id}/repositories",
|
|
|
|
"GET /user/orgs",
|
|
|
|
"GET /user/packages",
|
|
|
|
"GET /user/packages/{package_type}/{package_name}/versions",
|
|
|
|
"GET /user/public_emails",
|
|
|
|
"GET /user/repos",
|
|
|
|
"GET /user/repository_invitations",
|
|
|
|
"GET /user/starred",
|
|
|
|
"GET /user/subscriptions",
|
|
|
|
"GET /user/teams",
|
|
|
|
"GET /users",
|
|
|
|
"GET /users/{username}/events",
|
|
|
|
"GET /users/{username}/events/orgs/{org}",
|
|
|
|
"GET /users/{username}/events/public",
|
|
|
|
"GET /users/{username}/followers",
|
|
|
|
"GET /users/{username}/following",
|
|
|
|
"GET /users/{username}/gists",
|
|
|
|
"GET /users/{username}/gpg_keys",
|
|
|
|
"GET /users/{username}/keys",
|
|
|
|
"GET /users/{username}/orgs",
|
|
|
|
"GET /users/{username}/packages",
|
|
|
|
"GET /users/{username}/projects",
|
|
|
|
"GET /users/{username}/received_events",
|
|
|
|
"GET /users/{username}/received_events/public",
|
|
|
|
"GET /users/{username}/repos",
|
|
|
|
"GET /users/{username}/starred",
|
|
|
|
"GET /users/{username}/subscriptions",
|
|
|
|
];
|
|
|
|
|
|
|
|
function isPaginatingEndpoint(arg) {
|
|
|
|
if (typeof arg === "string") {
|
|
|
|
return paginatingEndpoints.includes(arg);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-21 08:28:41 +00:00
|
|
|
/**
|
|
|
|
* @param octokit Octokit instance
|
|
|
|
* @param options Options passed to Octokit constructor
|
|
|
|
*/
|
|
|
|
function paginateRest(octokit) {
|
|
|
|
return {
|
|
|
|
paginate: Object.assign(paginate.bind(null, octokit), {
|
2023-12-19 14:36:33 +00:00
|
|
|
iterator: iterator.bind(null, octokit),
|
|
|
|
}),
|
2022-01-21 08:28:41 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
paginateRest.VERSION = VERSION;
|
|
|
|
|
2023-12-19 14:36:33 +00:00
|
|
|
export { composePaginateRest, isPaginatingEndpoint, paginateRest, paginatingEndpoints };
|
2022-01-21 08:28:41 +00:00
|
|
|
//# sourceMappingURL=index.js.map
|