UNPKG

@aaronshaf/ger

Version:

Gerrit CLI and SDK - A modern CLI tool and TypeScript SDK for Gerrit Code Review, built with Effect-TS

167 lines (160 loc) 6 kB
import { Effect } from 'effect' import { type ApiError, GerritApiService } from '@/api/gerrit' import { sanitizeCDATA } from '@/utils/shell-safety' interface GroupsOptions { pattern?: string owned?: boolean project?: string user?: string limit?: string xml?: boolean json?: boolean } /** * Lists Gerrit groups with optional filtering. * * @param options - Configuration options * @param options.pattern - Optional regex pattern to filter groups by name * @param options.owned - Show only groups owned by the current user * @param options.project - Show groups with permissions on specific project * @param options.user - Show groups a specific user belongs to * @param options.limit - Maximum number of results (default: 25) * @param options.xml - Whether to output in XML format for LLM consumption * @returns Effect that completes when groups are listed */ export const groupsCommand = ( options: GroupsOptions = {}, ): Effect.Effect<void, ApiError, GerritApiService> => Effect.gen(function* () { const gerritApi = yield* GerritApiService // Parse limit option const limit = options.limit ? Number.parseInt(options.limit, 10) : 25 // Fetch groups const groups = yield* gerritApi .listGroups({ pattern: options.pattern, owned: options.owned, project: options.project, user: options.user, limit: Number.isNaN(limit) || limit < 1 ? 25 : limit, }) .pipe( Effect.catchTag('ApiError', (error) => Effect.gen(function* () { if (options.json) { console.log(JSON.stringify({ status: 'error', error: error.message }, null, 2)) } else if (options.xml) { console.log('<?xml version="1.0" encoding="UTF-8"?>') console.log('<groups_result>') console.log(' <status>error</status>') console.log(` <error><![CDATA[${sanitizeCDATA(error.message)}]]></error>`) console.log('</groups_result>') } else { if (error.status === 403) { console.error('✗ Permission denied to list groups') } else { console.error(`✗ Failed to list groups: ${error.message}`) } } return yield* Effect.fail(error) }), ), ) // Handle empty results if (groups.length === 0) { if (options.json) { console.log(JSON.stringify({ status: 'success', count: 0, groups: [] }, null, 2)) } else if (options.xml) { console.log(`<?xml version="1.0" encoding="UTF-8"?>`) console.log(`<groups_result>`) console.log(` <status>success</status>`) console.log(` <count>0</count>`) console.log(` <groups />`) console.log(`</groups_result>`) } else { console.log('No groups found') } return } // Output results if (options.json) { console.log( JSON.stringify( { status: 'success', count: groups.length, groups: groups.map((group) => ({ id: group.id, ...(group.name ? { name: group.name } : {}), ...(group.description ? { description: group.description } : {}), ...(group.owner ? { owner: group.owner } : {}), ...(group.owner_id ? { owner_id: group.owner_id } : {}), ...(group.group_id !== undefined ? { group_id: group.group_id } : {}), ...(group.options?.visible_to_all !== undefined ? { visible_to_all: group.options.visible_to_all } : {}), ...(group.created_on ? { created_on: group.created_on } : {}), ...(group.url ? { url: group.url } : {}), })), }, null, 2, ), ) } else if (options.xml) { console.log(`<?xml version="1.0" encoding="UTF-8"?>`) console.log(`<groups_result>`) console.log(` <status>success</status>`) console.log(` <count>${groups.length}</count>`) console.log(` <groups>`) for (const group of groups) { console.log(` <group>`) console.log(` <id><![CDATA[${sanitizeCDATA(group.id)}]]></id>`) if (group.name) { console.log(` <name><![CDATA[${sanitizeCDATA(group.name)}]]></name>`) } if (group.description) { console.log( ` <description><![CDATA[${sanitizeCDATA(group.description)}]]></description>`, ) } if (group.owner) { console.log(` <owner><![CDATA[${sanitizeCDATA(group.owner)}]]></owner>`) } if (group.owner_id) { console.log(` <owner_id><![CDATA[${sanitizeCDATA(group.owner_id)}]]></owner_id>`) } if (group.group_id !== undefined) { console.log(` <group_id>${group.group_id}</group_id>`) } if (group.options?.visible_to_all !== undefined) { console.log(` <visible_to_all>${group.options.visible_to_all}</visible_to_all>`) } if (group.created_on) { console.log( ` <created_on><![CDATA[${sanitizeCDATA(group.created_on)}]]></created_on>`, ) } if (group.url) { console.log(` <url><![CDATA[${sanitizeCDATA(group.url)}]]></url>`) } console.log(` </group>`) } console.log(` </groups>`) console.log(`</groups_result>`) } else { // Plain text output - more detailed than projects console.log(`Available groups (${groups.length}):\n`) for (const group of groups) { const name = group.name || group.id console.log(name) if (group.description) { console.log(` Description: ${group.description}`) } if (group.owner) { console.log(` Owner: ${group.owner}`) } console.log('') } } })