UNPKG

@octokit/plugin-paginate-graphql

Version:

Octokit plugin to paginate GraphQL API endpoint responses

182 lines (173 loc) 5.46 kB
// pkg/dist-src/errors.js var generateMessage = (path, cursorValue) => `The cursor at "${path.join( "," )}" did not change its value "${cursorValue}" after a page transition. Please make sure your that your query is set up correctly.`; var MissingCursorChange = class extends Error { constructor(pageInfo, cursorValue) { super(generateMessage(pageInfo.pathInQuery, cursorValue)); this.pageInfo = pageInfo; this.cursorValue = cursorValue; if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); } } name = "MissingCursorChangeError"; }; var MissingPageInfo = class extends Error { constructor(response) { super( `No pageInfo property found in response. Please make sure to specify the pageInfo in your query. Response-Data: ${JSON.stringify( response, null, 2 )}` ); this.response = response; if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); } } name = "MissingPageInfo"; }; // pkg/dist-src/object-helpers.js var isObject = (value) => Object.prototype.toString.call(value) === "[object Object]"; function findPaginatedResourcePath(responseData) { const paginatedResourcePath = deepFindPathToProperty( responseData, "pageInfo" ); if (paginatedResourcePath.length === 0) { throw new MissingPageInfo(responseData); } return paginatedResourcePath; } var deepFindPathToProperty = (object, searchProp, path = []) => { for (const key of Object.keys(object)) { const currentPath = [...path, key]; const currentValue = object[key]; if (isObject(currentValue)) { if (currentValue.hasOwnProperty(searchProp)) { return currentPath; } const result = deepFindPathToProperty( currentValue, searchProp, currentPath ); if (result.length > 0) { return result; } } } return []; }; var get = (object, path) => { return path.reduce((current, nextProperty) => current[nextProperty], object); }; var set = (object, path, mutator) => { const lastProperty = path[path.length - 1]; const parentPath = [...path].slice(0, -1); const parent = get(object, parentPath); if (typeof mutator === "function") { parent[lastProperty] = mutator(parent[lastProperty]); } else { parent[lastProperty] = mutator; } }; // pkg/dist-src/extract-page-info.js var extractPageInfos = (responseData) => { const pageInfoPath = findPaginatedResourcePath(responseData); return { pathInQuery: pageInfoPath, pageInfo: get(responseData, [...pageInfoPath, "pageInfo"]) }; }; // pkg/dist-src/page-info.js var isForwardSearch = (givenPageInfo) => { return givenPageInfo.hasOwnProperty("hasNextPage"); }; var getCursorFrom = (pageInfo) => isForwardSearch(pageInfo) ? pageInfo.endCursor : pageInfo.startCursor; var hasAnotherPage = (pageInfo) => isForwardSearch(pageInfo) ? pageInfo.hasNextPage : pageInfo.hasPreviousPage; // pkg/dist-src/iterator.js var createIterator = (octokit) => { return (query, initialParameters = {}) => { let nextPageExists = true; let parameters = { ...initialParameters }; return { [Symbol.asyncIterator]: () => ({ async next() { if (!nextPageExists) return { done: true, value: {} }; const response = await octokit.graphql( query, parameters ); const pageInfoContext = extractPageInfos(response); const nextCursorValue = getCursorFrom(pageInfoContext.pageInfo); nextPageExists = hasAnotherPage(pageInfoContext.pageInfo); if (nextPageExists && nextCursorValue === parameters.cursor) { throw new MissingCursorChange(pageInfoContext, nextCursorValue); } parameters = { ...parameters, cursor: nextCursorValue }; return { done: false, value: response }; } }) }; }; }; // pkg/dist-src/merge-responses.js var mergeResponses = (response1, response2) => { if (Object.keys(response1).length === 0) { return Object.assign(response1, response2); } const path = findPaginatedResourcePath(response1); const nodesPath = [...path, "nodes"]; const newNodes = get(response2, nodesPath); if (newNodes) { set(response1, nodesPath, (values) => { return [...values, ...newNodes]; }); } const edgesPath = [...path, "edges"]; const newEdges = get(response2, edgesPath); if (newEdges) { set(response1, edgesPath, (values) => { return [...values, ...newEdges]; }); } const pageInfoPath = [...path, "pageInfo"]; set(response1, pageInfoPath, get(response2, pageInfoPath)); return response1; }; // pkg/dist-src/paginate.js var createPaginate = (octokit) => { const iterator = createIterator(octokit); return async (query, initialParameters = {}) => { let mergedResponse = {}; for await (const response of iterator( query, initialParameters )) { mergedResponse = mergeResponses(mergedResponse, response); } return mergedResponse; }; }; // pkg/dist-src/version.js var VERSION = "0.0.0-development"; // pkg/dist-src/index.js function paginateGraphQL(octokit) { return { graphql: Object.assign(octokit.graphql, { paginate: Object.assign(createPaginate(octokit), { iterator: createIterator(octokit) }) }) }; } export { VERSION, paginateGraphQL };