UNPKG

@taizo-pro/github-discussions-cli

Version:

A powerful command-line tool for interacting with GitHub Discussions without opening a browser

149 lines 6.51 kB
import { Command } from 'commander'; import { table } from 'table'; import chalk from 'chalk'; import { GitHubClient, FileAuthManager, FileConfigManager } from '../../core/index.js'; import { EnhancedErrorHandler } from '../utils/enhanced-error-handler.js'; import { formatDate } from '../utils/formatters.js'; import { Spinner } from '../utils/spinner.js'; export const listCommand = new Command('list') .description('List discussions in a repository') .argument('[repo]', 'Repository in owner/name format') .option('-f, --first <number>', 'Number of discussions to fetch', '20') .option('--format <format>', 'Output format (table, json, markdown)', 'table') .option('--category <category>', 'Filter by category name') .option('--author <username>', 'Filter by author username') .option('--has-comments', 'Only show discussions with comments') .option('--no-comments', 'Only show discussions without comments') .option('--sort <field>', 'Sort by field (created,updated)', 'updated') .option('--order <direction>', 'Sort order (asc,desc)', 'desc') .action(async (repo, options) => { const spinner = new Spinner(); const context = { operation: 'list discussions', repository: repo }; try { const authManager = new FileAuthManager(); const configManager = new FileConfigManager(); spinner.start('Checking authentication...'); const token = await authManager.getToken(); if (!token) { spinner.fail('No GitHub token found'); console.error(chalk.red('Run "gh-discussions config" to set up authentication.')); process.exit(1); } spinner.succeed('Authentication verified'); const targetRepo = repo || (await configManager.getDefaultRepo()); if (!targetRepo) { console.error(chalk.red('No repository specified. Provide a repo argument or set a default repo with "gh-discussions config".')); process.exit(1); } context.repository = targetRepo; spinner.start(`Fetching discussions from ${targetRepo}...`); const client = new GitHubClient(token); let discussions = await EnhancedErrorHandler.retryWithBackoff(() => client.listDiscussions(targetRepo, { first: parseInt(options.first, 10) * 2, // Get more to filter orderBy: { field: options.sort === 'created' ? 'CREATED_AT' : 'UPDATED_AT', direction: options.order.toUpperCase() }, }), context); // Apply filters if (options.category || options.author || options.hasComments || options.noComments) { spinner.update('Applying filters...'); discussions = discussions.filter(discussion => { // Category filter if (options.category && discussion.category?.name.toLowerCase() !== options.category.toLowerCase()) { return false; } // Author filter if (options.author && discussion.author.login.toLowerCase() !== options.author.toLowerCase()) { return false; } // Comments filter if (options.hasComments && discussion.commentCount === 0) { return false; } if (options.noComments && discussion.commentCount > 0) { return false; } return true; }); // Limit after filtering const limit = parseInt(options.first, 10); if (discussions.length > limit) { discussions = discussions.slice(0, limit); } } const filterText = []; if (options.category) filterText.push(`category: ${options.category}`); if (options.author) filterText.push(`author: ${options.author}`); if (options.hasComments) filterText.push('with comments'); if (options.noComments) filterText.push('without comments'); const filterSuffix = filterText.length > 0 ? ` (${filterText.join(', ')})` : ''; spinner.succeed(`Found ${discussions.length} discussions${filterSuffix}`); if (discussions.length === 0) { console.log(chalk.yellow('No discussions found in this repository.')); return; } const outputFormat = options.format || (await configManager.getConfig()).outputFormat || 'table'; switch (outputFormat) { case 'json': console.log(JSON.stringify(discussions, null, 2)); break; case 'markdown': printMarkdownTable(discussions); break; default: printTable(discussions); } } catch (error) { spinner.fail(); await EnhancedErrorHandler.handleError(error, context); } }); function printTable(discussions) { const data = [ ['Title', 'Author', 'Comments', 'Updated', 'Category'] ]; discussions.forEach((discussion) => { data.push([ discussion.title.length > 50 ? discussion.title.substring(0, 47) + '...' : discussion.title, discussion.author.login, discussion.commentCount.toString(), formatDate(discussion.updatedAt), discussion.category?.name || 'N/A', ]); }); const output = table(data, { header: { alignment: 'center', content: chalk.bold('GitHub Discussions'), }, columns: { 0: { width: 50, wrapWord: true }, 1: { width: 15 }, 2: { width: 8, alignment: 'center' }, 3: { width: 12 }, 4: { width: 15 }, }, }); console.log(output); } function printMarkdownTable(discussions) { console.log('| Title | Author | Comments | Updated | Category |'); console.log('|-------|--------|----------|---------|----------|'); discussions.forEach((discussion) => { const title = discussion.title.length > 50 ? discussion.title.substring(0, 47) + '...' : discussion.title; console.log(`| ${title} | ${discussion.author.login} | ${discussion.commentCount} | ${formatDate(discussion.updatedAt)} | ${discussion.category?.name || 'N/A'} |`); }); } //# sourceMappingURL=list.js.map