github-projects/api/projectsGraphQL.js (161 lines of code) (raw):

"use strict"; // Using reference: https://docs.github.com/en/graphql/reference/objects Object.defineProperty(exports, "__esModule", { value: true }); exports.gqlUpdateFieldValue = exports.gqlGetFieldOptions = exports.gqlGetIssuesForProject = exports.gqlGetProject = void 0; const MAX_BATCH_SIZE = 100; const gqlGetProject = async (octokit, { projectNumber, owner }) => { const query = `query{ organization(login: "${owner}"){ projectV2(number: ${projectNumber}){ id url title } } } `; return (await octokit.graphql(query)).organization.projectV2; }; exports.gqlGetProject = gqlGetProject; /** * Fetches issues for a project. * In Github's graphql API, the projectV2 field has items in it, but not all of those are issues, * so we have to paginate through, and collect issues to satisfy the issueCount. * Also, the issues listing doesn't have any filtering, so we have to get pages, and filter them ourselves. * * @param octokit - The Octokit instance. * @param projectNumber - The project number. (e.g.: https://github.com/<owner>/<repo>/projects/<projectNumber>) * @param findIssueNumbers - An array of issue numbers to find. * @param owner - The owner of the repository. * @param limitOptions - Optional limit options for pagination. * @returns An array of issues. */ const gqlGetIssuesForProject = async (octokit, { projectNumber, findIssueNumbers = [], owner, }, limitOptions) => { var _a, _b; const { issueCount = 20, issueFieldCount = 10, labelsCount = 10 } = limitOptions || {}; const findIssueNumbersSet = new Set(findIssueNumbers); console.log(`Fetching ${(findIssueNumbers === null || findIssueNumbers === void 0 ? void 0 : findIssueNumbers.length) || issueCount} issues for project ${projectNumber}...`); const results = []; let issueStartCursor = null; let nextPageExists = true; let totalFetched = 0; while (nextPageExists) { const startCursor = issueStartCursor ? `"${issueStartCursor}"` : null; // null is needed for first page, but it cannot be a string const query = ` query { organization(login: "${owner}") { projectV2(number: ${projectNumber}) { items(first: ${MAX_BATCH_SIZE}, after: ${startCursor}, orderBy: { field: POSITION, direction: DESC }) { pageInfo { endCursor hasNextPage } nodes { __typename id fieldValues(first: ${issueFieldCount}) { nodes { __typename ... on ProjectV2ItemFieldSingleSelectValue { __typename name optionId field { ... on ProjectV2SingleSelectField { name } } } } } fullDatabaseId content { __typename ... on Issue { id number title resourcePath url repository { name owner { id } } labels(first: ${labelsCount}) { nodes { name } } } } } } } } }`; const responseItems = (await octokit.graphql(query)).organization.projectV2.items; const responseIssues = responseItems.nodes.filter((i) => { var _a; return ((_a = i.content) === null || _a === void 0 ? void 0 : _a.__typename) === 'Issue'; }); totalFetched += responseIssues.length; responseIssues.forEach((issue) => { if (findIssueNumbers.length) { if (findIssueNumbersSet.has(issue.content.number)) { results.push(issue); findIssueNumbersSet.delete(issue.content.number); } } else { results.push(issue); } }); if (findIssueNumbers.length && findIssueNumbersSet.size === 0) { console.log(`Found all requested ${findIssueNumbers.length} issues`); break; } else if (results.length >= issueCount) { console.log(`Fetched all requested ${issueCount} issues`); break; } else if ((_a = responseItems.pageInfo) === null || _a === void 0 ? void 0 : _a.hasNextPage) { console.log(`Fetched ${totalFetched} of ${issueCount} issues, fetching more...`); nextPageExists = true; if (nextPageExists) { issueStartCursor = ((_b = responseItems.pageInfo) === null || _b === void 0 ? void 0 : _b.endCursor) || null; } } else { console.log('No more issues to fetch'); nextPageExists = false; } } return results; }; exports.gqlGetIssuesForProject = gqlGetIssuesForProject; const gqlGetFieldOptions = (octokit, { projectNumber, owner }, limitOptions) => { const { fieldCount = 20 } = limitOptions || {}; return octokit.graphql(`query { organization(login: "${owner}") { projectV2(number: ${projectNumber}) { fields(first: ${fieldCount}) { nodes { __typename ... on ProjectV2SingleSelectField { id name options { id name } } } } } } }`); }; exports.gqlGetFieldOptions = gqlGetFieldOptions; const gqlUpdateFieldValue = async (octokit, { projectId, fieldId, itemId, optionId, fieldName }) => { const mutation = `mutation{ updateProjectV2ItemFieldValue(input: {itemId: "${itemId}", fieldId: "${fieldId}", projectId: "${projectId}", value: { singleSelectOptionId: "${optionId}" }}) { clientMutationId projectV2Item { id fieldValueByName(name: "${fieldName}") { ... on ProjectV2ItemFieldSingleSelectValue { name optionId } } } } }`; return octokit.graphql(mutation); }; exports.gqlUpdateFieldValue = gqlUpdateFieldValue; //# sourceMappingURL=projectsGraphQL.js.map