From 5f3a44aeeff3c5f31a8063b6005abb90343a817e Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Thu, 31 Aug 2023 12:33:53 -0500 Subject: [PATCH] Improve `astro info` command (#8327) * feat(astro): improve info command * chore: update browser field --- .changeset/eight-zebras-rest.md | 5 + .github/ISSUE_TEMPLATE/---01-bug-report.yml | 6 +- packages/astro/src/cli/info/index.ts | 116 ++++++++++++++------ 3 files changed, 90 insertions(+), 37 deletions(-) create mode 100644 .changeset/eight-zebras-rest.md diff --git a/.changeset/eight-zebras-rest.md b/.changeset/eight-zebras-rest.md new file mode 100644 index 000000000..5f921c0b6 --- /dev/null +++ b/.changeset/eight-zebras-rest.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Improve `astro info` command formatting, allow users to copy info automatically diff --git a/.github/ISSUE_TEMPLATE/---01-bug-report.yml b/.github/ISSUE_TEMPLATE/---01-bug-report.yml index 1e713ab13..0abf947cc 100644 --- a/.github/ISSUE_TEMPLATE/---01-bug-report.yml +++ b/.github/ISSUE_TEMPLATE/---01-bug-report.yml @@ -14,7 +14,7 @@ body: - type: textarea id: astro-info attributes: - label: Astro info + label: Astro Info description: Run the command `astro info` in your terminal and paste the output here. Please review the data before submitting in case there is any sensitive information you don't want to share. render: block validations: @@ -22,10 +22,8 @@ body: - type: input id: browser attributes: - label: What browser are you using? + label: If this issue only occurs in one browser, which browser is a problem? placeholder: Chrome, Firefox, Safari - validations: - required: true - type: textarea id: bug-description attributes: diff --git a/packages/astro/src/cli/info/index.ts b/packages/astro/src/cli/info/index.ts index 4944432e7..03bef2fea 100644 --- a/packages/astro/src/cli/info/index.ts +++ b/packages/astro/src/cli/info/index.ts @@ -1,50 +1,100 @@ /* eslint-disable no-console */ +import type yargs from 'yargs-parser'; import * as colors from 'kleur/colors'; import { arch, platform } from 'node:os'; -import whichPm from 'which-pm'; -import type yargs from 'yargs-parser'; +import prompts from 'prompts'; import { resolveConfig } from '../../core/config/index.js'; import { ASTRO_VERSION } from '../../core/constants.js'; import { flagsToAstroInlineConfig } from '../flags.js'; +import { execSync } from 'node:child_process'; interface InfoOptions { flags: yargs.Arguments; } export async function printInfo({ flags }: InfoOptions) { + const rows: Array<[string, string | string[]]> = [ + ['Astro', `v${ASTRO_VERSION}`], + ['Node', process.version], + ['System', getSystem()], + ['Package Manager', getPackageManager()], + ] + const inlineConfig = flagsToAstroInlineConfig(flags); - const packageManager = await whichPm(process.cwd()); - let adapter = "Couldn't determine."; - let integrations = []; - - const MAX_PADDING = 25; - function printRow(label: string, value: string) { - const padding = MAX_PADDING - label.length; - console.log(`${colors.bold(label)}` + ' '.repeat(padding) + `${colors.green(value)}`); - } - try { const { userConfig } = await resolveConfig(inlineConfig, 'info'); - if (userConfig.adapter?.name) { - adapter = userConfig.adapter.name; - } - if (userConfig.integrations) { - integrations = (userConfig?.integrations ?? []) - .filter(Boolean) - .flat() - .map((i: any) => i?.name); - } - } catch (_e) {} - console.log(); - const packageManagerName = packageManager?.name ?? "Couldn't determine."; - printRow('Astro version', `v${ASTRO_VERSION}`); - printRow('Package manager', packageManagerName); - printRow('Platform', platform()); - printRow('Architecture', arch()); - printRow('Adapter', adapter); - let integrationsString = "None or couldn't determine."; - if (integrations.length > 0) { - integrationsString = integrations.join(', '); + rows.push(['Output', userConfig.output ?? 'static']) + rows.push(['Adapter', userConfig.adapter?.name ?? 'none']) + const integrations = (userConfig?.integrations ?? []) + .filter(Boolean) + .flat() + .map((i: any) => i?.name) + .filter(Boolean); + rows.push(['Integrations', integrations.length > 0 ? integrations : 'none']); + } catch {} + + let output = ''; + for (const [label, value] of rows) { + output += printRow(label, value); } - printRow('Integrations', integrationsString); + + await copyToClipboard(output.trim()); +} + +const SUPPORTED_SYSTEM = new Set(['darwin', 'win32']); +async function copyToClipboard(text: string) { + const system = platform(); + if (!SUPPORTED_SYSTEM.has(system)) return; + + console.log(); + const { shouldCopy } = await prompts({ + type: 'confirm', + name: 'shouldCopy', + message: 'Copy to clipboard?', + initial: true, + }) + if (!shouldCopy) return; + const command = system === 'darwin' ? 'pbcopy' : 'clip'; + try { + execSync(`echo ${JSON.stringify(text.trim())} | ${command}`, { encoding: 'utf8', stdio: 'ignore' }); + } catch (e) { + console.error(colors.red(`\nSorry, something went wrong!`) + ` Please copy the text above manually.`); + } +} + +const PLATFORM_TO_OS: Partial, string>> = { + darwin: 'macOS', + win32: 'Windows', + linux: 'Linux', +} + +function getSystem() { + const system = PLATFORM_TO_OS[platform()] ?? platform(); + return `${system} (${arch()})`; +} + +function getPackageManager() { + if (!process.env.npm_config_user_agent) { + return 'unknown' + } + const specifier = process.env.npm_config_user_agent.split(' ')[0]; + const name = specifier.substring(0, specifier.lastIndexOf('/')); + return name === 'npminstall' ? 'cnpm' : name; +} + +const MAX_PADDING = 25; +function printRow(label: string, value: string | string[]) { + const padding = MAX_PADDING - label.length; + const [first, ...rest] = Array.isArray(value) ? value : [value]; + let plaintext = `${label}${' '.repeat(padding)}${first}`; + let richtext = `${colors.bold(label)}${' '.repeat(padding)}${colors.green(first)}`; + if (rest.length > 0) { + for (const entry of rest) { + plaintext += `\n${' '.repeat(MAX_PADDING)}${entry}`; + richtext += `\n${' '.repeat(MAX_PADDING)}${colors.green(entry)}` + } + } + plaintext += '\n'; + console.log(richtext); + return plaintext; }