refactor(cli): make the CLI an even thinner wrapper around command functions (#7583)

This commit is contained in:
Joshua Chen 2022-06-16 01:28:07 +08:00 committed by GitHub
parent b4d93b9bd0
commit 0114f00069
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 54 additions and 50 deletions

View file

@ -8,7 +8,6 @@
// @ts-check
import fs from 'fs-extra';
import logger from '@docusaurus/logger';
import cli from 'commander';
import {DOCUSAURUS_VERSION} from '@docusaurus/utils';
@ -27,8 +26,6 @@ import beforeCli from './beforeCli.mjs';
await beforeCli();
const resolveDir = (dir = '.') => fs.realpath(dir);
cli.version(DOCUSAURUS_VERSION).usage('<command> [options]');
cli
@ -54,9 +51,9 @@ cli
'--no-minify',
'build website without minimizing JS bundles (default: false)',
)
.action(async (siteDir, options) => {
await build(await resolveDir(siteDir), options);
});
// @ts-expect-error: Promise<string> is not assignable to Promise<void>... but
// good enough here.
.action(build);
cli
.command('swizzle [themeName] [componentName] [siteDir]')
@ -80,9 +77,7 @@ cli
'copy TypeScript theme files when possible (default: false)',
)
.option('--danger', 'enable swizzle for unsafe component of themes')
.action(async (themeName, componentName, siteDir, options) =>
swizzle(await resolveDir(siteDir), themeName, componentName, options),
);
.action(swizzle);
cli
.command('deploy [siteDir]')
@ -103,9 +98,7 @@ cli
'--skip-build',
'skip building website before deploy it (default: false)',
)
.action(async (siteDir, options) =>
deploy(await resolveDir(siteDir), options),
);
.action(deploy);
cli
.command('start [siteDir]')
@ -130,9 +123,7 @@ cli
'--no-minify',
'build website without minimizing JS bundles (default: false)',
)
.action(async (siteDir, options) =>
start(await resolveDir(siteDir), options),
);
.action(start);
cli
.command('serve [siteDir]')
@ -152,14 +143,12 @@ cli
'--no-open',
'do not open page in the browser (default: false, or true in CI)',
)
.action(async (siteDir, options) =>
serve(await resolveDir(siteDir), options),
);
.action(serve);
cli
.command('clear [siteDir]')
.description('Remove build artifacts.')
.action(async (siteDir) => clear(await resolveDir(siteDir)));
.action(clear);
cli
.command('write-translations [siteDir]')
@ -180,9 +169,7 @@ cli
'--messagePrefix <messagePrefix>',
'Allows to init new written messages with a given prefix. This might help you to highlight untranslated message by making them stand out in the UI (default: "")',
)
.action(async (siteDir, options) =>
writeTranslations(await resolveDir(siteDir), options),
);
.action(writeTranslations);
cli
.command('write-heading-ids [siteDir] [files...]')
@ -192,9 +179,7 @@ cli
"keep the headings' casing, otherwise make all lowercase (default: false)",
)
.option('--overwrite', 'overwrite existing heading IDs (default: false)')
.action(async (siteDir, files, options) =>
writeHeadingIds(await resolveDir(siteDir), files, options),
);
.action(writeHeadingIds);
cli.arguments('<command>').action((cmd) => {
cli.outputHelp();
@ -221,7 +206,7 @@ function isInternalCommand(command) {
}
if (!isInternalCommand(process.argv.slice(2)[0])) {
await externalCommand(cli, await resolveDir('.'));
await externalCommand(cli);
}
if (!process.argv.slice(2).length) {

View file

@ -38,14 +38,16 @@ export type BuildCLIOptions = Pick<
};
export async function build(
siteDir: string,
cliOptions: Partial<BuildCLIOptions>,
siteDirParam: string = '.',
cliOptions: Partial<BuildCLIOptions> = {},
// When running build, we force terminate the process to prevent async
// operations from never returning. However, if run as part of docusaurus
// deploy, we have to let deploy finish.
// See https://github.com/facebook/docusaurus/pull/2496
forceTerminate: boolean = true,
): Promise<string> {
const siteDir = await fs.realpath(siteDirParam);
['SIGINT', 'SIGTERM'].forEach((sig) => {
process.on(sig, () => process.exit());
});

View file

@ -26,7 +26,9 @@ async function removePath(entry: {path: string; description: string}) {
}
}
export async function clear(siteDir: string): Promise<void> {
export async function clear(siteDirParam: string = '.'): Promise<void> {
const siteDir = await fs.realpath(siteDirParam);
const generatedFolder = {
path: path.join(siteDir, GENERATED_FILES_DIR_NAME),
description: 'generated folder',

View file

@ -41,9 +41,11 @@ function shellExecLog(cmd: string) {
}
export async function deploy(
siteDir: string,
cliOptions: Partial<DeployCLIOptions>,
siteDirParam: string = '.',
cliOptions: Partial<DeployCLIOptions> = {},
): Promise<void> {
const siteDir = await fs.realpath(siteDirParam);
const {outDir, siteConfig, siteConfigPath} = await loadContext({
siteDir,
config: cliOptions.config,

View file

@ -5,14 +5,13 @@
* LICENSE file in the root directory of this source tree.
*/
import fs from 'fs-extra';
import {loadContext} from '../server';
import {initPlugins} from '../server/plugins/init';
import type {CommanderStatic} from 'commander';
export async function externalCommand(
cli: CommanderStatic,
siteDir: string,
): Promise<void> {
export async function externalCommand(cli: CommanderStatic): Promise<void> {
const siteDir = await fs.realpath('.');
const context = await loadContext({siteDir});
const plugins = await initPlugins(context);

View file

@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import fs from 'fs-extra';
import http from 'http';
import path from 'path';
import logger from '@docusaurus/logger';
@ -24,9 +25,11 @@ export type ServeCLIOptions = HostPortOptions &
};
export async function serve(
siteDir: string,
cliOptions: Partial<ServeCLIOptions>,
siteDirParam: string = '.',
cliOptions: Partial<ServeCLIOptions> = {},
): Promise<void> {
const siteDir = await fs.realpath(siteDirParam);
const buildDir = cliOptions.dir ?? DEFAULT_BUILD_DIR_NAME;
let dir = path.resolve(siteDir, buildDir);

View file

@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import fs from 'fs-extra';
import path from 'path';
import _ from 'lodash';
import logger from '@docusaurus/logger';
@ -35,9 +36,11 @@ export type StartCLIOptions = HostPortOptions &
};
export async function start(
siteDir: string,
cliOptions: Partial<StartCLIOptions>,
siteDirParam: string = '.',
cliOptions: Partial<StartCLIOptions> = {},
): Promise<void> {
const siteDir = await fs.realpath(siteDirParam);
process.env.NODE_ENV = 'development';
process.env.BABEL_ENV = 'development';
logger.info('Starting the development server...');

View file

@ -111,7 +111,7 @@ async function createTestSite() {
component: string;
typescript?: boolean;
}) {
return swizzleWithExit(siteDir, FixtureThemeName, component, {
return swizzleWithExit(FixtureThemeName, component, siteDir, {
wrap: true,
danger: true,
typescript,
@ -125,7 +125,7 @@ async function createTestSite() {
component: string;
typescript?: boolean;
}) {
return swizzleWithExit(siteDir, FixtureThemeName, component, {
return swizzleWithExit(FixtureThemeName, component, siteDir, {
eject: true,
danger: true,
typescript,

View file

@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import fs from 'fs-extra';
import logger from '@docusaurus/logger';
import {getThemeName, getThemePath, getThemeNames} from './themes';
import {getThemeComponents, getComponentName} from './components';
@ -87,11 +88,13 @@ If you want to swizzle it, use the code=${'--danger'} flag, or confirm that you
}
export async function swizzle(
siteDir: string,
themeNameParam: string | undefined,
componentNameParam: string | undefined,
optionsParam: Partial<SwizzleCLIOptions>,
themeNameParam: string | undefined = undefined,
componentNameParam: string | undefined = undefined,
siteDirParam: string = '.',
optionsParam: Partial<SwizzleCLIOptions> = {},
): Promise<void> {
const siteDir = await fs.realpath(siteDirParam);
const options = normalizeOptions(optionsParam);
const {list, danger, typescript} = options;

View file

@ -41,10 +41,12 @@ async function getPathsToWatch(siteDir: string): Promise<string[]> {
}
export async function writeHeadingIds(
siteDir: string,
files: string[] | undefined,
options: WriteHeadingIDOptions,
siteDirParam: string = '.',
files: string[] = [],
options: WriteHeadingIDOptions = {},
): Promise<void> {
const siteDir = await fs.realpath(siteDirParam);
const markdownFiles = await safeGlobby(
files ?? (await getPathsToWatch(siteDir)),
{

View file

@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import fs from 'fs-extra';
import path from 'path';
import {loadContext, type LoadContextOptions} from '../server';
import {initPlugins} from '../server/plugins/init';
@ -75,9 +76,11 @@ async function writePluginTranslationFiles({
}
export async function writeTranslations(
siteDir: string,
options: Partial<WriteTranslationsCLIOptions>,
siteDirParam: string = '.',
options: Partial<WriteTranslationsCLIOptions> = {},
): Promise<void> {
const siteDir = await fs.realpath(siteDirParam);
const context = await loadContext({
siteDir,
config: options.config,