| /** |
| * 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`) |
| * |
| * 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. |
| */ |
| const REGEX = [ |
| /^\/search\//, |
| /^\/repos\/[^/]+\/[^/]+\/commits\/[^/]+\/(check-runs|check-suites)([^/]|$)/, |
| /^\/installation\/repositories([^/]|$)/, |
| /^\/user\/installations([^/]|$)/, |
| /^\/repos\/[^/]+\/[^/]+\/actions\/secrets([^/]|$)/, |
| /^\/repos\/[^/]+\/[^/]+\/actions\/workflows(\/[^/]+\/runs)?([^/]|$)/, |
| /^\/repos\/[^/]+\/[^/]+\/actions\/runs(\/[^/]+\/(artifacts|jobs))?([^/]|$)/ |
| ]; |
| export function normalizePaginatedListResponse(octokit, url, response) { |
| const path = url.replace(octokit.request.endpoint.DEFAULTS.baseUrl, ""); |
| const responseNeedsNormalization = REGEX.find(regex => regex.test(path)); |
| if (!responseNeedsNormalization) |
| return; |
| // 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; |
| Object.defineProperty(response.data, namespaceKey, { |
| get() { |
| octokit.log.warn(`[@octokit/paginate-rest] "response.data.${namespaceKey}" is deprecated for "GET ${path}". Get the results directly from "response.data"`); |
| return Array.from(data); |
| } |
| }); |
| } |