diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index 574794220687..d3cd057e7fda 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -410,37 +410,6 @@ export type DocusaurusContext = { // isBrowser: boolean; // Not here on purpose! }; -export type HostPortCLIOptions = { - host?: string; - port?: string; -}; - -export type ConfigOptions = { - config: string; -}; - -export type StartCLIOptions = HostPortCLIOptions & - ConfigOptions & { - hotOnly: boolean; - open: boolean; - poll: boolean | number; - locale?: string; - }; - -export type ServeCLIOptions = HostPortCLIOptions & - ConfigOptions & { - dir: string; - build: boolean; - }; - -export type BuildCLIOptions = ConfigOptions & { - bundleAnalyzer: boolean; - outDir: string; - minify: boolean; - skipBuild: boolean; - locale?: string; -}; - export type LoadContext = { siteDir: string; generatedFilesDir: string; diff --git a/packages/docusaurus/src/commands/build.ts b/packages/docusaurus/src/commands/build.ts index 72d613082858..555cb76bd66b 100644 --- a/packages/docusaurus/src/commands/build.ts +++ b/packages/docusaurus/src/commands/build.ts @@ -13,10 +13,10 @@ import ReactLoadableSSRAddon from 'react-loadable-ssr-addon-v5-slorber'; import type {Configuration} from 'webpack'; import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer'; import merge from 'webpack-merge'; -import {load, loadContext} from '../server'; +import {load, loadContext, type LoadContextOptions} from '../server'; import {handleBrokenLinks} from '../server/brokenLinks'; -import type {BuildCLIOptions, Props} from '@docusaurus/types'; +import type {Props} from '@docusaurus/types'; import createClientConfig from '../webpack/client'; import createServerConfig from '../webpack/server'; import { @@ -29,6 +29,14 @@ import {loadI18n} from '../server/i18n'; import {mapAsyncSequential} from '@docusaurus/utils'; import type {HelmetServerState} from 'react-helmet-async'; +export type BuildCLIOptions = Pick< + LoadContextOptions, + 'config' | 'locale' | 'outDir' +> & { + bundleAnalyzer?: boolean; + minify?: boolean; +}; + export async function build( siteDir: string, cliOptions: Partial, @@ -64,8 +72,8 @@ export async function build( } const context = await loadContext({ siteDir, - customOutDir: cliOptions.outDir, - customConfigFilePath: cliOptions.config, + outDir: cliOptions.outDir, + config: cliOptions.config, locale: cliOptions.locale, localizePath: cliOptions.locale ? false : undefined, }); @@ -113,8 +121,8 @@ async function buildLocale({ const props: Props = await load({ siteDir, - customOutDir: cliOptions.outDir, - customConfigFilePath: cliOptions.config, + outDir: cliOptions.outDir, + config: cliOptions.config, locale, localizePath: cliOptions.locale ? false : undefined, }); diff --git a/packages/docusaurus/src/commands/commandUtils.ts b/packages/docusaurus/src/commands/commandUtils.ts deleted file mode 100644 index d14d5b8977ad..000000000000 --- a/packages/docusaurus/src/commands/commandUtils.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -import {choosePort} from '../server/choosePort'; -import type {HostPortCLIOptions} from '@docusaurus/types'; -import {DEFAULT_PORT} from '@docusaurus/utils'; - -export function getCLIOptionHost( - hostOption: HostPortCLIOptions['host'], -): string { - return hostOption ?? 'localhost'; -} - -export async function getCLIOptionPort( - portOption: HostPortCLIOptions['port'], - host: string, -): Promise { - const basePort = portOption ? parseInt(portOption, 10) : DEFAULT_PORT; - return choosePort(host, basePort); -} diff --git a/packages/docusaurus/src/commands/deploy.ts b/packages/docusaurus/src/commands/deploy.ts index 2e0fbb504767..485c3940049d 100644 --- a/packages/docusaurus/src/commands/deploy.ts +++ b/packages/docusaurus/src/commands/deploy.ts @@ -9,12 +9,18 @@ import fs from 'fs-extra'; import shell from 'shelljs'; import logger from '@docusaurus/logger'; import {hasSSHProtocol, buildSshUrl, buildHttpsUrl} from '@docusaurus/utils'; -import {loadContext} from '../server'; +import {loadContext, type LoadContextOptions} from '../server'; import {build} from './build'; -import type {BuildCLIOptions} from '@docusaurus/types'; import path from 'path'; import os from 'os'; +export type DeployCLIOptions = Pick< + LoadContextOptions, + 'config' | 'locale' | 'outDir' +> & { + skipBuild?: boolean; +}; + // GIT_PASS env variable should not appear in logs function obfuscateGitPass(str: string) { const gitPass = process.env.GIT_PASS; @@ -36,12 +42,12 @@ function shellExecLog(cmd: string) { export async function deploy( siteDir: string, - cliOptions: Partial, + cliOptions: Partial, ): Promise { const {outDir, siteConfig, siteConfigPath} = await loadContext({ siteDir, - customConfigFilePath: cliOptions.config, - customOutDir: cliOptions.outDir, + config: cliOptions.config, + outDir: cliOptions.outDir, }); if (typeof siteConfig.trailingSlash === 'undefined') { diff --git a/packages/docusaurus/src/commands/serve.ts b/packages/docusaurus/src/commands/serve.ts index 35ba82fd5a01..044bd04ee684 100644 --- a/packages/docusaurus/src/commands/serve.ts +++ b/packages/docusaurus/src/commands/serve.ts @@ -9,11 +9,17 @@ import http from 'http'; import serveHandler from 'serve-handler'; import logger from '@docusaurus/logger'; import path from 'path'; +import type {LoadContextOptions} from '../server'; import {loadSiteConfig} from '../server/config'; import {build} from './build'; -import {getCLIOptionHost, getCLIOptionPort} from './commandUtils'; +import {getHostPort, type HostPortOptions} from '../server/getHostPort'; import {DEFAULT_BUILD_DIR_NAME} from '@docusaurus/utils'; -import type {ServeCLIOptions} from '@docusaurus/types'; + +export type ServeCLIOptions = HostPortOptions & + Pick & { + dir?: string; + build?: boolean; + }; export async function serve( siteDir: string, @@ -33,8 +39,7 @@ export async function serve( ); } - const host: string = getCLIOptionHost(cliOptions.host); - const port: number | null = await getCLIOptionPort(cliOptions.port, host); + const {host, port} = await getHostPort(cliOptions); if (port === null) { process.exit(); diff --git a/packages/docusaurus/src/commands/start.ts b/packages/docusaurus/src/commands/start.ts index 169776a1f193..8dee7788911b 100644 --- a/packages/docusaurus/src/commands/start.ts +++ b/packages/docusaurus/src/commands/start.ts @@ -17,17 +17,23 @@ import evalSourceMapMiddleware from 'react-dev-utils/evalSourceMapMiddleware'; import webpack from 'webpack'; import WebpackDevServer from 'webpack-dev-server'; import merge from 'webpack-merge'; -import {load} from '../server'; -import type {StartCLIOptions} from '@docusaurus/types'; +import {load, type LoadContextOptions} from '../server'; import createClientConfig from '../webpack/client'; import { applyConfigureWebpack, applyConfigurePostCss, getHttpsConfig, } from '../webpack/utils'; -import {getCLIOptionHost, getCLIOptionPort} from './commandUtils'; +import {getHostPort, type HostPortOptions} from '../server/getHostPort'; import {getTranslationsLocaleDirPath} from '../server/translations/translations'; +export type StartCLIOptions = HostPortOptions & + Pick & { + hotOnly?: boolean; + open?: boolean; + poll?: boolean | number; + }; + export async function start( siteDir: string, cliOptions: Partial, @@ -39,7 +45,7 @@ export async function start( function loadSite() { return load({ siteDir, - customConfigFilePath: cliOptions.config, + config: cliOptions.config, locale: cliOptions.locale, localizePath: undefined, // Should this be configurable? }); @@ -50,8 +56,7 @@ export async function start( const protocol: string = process.env.HTTPS === 'true' ? 'https' : 'http'; - const host: string = getCLIOptionHost(cliOptions.host); - const port: number | null = await getCLIOptionPort(cliOptions.port, host); + const {host, port} = await getHostPort(cliOptions); if (port === null) { process.exit(); diff --git a/packages/docusaurus/src/commands/swizzle/actions.ts b/packages/docusaurus/src/commands/swizzle/actions.ts index 8bff8fc92873..1379e8238b54 100644 --- a/packages/docusaurus/src/commands/swizzle/actions.ts +++ b/packages/docusaurus/src/commands/swizzle/actions.ts @@ -11,14 +11,14 @@ import path from 'path'; import _ from 'lodash'; import {Globby, posixPath, THEME_PATH} from '@docusaurus/utils'; import type {SwizzleAction, SwizzleComponentConfig} from '@docusaurus/types'; -import type {SwizzleOptions} from './common'; +import type {SwizzleCLIOptions} from './common'; import {askSwizzleAction} from './prompts'; export const SwizzleActions: SwizzleAction[] = ['wrap', 'eject']; export async function getAction( componentConfig: SwizzleComponentConfig, - options: Pick, + options: Pick, ): Promise { if (options.wrap) { return 'wrap'; diff --git a/packages/docusaurus/src/commands/swizzle/common.ts b/packages/docusaurus/src/commands/swizzle/common.ts index 2d399b60a731..4c6eeda8135c 100644 --- a/packages/docusaurus/src/commands/swizzle/common.ts +++ b/packages/docusaurus/src/commands/swizzle/common.ts @@ -61,7 +61,7 @@ export type SwizzlePlugin = { export type SwizzleContext = {plugins: SwizzlePlugin[]}; -export type SwizzleOptions = { +export type SwizzleCLIOptions = { typescript: boolean; danger: boolean; list: boolean; @@ -70,8 +70,8 @@ export type SwizzleOptions = { }; export function normalizeOptions( - options: Partial, -): SwizzleOptions { + options: Partial, +): SwizzleCLIOptions { return { typescript: options.typescript ?? false, danger: options.danger ?? false, diff --git a/packages/docusaurus/src/commands/swizzle/index.ts b/packages/docusaurus/src/commands/swizzle/index.ts index 1937785328a1..0d13d7387aab 100644 --- a/packages/docusaurus/src/commands/swizzle/index.ts +++ b/packages/docusaurus/src/commands/swizzle/index.ts @@ -10,7 +10,7 @@ import {getThemeName, getThemePath, getThemeNames} from './themes'; import {getThemeComponents, getComponentName} from './components'; import {helpTables, themeComponentsTable} from './tables'; import type {SwizzleAction, SwizzleComponentConfig} from '@docusaurus/types'; -import type {SwizzleOptions, SwizzlePlugin} from './common'; +import type {SwizzleCLIOptions, SwizzlePlugin} from './common'; import {normalizeOptions} from './common'; import type {ActionResult} from './actions'; import {eject, getAction, wrap} from './actions'; @@ -25,7 +25,7 @@ async function listAllThemeComponents({ }: { themeNames: string[]; plugins: SwizzlePlugin[]; - typescript: SwizzleOptions['typescript']; + typescript: SwizzleCLIOptions['typescript']; }) { const themeComponentsTables = ( await Promise.all( @@ -90,7 +90,7 @@ export async function swizzle( siteDir: string, themeNameParam: string | undefined, componentNameParam: string | undefined, - optionsParam: Partial, + optionsParam: Partial, ): Promise { const options = normalizeOptions(optionsParam); const {list, danger, typescript} = options; diff --git a/packages/docusaurus/src/commands/writeTranslations.ts b/packages/docusaurus/src/commands/writeTranslations.ts index 43acf9c5fab0..606c8447d698 100644 --- a/packages/docusaurus/src/commands/writeTranslations.ts +++ b/packages/docusaurus/src/commands/writeTranslations.ts @@ -5,9 +5,9 @@ * LICENSE file in the root directory of this source tree. */ -import type {ConfigOptions, InitializedPlugin} from '@docusaurus/types'; +import type {InitializedPlugin} from '@docusaurus/types'; import path from 'path'; -import {loadContext} from '../server'; +import {loadContext, type LoadContextOptions} from '../server'; import {initPlugins} from '../server/plugins/init'; import { @@ -23,6 +23,12 @@ import { } from '../server/translations/translationsExtractor'; import {getCustomBabelConfigFilePath, getBabelOptions} from '../webpack/utils'; +export type WriteTranslationsCLIOptions = Pick< + LoadContextOptions, + 'config' | 'locale' +> & + WriteTranslationsOptions; + /** * This is a hack, so that @docusaurus/theme-common translations are extracted! * A theme doesn't have a way to express that one of its dependency (like @@ -74,13 +80,11 @@ async function writePluginTranslationFiles({ export async function writeTranslations( siteDir: string, - options: Partial< - WriteTranslationsOptions & ConfigOptions & {locale?: string} - >, + options: Partial, ): Promise { const context = await loadContext({ siteDir, - customConfigFilePath: options.config, + config: options.config, locale: options.locale, }); const plugins = await initPlugins(context); diff --git a/packages/docusaurus/src/server/choosePort.ts b/packages/docusaurus/src/server/getHostPort.ts similarity index 85% rename from packages/docusaurus/src/server/choosePort.ts rename to packages/docusaurus/src/server/getHostPort.ts index 53a5b5c3cf84..c9792a45ec65 100644 --- a/packages/docusaurus/src/server/choosePort.ts +++ b/packages/docusaurus/src/server/getHostPort.ts @@ -8,6 +8,7 @@ import {execSync, type ExecSyncOptionsWithStringEncoding} from 'child_process'; import detect from 'detect-port'; import logger from '@docusaurus/logger'; +import {DEFAULT_PORT} from '@docusaurus/utils'; import prompts from 'prompts'; const execOptions: ExecSyncOptionsWithStringEncoding = { @@ -48,7 +49,7 @@ function getProcessForPort(port: number): string | null { * port is already being used. This feature was heavily inspired by * create-react-app and uses many of the same utility functions to implement it. */ -export async function choosePort( +async function choosePort( host: string, defaultPort: number, ): Promise { @@ -85,3 +86,18 @@ Would you like to run the app on another port instead?`), throw err; } } + +export type HostPortOptions = { + host?: string; + port?: string; +}; + +export async function getHostPort(options: HostPortOptions): Promise<{ + host: string; + port: number | null; +}> { + const host = options.host ?? 'localhost'; + const basePort = options.port ? parseInt(options.port, 10) : DEFAULT_PORT; + const port = await choosePort(host, basePort); + return {host, port}; +} diff --git a/packages/docusaurus/src/server/index.ts b/packages/docusaurus/src/server/index.ts index 0ada575f811f..55b2466d11c9 100644 --- a/packages/docusaurus/src/server/index.ts +++ b/packages/docusaurus/src/server/index.ts @@ -31,10 +31,10 @@ import type {DocusaurusConfig, LoadContext, Props} from '@docusaurus/types'; export type LoadContextOptions = { /** Usually the CWD; can be overridden with command argument. */ siteDir: string; - /** Can be customized with `--out-dir` option */ - customOutDir?: string; - /** Can be customized with `--config` option */ - customConfigFilePath?: string; + /** Custom output directory. Can be customized with `--out-dir` option */ + outDir?: string; + /** Custom config path. Can be customized with `--config` option */ + config?: string; /** Default is `i18n.defaultLocale` */ locale?: string; /** @@ -55,7 +55,12 @@ export type LoadContextOptions = { export async function loadContext( options: LoadContextOptions, ): Promise { - const {siteDir, customOutDir, locale, customConfigFilePath} = options; + const { + siteDir, + outDir: baseOutDir = DEFAULT_BUILD_DIR_NAME, + locale, + config: customConfigFilePath, + } = options; const generatedFilesDir = path.resolve(siteDir, GENERATED_FILES_DIR_NAME); const {siteConfig: initialSiteConfig, siteConfigPath} = await loadSiteConfig({ @@ -72,7 +77,7 @@ export async function loadContext( pathType: 'url', }); const outDir = localizePath({ - path: path.resolve(siteDir, customOutDir ?? DEFAULT_BUILD_DIR_NAME), + path: path.resolve(siteDir, baseOutDir), i18n, options, pathType: 'fs', diff --git a/packages/docusaurus/src/server/plugins/__tests__/init.test.ts b/packages/docusaurus/src/server/plugins/__tests__/init.test.ts index 3ecf57b0d860..adcd9147dcb6 100644 --- a/packages/docusaurus/src/server/plugins/__tests__/init.test.ts +++ b/packages/docusaurus/src/server/plugins/__tests__/init.test.ts @@ -37,9 +37,7 @@ describe('initPlugins', () => { it('throws user-friendly error message for plugins with bad values', async () => { await expect(() => - loadSite({ - customConfigFilePath: 'badPlugins.docusaurus.config.js', - }), + loadSite({config: 'badPlugins.docusaurus.config.js'}), ).rejects.toThrowErrorMatchingSnapshot(); }); });