//native
async function graphql(auth: RT.Github, query: string, variables: object) {
const response = await fetch("https://api.github.com/graphql", {
method: "POST",
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({ query, variables }),
})
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`)
}
const { data, errors } = (await response.json()) as {
data: any
errors?: unknown[]
}
if (errors?.length) throw new Error(JSON.stringify(errors))
return data
}
export type DynSelect_project_number = string
// Dropdown of the owner's projects; fill owner first.
export async function project_number(auth: RT.Github, owner: string) {
if (!auth?.token || !owner) return []
const data = await graphql(
auth,
`
query ($owner: String!) {
repositoryOwner(login: $owner) {
... on ProjectV2Owner {
projectsV2(first: 100) {
nodes {
number
title
}
}
}
}
}
`,
{ owner }
)
return (data.repositoryOwner?.projectsV2?.nodes ?? []).map((p: any) => ({
value: String(p.number),
label: `#${p.number} ${p.title}`,
}))
}
export type DynSelect_item_id = string
// Dropdown of the project's items.
export async function item_id(
auth: RT.Github,
owner: string,
project_number: string
) {
if (!auth?.token || !owner || !project_number) return []
const data = await graphql(
auth,
`
query ($owner: String!, $number: Int!) {
repositoryOwner(login: $owner) {
... on ProjectV2Owner {
projectV2(number: $number) {
items(first: 100) {
nodes {
id
content {
... on Issue {
number
title
}
... on PullRequest {
number
title
}
... on DraftIssue {
title
}
}
}
}
}
}
}
}
`,
{ owner, number: Number(project_number) }
)
return (data.repositoryOwner?.projectV2?.items.nodes ?? []).map((i: any) => ({
value: i.id,
label: i.content?.number
? `#${i.content.number} ${i.content.title}`
: (i.content?.title ?? i.id),
}))
}
export type DynSelect_status = string
// Dropdown of the project's Status options.
export async function status(
auth: RT.Github,
owner: string,
project_number: string
) {
if (!auth?.token || !owner || !project_number) return []
const data = await graphql(
auth,
`
query ($owner: String!, $number: Int!) {
repositoryOwner(login: $owner) {
... on ProjectV2Owner {
projectV2(number: $number) {
field(name: "Status") {
... on ProjectV2SingleSelectField {
options {
id
name
}
}
}
}
}
}
}
`,
{ owner, number: Number(project_number) }
)
return (data.repositoryOwner?.projectV2?.field?.options ?? []).map(
(o: any) => ({
value: o.id,
label: o.name,
})
)
}
/**
* Update Project Item Status
* Set the Status of a project item (issue, pull request or draft issue). status is the Status option id. Classic tokens and OAuth connections need the project scope.
*/
export async function main(
auth: RT.Github,
owner: string,
project_number: DynSelect_project_number,
item_id: DynSelect_item_id,
status: DynSelect_status
) {
const data = await graphql(
auth,
`
query ($owner: String!, $number: Int!) {
repositoryOwner(login: $owner) {
... on ProjectV2Owner {
projectV2(number: $number) {
id
field(name: "Status") {
... on ProjectV2SingleSelectField {
id
}
}
}
}
}
}
`,
{ owner, number: Number(project_number) }
)
const project = data.repositoryOwner?.projectV2
if (!project?.field)
throw new Error(`Project ${project_number} has no Status field`)
const result = await graphql(
auth,
`
mutation (
$projectId: ID!
$itemId: ID!
$fieldId: ID!
$optionId: String!
) {
updateProjectV2ItemFieldValue(
input: {
projectId: $projectId
itemId: $itemId
fieldId: $fieldId
value: { singleSelectOptionId: $optionId }
}
) {
projectV2Item {
id
}
}
}
`,
{
projectId: project.id,
itemId: item_id,
fieldId: project.field.id,
optionId: status,
}
)
return result.updateProjectV2ItemFieldValue.projectV2Item
}
Submitted by hugo989 2 hours ago