|
import { Octokit } from "https://cdn.skypack.dev/@octokit/core?dts"; |
|
import { Kind, parse, visit } from "https://cdn.skypack.dev/graphql?dts"; |
|
|
|
interface PaginationItem { |
|
location: string; |
|
cursorVariableName: string; |
|
} |
|
|
|
const extractPaginatedItems = (query: string): PaginationItem[] => { |
|
const ast = parse(query, { noLocation: true }); |
|
|
|
const currentPath: string[] = []; |
|
const paginationInfos: PaginationItem[] = []; |
|
|
|
visit(ast, { |
|
enter(node, key, parent, path, ancestors) { |
|
if (node.kind === Kind.FIELD) { |
|
currentPath.push(node.name.value); |
|
} |
|
|
|
if ( |
|
node.kind === Kind.ARGUMENT && |
|
node.name.value === "after" && |
|
node.value.kind === Kind.VARIABLE |
|
) { |
|
paginationInfos.push({ |
|
location: currentPath.join("."), |
|
cursorVariableName: node.value.name.value, |
|
}); |
|
} |
|
}, |
|
leave(node) { |
|
if (node.kind === Kind.FIELD) { |
|
currentPath.pop(); |
|
} |
|
}, |
|
}); |
|
|
|
return paginationInfos; |
|
}; |
|
|
|
const getObjectByPosition = (obj: any, positionStr: string) => { |
|
const position = positionStr.split("."); |
|
return position.reduce((current, nextProperty) => current[nextProperty], obj); |
|
}; |
|
|
|
const paginateComplex = (octokit: Octokit) => { |
|
return async (query: string) => { |
|
// Find Argument with name 'after' and get |
|
// 1. the value.name.value of a type 'Variable' |
|
// 2. the path to the paginated entity (which is either nodes or edges) |
|
const paginationItems = extractPaginatedItems(query); |
|
const { cursorVariableName, location } = paginationItems[0]; |
|
|
|
let hasNextPage = true; |
|
let nextCursor = undefined; |
|
let allNodes = []; |
|
|
|
while (hasNextPage) { |
|
const result = await octokit.graphql(query, { |
|
[cursorVariableName]: nextCursor, |
|
}) as any; |
|
const paginatedEntity = getObjectByPosition(result, location); |
|
const { nodes, pageInfo } = paginatedEntity; |
|
allNodes.push(...nodes); |
|
hasNextPage = pageInfo.hasNextPage; |
|
nextCursor = pageInfo.endCursor; |
|
} |
|
|
|
return { |
|
repository: { |
|
issues: allNodes, |
|
}, |
|
}; |
|
}; |
|
}; |
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
const octokit = new Octokit({ |
|
auth: Deno.env.get("GITHUB_TOKEN"), |
|
}); |
|
|
|
const paginate = paginateComplex(octokit); |
|
|
|
const result = await paginate(`#graphql |
|
query paginate($cursor1: String) { |
|
repository(owner: "octokit", name: "rest.js") { |
|
issues(first: 10, after: $cursor1) { |
|
pageInfo { |
|
endCursor |
|
hasNextPage |
|
} |
|
nodes { |
|
title |
|
} |
|
} |
|
} |
|
} |
|
`); |
|
|
|
console.log(JSON.stringify(result, null, 2)); |