| 'use strict'; |
| |
| Object.defineProperty(exports, '__esModule', { value: true }); |
| |
| const VERSION = "1.1.2"; |
| |
| /** |
| * 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))?([^/]|$)/]; |
| 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); |
| } |
| |
| }); |
| } |
| |
| function iterator(octokit, route, parameters) { |
| const options = octokit.request.endpoint(route, parameters); |
| const method = options.method; |
| const headers = options.headers; |
| let url = options.url; |
| return { |
| [Symbol.asyncIterator]: () => ({ |
| next() { |
| if (!url) { |
| return Promise.resolve({ |
| done: true |
| }); |
| } |
| |
| return octokit.request({ |
| method, |
| url, |
| headers |
| }).then(response => { |
| normalizePaginatedListResponse(octokit, url, response); // `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 |
| |
| url = ((response.headers.link || "").match(/<([^>]+)>;\s*rel="next"/) || [])[1]; |
| return { |
| value: response |
| }; |
| }); |
| } |
| |
| }) |
| }; |
| } |
| |
| 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) { |
| return iterator.next().then(result => { |
| 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); |
| }); |
| } |
| |
| /** |
| * @param octokit Octokit instance |
| * @param options Options passed to Octokit constructor |
| */ |
| |
| function paginateRest(octokit) { |
| return { |
| paginate: Object.assign(paginate.bind(null, octokit), { |
| iterator: iterator.bind(null, octokit) |
| }) |
| }; |
| } |
| paginateRest.VERSION = VERSION; |
| |
| exports.paginateRest = paginateRest; |
| //# sourceMappingURL=index.js.map |