Convert CLI top-level imports as dynamic imports (#7635)

This commit is contained in:
Bjorn Lu 2023-07-13 22:34:59 +08:00 committed by GitHub
parent db4095d3f5
commit bdde6b9f6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 46 deletions

View file

@ -22,6 +22,7 @@ import { printHelp } from '../../core/messages.js';
import { appendForwardSlash } from '../../core/path.js'; import { appendForwardSlash } from '../../core/path.js';
import { apply as applyPolyfill } from '../../core/polyfill.js'; import { apply as applyPolyfill } from '../../core/polyfill.js';
import { parseNpmName } from '../../core/util.js'; import { parseNpmName } from '../../core/util.js';
import { eventCliSession, telemetry } from '../../events/index.js';
import { generate, parse, t, visit } from './babel.js'; import { generate, parse, t, visit } from './babel.js';
import { ensureImport } from './imports.js'; import { ensureImport } from './imports.js';
import { wrapDefaultExport } from './wrapper.js'; import { wrapDefaultExport } from './wrapper.js';
@ -29,7 +30,6 @@ import { wrapDefaultExport } from './wrapper.js';
interface AddOptions { interface AddOptions {
logging: LogOptions; logging: LogOptions;
flags: yargs.Arguments; flags: yargs.Arguments;
cwd?: string;
} }
interface IntegrationInfo { interface IntegrationInfo {
@ -86,7 +86,8 @@ async function getRegistry(): Promise<string> {
} }
} }
export async function add(names: string[], { cwd, flags, logging }: AddOptions) { export async function add(names: string[], { flags, logging }: AddOptions) {
telemetry.record(eventCliSession('add'));
applyPolyfill(); applyPolyfill();
if (flags.help || names.length === 0) { if (flags.help || names.length === 0) {
printHelp({ printHelp({
@ -128,6 +129,7 @@ export async function add(names: string[], { cwd, flags, logging }: AddOptions)
} }
// Some packages might have a common alias! We normalize those here. // Some packages might have a common alias! We normalize those here.
const cwd = flags.root;
const integrationNames = names.map((name) => (ALIASES.has(name) ? ALIASES.get(name)! : name)); const integrationNames = names.map((name) => (ALIASES.has(name) ? ALIASES.get(name)! : name));
const integrations = await validateIntegrations(integrationNames); const integrations = await validateIntegrations(integrationNames);
let installResult = await tryToInstallIntegrations({ integrations, cwd, flags, logging }); let installResult = await tryToInstallIntegrations({ integrations, cwd, flags, logging });

View file

@ -2,15 +2,8 @@
import * as colors from 'kleur/colors'; import * as colors from 'kleur/colors';
import yargs from 'yargs-parser'; import yargs from 'yargs-parser';
import { ASTRO_VERSION } from '../core/constants.js'; import { ASTRO_VERSION } from '../core/constants.js';
import { collectErrorMetadata } from '../core/errors/dev/index.js'; import type { LogOptions } from '../core/logger/core.js';
import { createSafeError } from '../core/errors/index.js';
import { debug, type LogOptions } from '../core/logger/core.js';
import { enableVerboseLogging, nodeLogDestination } from '../core/logger/node.js';
import { formatErrorMessage, printHelp } from '../core/messages.js';
import * as event from '../events/index.js';
import { eventError, telemetry } from '../events/index.js';
type Arguments = yargs.Arguments;
type CLICommand = type CLICommand =
| 'help' | 'help'
| 'version' | 'version'
@ -25,7 +18,8 @@ type CLICommand =
| 'telemetry'; | 'telemetry';
/** Display --help flag */ /** Display --help flag */
function printAstroHelp() { async function printAstroHelp() {
const { printHelp } = await import('../core/messages.js');
printHelp({ printHelp({
commandName: 'astro', commandName: 'astro',
usage: '[command] [...flags]', usage: '[command] [...flags]',
@ -63,7 +57,7 @@ function printVersion() {
} }
/** Determine which command the user requested */ /** Determine which command the user requested */
function resolveCommand(flags: Arguments): CLICommand { function resolveCommand(flags: yargs.Arguments): CLICommand {
const cmd = flags._[2] as string; const cmd = flags._[2] as string;
if (flags.version) return 'version'; if (flags.version) return 'version';
@ -90,23 +84,20 @@ function resolveCommand(flags: Arguments): CLICommand {
* to present user-friendly error output where the fn is called. * to present user-friendly error output where the fn is called.
**/ **/
async function runCommand(cmd: string, flags: yargs.Arguments) { async function runCommand(cmd: string, flags: yargs.Arguments) {
const root = flags.root;
// These commands can run directly without parsing the user config. // These commands can run directly without parsing the user config.
switch (cmd) { switch (cmd) {
case 'help': case 'help':
printAstroHelp(); await printAstroHelp();
return; return;
case 'version': case 'version':
printVersion(); printVersion();
return; return;
case 'info': { case 'info': {
const { printInfo } = await import('./info/index.js'); const { printInfo } = await import('./info/index.js');
await printInfo({ cwd: root, flags }); await printInfo({ flags });
return; return;
} }
case 'docs': { case 'docs': {
telemetry.record(event.eventCliSession(cmd));
const { docs } = await import('./docs/index.js'); const { docs } = await import('./docs/index.js');
await docs({ flags }); await docs({ flags });
return; return;
@ -121,6 +112,7 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
} }
} }
const { enableVerboseLogging, nodeLogDestination } = await import('../core/logger/node.js');
const logging: LogOptions = { const logging: LogOptions = {
dest: nodeLogDestination, dest: nodeLogDestination,
level: 'info', level: 'info',
@ -141,10 +133,9 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
// by the end of this switch statement. // by the end of this switch statement.
switch (cmd) { switch (cmd) {
case 'add': { case 'add': {
telemetry.record(event.eventCliSession(cmd));
const { add } = await import('./add/index.js'); const { add } = await import('./add/index.js');
const packages = flags._.slice(3) as string[]; const packages = flags._.slice(3) as string[];
await add(packages, { cwd: root, flags, logging }); await add(packages, { flags, logging });
return; return;
} }
case 'dev': { case 'dev': {
@ -177,7 +168,7 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
await checkServer.watch(); await checkServer.watch();
return await new Promise(() => {}); // lives forever return await new Promise(() => {}); // lives forever
} else { } else {
let checkResult = await checkServer.check(); const checkResult = await checkServer.check();
return process.exit(checkResult); return process.exit(checkResult);
} }
} }
@ -201,29 +192,7 @@ export async function cli(args: string[]) {
try { try {
await runCommand(cmd, flags); await runCommand(cmd, flags);
} catch (err) { } catch (err) {
const { throwAndExit } = await import('./throw-and-exit.js');
await throwAndExit(cmd, err); await throwAndExit(cmd, err);
} }
} }
/** Display error and exit */
async function throwAndExit(cmd: string, err: unknown) {
let telemetryPromise: Promise<any>;
let errorMessage: string;
function exitWithErrorMessage() {
console.error(errorMessage);
process.exit(1);
}
const errorWithMetadata = collectErrorMetadata(createSafeError(err));
telemetryPromise = telemetry.record(eventError({ cmd, err: errorWithMetadata, isFatal: true }));
errorMessage = formatErrorMessage(errorWithMetadata);
// Timeout the error reporter (very short) because the user is waiting.
// NOTE(fks): It is better that we miss some events vs. holding too long.
// TODO(fks): Investigate using an AbortController once we drop Node v14.
setTimeout(exitWithErrorMessage, 400);
// Wait for the telemetry event to send, then exit. Ignore any error.
await telemetryPromise
.catch((err2) => debug('telemetry', `record() error: ${err2.message}`))
.then(exitWithErrorMessage);
}

View file

@ -7,11 +7,10 @@ import { openConfig } from '../../core/config/index.js';
import { ASTRO_VERSION } from '../../core/constants.js'; import { ASTRO_VERSION } from '../../core/constants.js';
interface InfoOptions { interface InfoOptions {
cwd?: string;
flags: yargs.Arguments; flags: yargs.Arguments;
} }
export async function printInfo({ cwd, flags }: InfoOptions) { export async function printInfo({ flags }: InfoOptions) {
const packageManager = await whichPm(process.cwd()); const packageManager = await whichPm(process.cwd());
let adapter = "Couldn't determine."; let adapter = "Couldn't determine.";
let integrations = []; let integrations = [];
@ -24,7 +23,7 @@ export async function printInfo({ cwd, flags }: InfoOptions) {
try { try {
const { userConfig } = await openConfig({ const { userConfig } = await openConfig({
cwd, cwd: flags.root,
flags, flags,
cmd: 'info', cmd: 'info',
}); });

View file

@ -0,0 +1,29 @@
/* eslint-disable no-console */
import { collectErrorMetadata } from '../core/errors/dev/index.js';
import { createSafeError } from '../core/errors/index.js';
import { debug } from '../core/logger/core.js';
import { formatErrorMessage } from '../core/messages.js';
import { eventError, telemetry } from '../events/index.js';
/** Display error and exit */
export async function throwAndExit(cmd: string, err: unknown) {
let telemetryPromise: Promise<any>;
let errorMessage: string;
function exitWithErrorMessage() {
console.error(errorMessage);
process.exit(1);
}
const errorWithMetadata = collectErrorMetadata(createSafeError(err));
telemetryPromise = telemetry.record(eventError({ cmd, err: errorWithMetadata, isFatal: true }));
errorMessage = formatErrorMessage(errorWithMetadata);
// Timeout the error reporter (very short) because the user is waiting.
// NOTE(fks): It is better that we miss some events vs. holding too long.
// TODO(fks): Investigate using an AbortController once we drop Node v14.
setTimeout(exitWithErrorMessage, 400);
// Wait for the telemetry event to send, then exit. Ignore any error.
await telemetryPromise
.catch((err2) => debug('telemetry', `record() error: ${err2.message}`))
.then(exitWithErrorMessage);
}