Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
- prefer `foo == null` and `foo != null` over `foo === undefined` and `foo !== undefined`
- import: use dynamic import only when necessary, the static form is preferable
- avoid the typescript `any` type - prefer strict typing, if you can't find a good way to fix a type issue (particularly with graphql data or documents) explain the problem instead of working around it
- for `--json` output, preserve GraphQL field names and nesting instead of inventing CLI-specific JSON shapes
- for paginated `--json` output, preserve connection shape and concatenate `nodes` rather than flattening or renaming fields

## permissions

Expand Down
11 changes: 9 additions & 2 deletions src/commands/document/document-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,17 @@ export const listCommand = new Command()
})
spinner?.stop()

const documents = result.documents?.nodes || []
const documentsConnection = result.documents ?? {
nodes: [],
pageInfo: {
hasNextPage: false,
endCursor: null,
},
}
const documents = documentsConnection.nodes

if (json) {
console.log(JSON.stringify(documents, null, 2))
console.log(JSON.stringify(documentsConnection, null, 2))
return
}

Expand Down
17 changes: 1 addition & 16 deletions src/commands/initiative-update/initiative-update-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,23 +142,8 @@ export const listCommand = new Command()

const updates = initiative.initiativeUpdates?.nodes || []

// JSON output
if (json) {
const jsonOutput = {
initiative: {
name: initiative.name,
slugId: initiative.slugId,
},
updates: updates.map((update) => ({
id: update.id,
body: update.body,
health: update.health,
url: update.url,
createdAt: update.createdAt,
author: update.user?.name || null,
})),
}
console.log(JSON.stringify(jsonOutput, null, 2))
console.log(JSON.stringify(initiative, null, 2))
return
}

Expand Down
44 changes: 22 additions & 22 deletions src/commands/initiative/initiative-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ const GetInitiatives = gql(`
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
`)
Expand Down Expand Up @@ -154,11 +158,19 @@ export const listCommand = new Command()
})
spinner?.stop()

let initiatives = result.initiatives?.nodes || []
const initiativesConnection = result.initiatives ?? {
nodes: [],
pageInfo: {
hasNextPage: false,
endCursor: null,
},
}

let initiatives = initiativesConnection.nodes

if (initiatives.length === 0) {
if (json) {
console.log("[]")
console.log(JSON.stringify(initiativesConnection, null, 2))
} else {
console.log("No initiatives found.")
}
Expand All @@ -177,27 +189,15 @@ export const listCommand = new Command()
return a.name.localeCompare(b.name)
})

// JSON output
if (json) {
const jsonOutput = initiatives.map((init) => ({
id: init.id,
slugId: init.slugId,
name: init.name,
description: init.description,
status: init.status,
health: init.health,
targetDate: init.targetDate,
owner: init.owner
? {
id: init.owner.id,
displayName: init.owner.displayName,
}
: null,
projectCount: init.projects?.nodes?.length || 0,
url: init.url,
archivedAt: init.archivedAt,
}))
console.log(JSON.stringify(jsonOutput, null, 2))
console.log(JSON.stringify(
{
...initiativesConnection,
nodes: initiatives,
},
null,
2,
))
return
}

Expand Down
31 changes: 1 addition & 30 deletions src/commands/initiative/initiative-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,37 +113,8 @@ export const viewCommand = new Command()
throw new NotFoundError("Initiative", initiativeId)
}

// JSON output
if (json) {
const jsonOutput = {
id: initiative.id,
slugId: initiative.slugId,
name: initiative.name,
description: initiative.description,
status: initiative.status,
health: initiative.health,
targetDate: initiative.targetDate,
color: initiative.color,
icon: initiative.icon,
url: initiative.url,
archivedAt: initiative.archivedAt,
createdAt: initiative.createdAt,
updatedAt: initiative.updatedAt,
owner: initiative.owner
? {
id: initiative.owner.id,
name: initiative.owner.name,
displayName: initiative.owner.displayName,
}
: null,
projects: (initiative.projects?.nodes || []).map((p) => ({
id: p.id,
slugId: p.slugId,
name: p.name,
status: p.status?.name,
})),
}
console.log(JSON.stringify(jsonOutput, null, 2))
console.log(JSON.stringify(initiative, null, 2))
return
}

Expand Down
27 changes: 24 additions & 3 deletions src/commands/issue/issue-agent-session-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ const GetIssueAgentSessions = gql(`
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
Expand Down Expand Up @@ -88,7 +92,7 @@ export const agentSessionListCommand = new Command()
}

const { Spinner } = await import("@std/cli/unstable-spinner")
const showSpinner = shouldShowSpinner()
const showSpinner = shouldShowSpinner() && !json
const spinner = showSpinner ? new Spinner() : null
spinner?.start()

Expand All @@ -98,16 +102,33 @@ export const agentSessionListCommand = new Command()
})
spinner?.stop()

let sessions = (result.issue?.comments?.nodes || [])
const comments = result.issue?.comments ?? {
nodes: [],
pageInfo: {
hasNextPage: false,
endCursor: null,
},
}

let sessions = comments.nodes
.map((c) => c.agentSession)
.filter((s): s is NonNullable<typeof s> => s != null)

const jsonComments = status
? {
...comments,
nodes: comments.nodes.filter((comment) =>
comment.agentSession?.status === status
),
}
: comments

if (status) {
sessions = sessions.filter((s) => s.status === status)
}

if (json) {
console.log(JSON.stringify(sessions, null, 2))
console.log(JSON.stringify(jsonComments, null, 2))
return
}

Expand Down
2 changes: 1 addition & 1 deletion src/commands/issue/issue-agent-session-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export const agentSessionViewCommand = new Command()
.action(async ({ json }, sessionId) => {
try {
const { Spinner } = await import("@std/cli/unstable-spinner")
const showSpinner = shouldShowSpinner()
const showSpinner = shouldShowSpinner() && !json
const spinner = showSpinner ? new Spinner() : null
spinner?.start()

Expand Down
15 changes: 13 additions & 2 deletions src/commands/issue/issue-comment-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ export const commentListCommand = new Command()
id
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
Expand All @@ -53,10 +57,17 @@ export const commentListCommand = new Command()
const client = getGraphQLClient()
const data = await client.request(query, { id: resolvedIdentifier })

const comments = data.issue?.comments?.nodes || []
const commentsConnection = data.issue?.comments ?? {
nodes: [],
pageInfo: {
hasNextPage: false,
endCursor: null,
},
}
const comments = commentsConnection.nodes

if (json) {
console.log(JSON.stringify(comments, null, 2))
console.log(JSON.stringify(commentsConnection, null, 2))
return
}

Expand Down
50 changes: 36 additions & 14 deletions src/commands/label/label-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,7 @@ const GetIssueLabels = gql(`
}
`)

interface Label {
id: string
name: string
description?: string | null
color: string
team?: { key: string; name: string } | null
}
type Label = NonNullable<GetIssueLabelsQuery["issueLabels"]>["nodes"][number]

export const listCommand = new Command()
.name("list")
Expand Down Expand Up @@ -95,6 +89,12 @@ export const listCommand = new Command()
const allLabels: Label[] = []
let hasNextPage = true
let after: string | null | undefined = undefined
let pageInfo: NonNullable<
GetIssueLabelsQuery["issueLabels"]
>["pageInfo"] = {
hasNextPage: false,
endCursor: null,
}

while (hasNextPage) {
const result: GetIssueLabelsQuery = await client.request(
Expand All @@ -106,17 +106,33 @@ export const listCommand = new Command()
},
)

const labels = result.issueLabels?.nodes || []
allLabels.push(...(labels as Label[]))
const labelsConnection = result.issueLabels
const labels = labelsConnection?.nodes || []
allLabels.push(...labels)

hasNextPage = result.issueLabels?.pageInfo?.hasNextPage || false
after = result.issueLabels?.pageInfo?.endCursor
pageInfo = labelsConnection?.pageInfo ?? {
hasNextPage: false,
endCursor: null,
}
hasNextPage = pageInfo.hasNextPage
after = pageInfo.endCursor
}

spinner?.stop()

if (allLabels.length === 0) {
console.log("No labels found.")
if (json) {
console.log(JSON.stringify(
{
nodes: allLabels,
pageInfo,
},
null,
2,
))
} else {
console.log("No labels found.")
}
return
}

Expand All @@ -125,9 +141,15 @@ export const listCommand = new Command()
a.name.toLowerCase().localeCompare(b.name.toLowerCase())
)

// JSON output
if (json) {
console.log(JSON.stringify(sortedLabels, null, 2))
console.log(JSON.stringify(
{
nodes: sortedLabels,
pageInfo,
},
null,
2,
))
return
}

Expand Down
Loading
Loading