0

List Project Items

by
Published today

List the items (issues, pull requests, draft issues) of a project with their Status. Paginate with after = pageInfo.endCursor. Classic tokens and OAuth connections need the read:project scope.

Script github Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 1 hour ago
1
//native
2

3
async function graphql(auth: RT.Github, query: string, variables: object) {
4
  const response = await fetch("https://api.github.com/graphql", {
5
    method: "POST",
6
    headers: {
7
      Authorization: `Bearer ${auth.token}`,
8
      "Content-Type": "application/json",
9
      Accept: "application/json",
10
    },
11
    body: JSON.stringify({ query, variables }),
12
  })
13
  if (!response.ok) {
14
    throw new Error(`${response.status} ${await response.text()}`)
15
  }
16
  const { data, errors } = (await response.json()) as {
17
    data: any
18
    errors?: unknown[]
19
  }
20
  if (errors?.length) throw new Error(JSON.stringify(errors))
21
  return data
22
}
23

24
export type DynSelect_project_number = string
25

26
// Dropdown of the owner's projects; fill owner first.
27
export async function project_number(auth: RT.Github, owner: string) {
28
  if (!auth?.token || !owner) return []
29
  const data = await graphql(
30
    auth,
31
    `
32
      query ($owner: String!) {
33
        repositoryOwner(login: $owner) {
34
          ... on ProjectV2Owner {
35
            projectsV2(first: 100) {
36
              nodes {
37
                number
38
                title
39
              }
40
            }
41
          }
42
        }
43
      }
44
    `,
45
    { owner }
46
  )
47
  return (data.repositoryOwner?.projectsV2?.nodes ?? []).map((p: any) => ({
48
    value: String(p.number),
49
    label: `#${p.number} ${p.title}`,
50
  }))
51
}
52

53
/**
54
 * List Project Items
55
 * List the items (issues, pull requests, draft issues) of a project with their Status. Paginate with after = pageInfo.endCursor. Classic tokens and OAuth connections need the read:project scope.
56
 */
57
export async function main(
58
  auth: RT.Github,
59
  owner: string,
60
  project_number: DynSelect_project_number,
61
  first: number = 50,
62
  after: string | undefined
63
) {
64
  const data = await graphql(
65
    auth,
66
    `
67
      query ($owner: String!, $number: Int!, $first: Int!, $after: String) {
68
        repositoryOwner(login: $owner) {
69
          ... on ProjectV2Owner {
70
            projectV2(number: $number) {
71
              items(first: $first, after: $after) {
72
                nodes {
73
                  id
74
                  type
75
                  isArchived
76
                  status: fieldValueByName(name: "Status") {
77
                    ... on ProjectV2ItemFieldSingleSelectValue {
78
                      name
79
                      optionId
80
                    }
81
                  }
82
                  content {
83
                    ... on Issue {
84
                      number
85
                      title
86
                      state
87
                      url
88
                      repository {
89
                        nameWithOwner
90
                      }
91
                    }
92
                    ... on PullRequest {
93
                      number
94
                      title
95
                      state
96
                      url
97
                      repository {
98
                        nameWithOwner
99
                      }
100
                    }
101
                    ... on DraftIssue {
102
                      title
103
                    }
104
                  }
105
                }
106
                pageInfo {
107
                  endCursor
108
                  hasNextPage
109
                }
110
              }
111
            }
112
          }
113
        }
114
      }
115
    `,
116
    { owner, number: Number(project_number), first, after: after || null }
117
  )
118
  const project = data.repositoryOwner?.projectV2
119
  if (!project)
120
    throw new Error(`Project ${project_number} not found for ${owner}`)
121
  return project.items
122
}
123