Refactor simple CLI commands (#7619)

This commit is contained in:
Bjorn Lu 2023-07-11 17:21:57 +08:00 committed by GitHub
parent 3669e2d276
commit 03c28aa629
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 123 additions and 115 deletions

View file

@ -9,35 +9,36 @@ import preferredPM from 'preferred-pm';
import prompts from 'prompts';
import { fileURLToPath, pathToFileURL } from 'url';
import type yargs from 'yargs-parser';
import { loadTSConfig, resolveConfigPath } from '../config/index.js';
import { loadTSConfig, resolveConfigPath } from '../../core/config/index.js';
import {
defaultTSConfig,
presets,
updateTSConfigForFramework,
type frameworkWithTSSettings,
} from '../config/tsconfig.js';
import { debug, info, type LogOptions } from '../logger/core.js';
import * as msg from '../messages.js';
import { printHelp } from '../messages.js';
import { appendForwardSlash } from '../path.js';
import { apply as applyPolyfill } from '../polyfill.js';
import { parseNpmName } from '../util.js';
} from '../../core/config/tsconfig.js';
import { debug, info, type LogOptions } from '../../core/logger/core.js';
import * as msg from '../../core/messages.js';
import { printHelp } from '../../core/messages.js';
import { appendForwardSlash } from '../../core/path.js';
import { apply as applyPolyfill } from '../../core/polyfill.js';
import { parseNpmName } from '../../core/util.js';
import { generate, parse, t, visit } from './babel.js';
import { ensureImport } from './imports.js';
import { wrapDefaultExport } from './wrapper.js';
export interface AddOptions {
interface AddOptions {
logging: LogOptions;
flags: yargs.Arguments;
cwd?: string;
}
export interface IntegrationInfo {
interface IntegrationInfo {
id: string;
packageName: string;
dependencies: [name: string, version: string][];
type: 'integration' | 'adapter';
}
const ALIASES = new Map([
['solid', 'solid-js'],
['tailwindcss', 'tailwind'],
@ -85,7 +86,7 @@ async function getRegistry(): Promise<string> {
}
}
export default async function add(names: string[], { cwd, flags, logging }: AddOptions) {
export async function add(names: string[], { cwd, flags, logging }: AddOptions) {
applyPolyfill();
if (flags.help || names.length === 0) {
printHelp({

View file

@ -0,0 +1,22 @@
import type yargs from 'yargs-parser';
import { printHelp } from '../../core/messages.js';
import { openInBrowser } from './open.js';
interface DocsOptions {
flags: yargs.Arguments;
}
export async function docs({ flags }: DocsOptions) {
if (flags.help || flags.h) {
printHelp({
commandName: 'astro docs',
tables: {
Flags: [['--help (-h)', 'See all available flags.']],
},
description: `Launches the Astro Docs website directly from the terminal.`,
});
return;
}
return await openInBrowser('https://docs.astro.build/');
}

View file

@ -1,7 +1,6 @@
/* eslint-disable no-console */
import fs from 'fs';
import * as colors from 'kleur/colors';
import { arch, platform } from 'node:os';
import type { Arguments as Flags } from 'yargs-parser';
import yargs from 'yargs-parser';
import { ZodError } from 'zod';
@ -19,7 +18,6 @@ import { enableVerboseLogging, nodeLogDestination } from '../core/logger/node.js
import { formatConfigErrorMessage, formatErrorMessage, printHelp } from '../core/messages.js';
import * as event from '../events/index.js';
import { eventConfigError, eventError, telemetry } from '../events/index.js';
import { openInBrowser } from './open.js';
type Arguments = yargs.Arguments;
type CLICommand =
@ -69,62 +67,11 @@ function printAstroHelp() {
}
/** Display --version flag */
async function printVersion() {
function printVersion() {
console.log();
console.log(` ${colors.bgGreen(colors.black(` astro `))} ${colors.green(`v${ASTRO_VERSION}`)}`);
}
async function printInfo({
cwd,
flags,
logging,
}: {
cwd?: string;
flags?: Flags;
logging: LogOptions;
}) {
const whichPm = await import('which-pm');
const packageManager = await whichPm.default(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 openConfig({
cwd,
flags,
cmd: 'info',
logging,
});
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(', ');
}
printRow('Integrations', integrationsString);
}
/** Determine which command the user requested */
function resolveCommand(flags: Arguments): CLICommand {
const cmd = flags._[2] as string;
@ -171,24 +118,40 @@ async function handleConfigError(
**/
async function runCommand(cmd: string, flags: yargs.Arguments) {
const root = flags.root;
// logLevel
let logging: LogOptions = {
dest: nodeLogDestination,
level: 'info',
};
// These commands can run directly without parsing the user config.
switch (cmd) {
case 'help':
printAstroHelp();
return process.exit(0);
return;
case 'version':
await printVersion();
return process.exit(0);
printVersion();
return;
case 'info': {
await printInfo({ cwd: root, flags, logging });
return process.exit(0);
const { printInfo } = await import('./info/index.js');
await printInfo({ cwd: root, flags });
return;
}
case 'docs': {
telemetry.record(event.eventCliSession(cmd));
const { docs } = await import('./docs/index.js');
await docs({ flags });
return;
}
case 'telemetry': {
// Do not track session start, since the user may be trying to enable,
// disable, or modify telemetry settings.
const { update } = await import('./telemetry/index.js');
const subcommand = flags._[3]?.toString();
await update(subcommand, { flags });
return;
}
}
const logging: LogOptions = {
dest: nodeLogDestination,
level: 'info',
};
if (flags.verbose) {
logging.level = 'debug';
enableVerboseLogging();
@ -196,39 +159,15 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
logging.level = 'silent';
}
// Special CLI Commands: "add", "docs", "telemetry"
// These commands run before the user's config is parsed, and may have other special
// conditions that should be handled here, before the others.
//
// These commands can also be run directly without parsing the user config,
// but they rely on parsing the `logging` first.
switch (cmd) {
case 'add': {
const { default: add } = await import('../core/add/index.js');
telemetry.record(event.eventCliSession(cmd));
const { add } = await import('./add/index.js');
const packages = flags._.slice(3) as string[];
return await add(packages, { cwd: root, flags, logging });
}
case 'docs': {
telemetry.record(event.eventCliSession(cmd));
if (flags.help || flags.h) {
printHelp({
commandName: 'astro docs',
tables: {
Flags: [['--help (-h)', 'See all available flags.']],
},
description: `Launches the Astro Docs website directly from the terminal.`,
});
return;
}
return await openInBrowser('https://docs.astro.build/');
}
case 'telemetry': {
const telemetryHandler = await import('./telemetry.js');
// Do not track session start, since the user may be trying to enable,
// disable, or modify telemetry settings.
const subcommand = flags._[3]?.toString();
return await telemetryHandler.update(subcommand, { flags });
await add(packages, { cwd: root, flags, logging });
return;
}
}
@ -241,7 +180,6 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
cwd: root,
flags,
cmd,
logging,
}).catch(async (e) => {
await handleConfigError(e, { cmd, cwd: root, flags, logging });
return {} as any;

View file

@ -0,0 +1,53 @@
/* eslint-disable no-console */
import { arch, platform } from 'node:os';
import * as colors from 'kleur/colors';
import whichPm from 'which-pm';
import type yargs from 'yargs-parser';
import { openConfig } from '../../core/config/index.js';
import { ASTRO_VERSION } from '../../core/constants.js';
interface InfoOptions {
cwd?: string;
flags: yargs.Arguments;
}
export async function printInfo({ cwd, flags }: InfoOptions) {
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 openConfig({
cwd,
flags,
cmd: '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(', ');
}
printRow('Integrations', integrationsString);
}

View file

@ -1,9 +1,9 @@
/* eslint-disable no-console */
import type yargs from 'yargs-parser';
import * as msg from '../core/messages.js';
import { telemetry } from '../events/index.js';
import * as msg from '../../core/messages.js';
import { telemetry } from '../../events/index.js';
export interface TelemetryOptions {
interface TelemetryOptions {
flags: yargs.Arguments;
}

View file

@ -34,10 +34,7 @@ export function getViteConfig(inlineConfig: UserConfig) {
dest: nodeLogDestination,
level: 'info',
};
const { astroConfig: config } = await openConfig({
cmd,
logging,
});
const { astroConfig: config } = await openConfig({ cmd });
const settings = createSettings(config, inlineConfig.root);
await runHookConfigSetup({ settings, command: cmd, logging });
const viteConfig = await createVite(

View file

@ -7,7 +7,6 @@ import path from 'path';
import { fileURLToPath, pathToFileURL } from 'url';
import { mergeConfig as mergeViteConfig } from 'vite';
import { AstroError, AstroErrorData } from '../errors/index.js';
import type { LogOptions } from '../logger/core.js';
import { arraify, isObject, isURL } from '../util.js';
import { createRelativeSchema } from './schema.js';
import { loadConfigWithVite } from './vite-load.js';
@ -163,7 +162,6 @@ interface LoadConfigOptions {
flags?: Flags;
cmd: string;
validate?: boolean;
logging: LogOptions;
/** Invalidate when reloading a previously loaded config */
isRestart?: boolean;
fsMod?: typeof fs;

View file

@ -87,7 +87,6 @@ export async function restartContainer({
cwd: resolvedRoot,
flags,
cmd: 'dev',
logging,
isRestart: true,
fsMod: container.fs,
});