blob: e664142ae96f6b3405d22c8a1e55cbb0c7a77f5e [file] [log] [blame]
/**
* 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
* the list of the items which name varies from endpoint to endpoint:
*
* - https://developer.github.com/v3/search/#example (key `items`)
* - https://developer.github.com/v3/checks/runs/#response-3 (key: `check_runs`)
* - https://developer.github.com/v3/checks/suites/#response-1 (key: `check_suites`)
* - https://developer.github.com/v3/apps/installations/#list-repositories (key: `repositories`)
* - https://developer.github.com/v3/apps/installations/#list-installations-for-a-user (key `installations`)
* - https://developer.github.com/v3/orgs/#list-installations-for-an-organization (key `installations`)
*
* 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
* paginated or not. For the exceptions with the namespace, a fallback check for the route
* paths has to be added in order to normalize the response. We cannot check for the total_count
* property because it also exists in the response of Get the combined status for a specific ref.
*/
module.exports = normalizePaginatedListResponse;
const { Deprecation } = require("deprecation");
const once = require("once");
const deprecateIncompleteResults = once((log, deprecation) =>
log.warn(deprecation)
);
const deprecateTotalCount = once((log, deprecation) => log.warn(deprecation));
const deprecateNamespace = once((log, deprecation) => log.warn(deprecation));
const REGEX_IS_SEARCH_PATH = /^\/search\//;
const REGEX_IS_CHECKS_PATH = /^\/repos\/[^/]+\/[^/]+\/commits\/[^/]+\/(check-runs|check-suites)/;
const REGEX_IS_INSTALLATION_REPOSITORIES_PATH = /^\/installation\/repositories/;
const REGEX_IS_USER_INSTALLATIONS_PATH = /^\/user\/installations/;
const REGEX_IS_ORG_INSTALLATIONS_PATH = /^\/orgs\/[^/]+\/installations/;
function normalizePaginatedListResponse(octokit, url, response) {
const path = url.replace(octokit.request.endpoint.DEFAULTS.baseUrl, "");
if (
!REGEX_IS_SEARCH_PATH.test(path) &&
!REGEX_IS_CHECKS_PATH.test(path) &&
!REGEX_IS_INSTALLATION_REPOSITORIES_PATH.test(path) &&
!REGEX_IS_USER_INSTALLATIONS_PATH.test(path) &&
!REGEX_IS_ORG_INSTALLATIONS_PATH.test(path)
) {
return;
}
// keep the additional properties intact to avoid a breaking change,
// but log a deprecation warning when accessed
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];
response.data = response.data[namespaceKey];
Object.defineProperty(response.data, namespaceKey, {
get() {
deprecateNamespace(
octokit.log,
new Deprecation(
`[@octokit/rest] "result.data.${namespaceKey}" is deprecated. Use "result.data" instead`
)
);
return response.data;
}
});
if (typeof incompleteResults !== "undefined") {
Object.defineProperty(response.data, "incomplete_results", {
get() {
deprecateIncompleteResults(
octokit.log,
new Deprecation(
'[@octokit/rest] "result.data.incomplete_results" is deprecated.'
)
);
return incompleteResults;
}
});
}
if (typeof repositorySelection !== "undefined") {
Object.defineProperty(response.data, "repository_selection", {
get() {
deprecateTotalCount(
octokit.log,
new Deprecation(
'[@octokit/rest] "result.data.repository_selection" is deprecated.'
)
);
return repositorySelection;
}
});
}
Object.defineProperty(response.data, "total_count", {
get() {
deprecateTotalCount(
octokit.log,
new Deprecation(
'[@octokit/rest] "result.data.total_count" is deprecated.'
)
);
return totalCount;
}
});
}