From a70514205d48db9b87844520e245e441819999ba Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Thu, 24 Feb 2022 18:50:37 +0800 Subject: [PATCH] feat(create): new --package-manager option; interactive package manager selection (#6750) --- admin/scripts/test-release.sh | 5 +-- packages/create-docusaurus/bin/index.js | 15 +++++--- packages/create-docusaurus/src/index.ts | 51 +++++++++++++++++++++---- website/docs/installation.md | 37 +++++++++++------- 4 files changed, 76 insertions(+), 32 deletions(-) diff --git a/admin/scripts/test-release.sh b/admin/scripts/test-release.sh index 57640225a5..2ecda2a3e5 100755 --- a/admin/scripts/test-release.sh +++ b/admin/scripts/test-release.sh @@ -12,13 +12,10 @@ NEW_VERSION="$(node -p "require('./packages/docusaurus/package.json').version"). CONTAINER_NAME="verdaccio" EXTRA_OPTS="" -usage() { echo "Usage: $0 [-n] [-s]" 1>&2; exit 1; } +usage() { echo "Usage: $0 [-s]" 1>&2; exit 1; } while getopts ":ns" o; do case "${o}" in - n) - EXTRA_OPTS="${EXTRA_OPTS} --use-npm" - ;; s) EXTRA_OPTS="${EXTRA_OPTS} --skip-install" ;; diff --git a/packages/create-docusaurus/bin/index.js b/packages/create-docusaurus/bin/index.js index e5461c8d3b..6c51bbec4f 100755 --- a/packages/create-docusaurus/bin/index.js +++ b/packages/create-docusaurus/bin/index.js @@ -36,14 +36,17 @@ program.version(packageJson.version); program .arguments('[siteName] [template] [rootDir]') - .option('--use-npm', 'Use NPM as package manage even with Yarn installed') .option( - '--skip-install', + '-p, --package-manager ', + 'The package manager used to install dependencies. One of yarn, npm, and pnpm.', + ) + .option( + '-s, --skip-install', 'Do not run package manager immediately after scaffolding', ) - .option('--typescript', 'Use the TypeScript template variant') + .option('-t, --typescript', 'Use the TypeScript template variant') .option( - '--git-strategy ', + '-g, --git-strategy ', `Only used if the template is a git repository. \`deep\`: preserve full history \`shallow\`: clone with --depth=1 @@ -56,10 +59,10 @@ program siteName, template, rootDir = '.', - {useNpm, skipInstall, typescript, gitStrategy} = {}, + {packageManager, skipInstall, typescript, gitStrategy} = {}, ) => { wrapCommand(init)(path.resolve(rootDir), siteName, template, { - useNpm, + packageManager, skipInstall, typescript, gitStrategy, diff --git a/packages/create-docusaurus/src/index.ts b/packages/create-docusaurus/src/index.ts index 9f2f37965a..aa270c292f 100755 --- a/packages/create-docusaurus/src/index.ts +++ b/packages/create-docusaurus/src/index.ts @@ -17,6 +17,8 @@ import {fileURLToPath} from 'url'; const RecommendedTemplate = 'classic'; const TypeScriptTemplateSuffix = '-typescript'; +// Only used in the rare, rare case of running globally installed create + +// using --skip-install. We need a default name to show the tip text const DefaultPackageManager = 'npm'; const SupportedPackageManagers = { @@ -54,18 +56,48 @@ function findPackageManagerFromUserAgent(): ); } -async function getPackageManager( - forceUseNpm?: boolean, -): Promise { - // TODO replace --use-npm by --package-manager option - if (forceUseNpm) { +async function askForPackageManagerChoice(): Promise { + const hasYarn = shell.exec('yarn --version', {silent: true}).code === 0; + const hasPNPM = shell.exec('pnpm --version', {silent: true}).code === 0; + + if (!hasYarn && !hasPNPM) { return 'npm'; } + const choices = ['npm', hasYarn && 'yarn', hasPNPM && 'pnpm'] + .filter((p): p is string => Boolean(p)) + .map((p) => ({title: p, value: p})); + + return ( + await prompts({ + type: 'select', + name: 'packageManager', + message: 'Select a package manager...', + choices, + }) + ).packageManager; +} + +async function getPackageManager( + packageManagerChoice: SupportedPackageManager | undefined, + skipInstall: boolean = false, +): Promise { + if ( + packageManagerChoice && + !PackageManagersList.includes(packageManagerChoice) + ) { + throw new Error( + `Invalid package manager choice ${packageManagerChoice}. Must be one of ${PackageManagersList.join( + ', ', + )}`, + ); + } return ( + packageManagerChoice ?? (await findPackageManagerFromLockFile()) ?? findPackageManagerFromUserAgent() ?? - DefaultPackageManager + // This only happens if the user has a global installation in PATH + (skipInstall ? DefaultPackageManager : askForPackageManagerChoice()) ); } @@ -169,13 +201,12 @@ export default async function init( siteName?: string, reqTemplate?: string, cliOptions: Partial<{ - useNpm: boolean; + packageManager: SupportedPackageManager; skipInstall: boolean; typescript: boolean; gitStrategy: typeof gitStrategies[number]; }> = {}, ): Promise { - const pkgManager = await getPackageManager(cliOptions.useNpm); const templatesDir = fileURLToPath(new URL('../templates', import.meta.url)); const templates = await readTemplates(templatesDir); const hasTS = (templateName: string) => @@ -358,6 +389,10 @@ export default async function init( // Display the most elegant way to cd. const cdpath = path.relative('.', dest); + const pkgManager = await getPackageManager( + cliOptions.packageManager, + cliOptions.skipInstall, + ); if (!cliOptions.skipInstall) { shell.cd(dest); logger.info`Installing dependencies with name=${pkgManager}...`; diff --git a/website/docs/installation.md b/website/docs/installation.md index ba81f9cc4f..0a79f9b3f7 100644 --- a/website/docs/installation.md +++ b/website/docs/installation.md @@ -37,10 +37,18 @@ Example: npx create-docusaurus@latest website classic ``` -If you do not specify `name` or `template`, it will prompt you for them. We recommend the `classic` template so that you can get started quickly, and it contains features found in Docusaurus 1. The `classic` template contains `@docusaurus/preset-classic` which includes standard documentation, a blog, custom pages, and a CSS framework (with dark mode support). You can get up and running extremely quickly with the classic template and customize things later on when you have gained more familiarity with Docusaurus. +If you do not specify `name` or `template`, it will prompt you for them. + +We recommend the `classic` template so that you can get started quickly, and it contains features found in Docusaurus 1. The `classic` template contains `@docusaurus/preset-classic` which includes standard documentation, a blog, custom pages, and a CSS framework (with dark mode support). You can get up and running extremely quickly with the classic template and customize things later on when you have gained more familiarity with Docusaurus. The `template` also accepts a git repo URL or a local file path, with the latter evaluated relative to the current working directory. The repo/folder content will be copied to the site directory. If it's a git repository, you can also specify a cloning strategy. Run `npx create-docusaurus@latest --help` for more information. +You can also use the template's TypeScript variant by passing the `--typescript` flag. + +```bash +npx create-docusaurus@latest my-website classic --typescript +``` + :::info FB-Only If you are setting up a new Docusaurus website for a Facebook open source project, use the `facebook` template instead, which comes with some useful Facebook-specific defaults: @@ -51,20 +59,8 @@ npx create-docusaurus@latest my-website facebook ::: -If you want to skip installing dependencies, use the `--skip-install` option, like the following: - -```bash -npx create-docusaurus@latest my-website classic --skip-install -``` - -You can also use the template's TypeScript variant by passing the `--typescript` flag. - -```bash -npx create-docusaurus@latest my-website classic --typescript -``` -
- Alternative installation methods + Alternative installation commands You can also initialize a new project using your preferred project manager: @@ -96,6 +92,19 @@ pnpm create docusaurus website classic
+Docusaurus makes best efforts to select a package manager to install dependencies for you, based on the command you are using and the project you are in. You can override this behavior by using `--package-manager [npm/yarn/pnpm]`. + +```bash +# Use Yarn to install dependencies even when the command is npx +npx create-docusaurus@latest my-website classic --package-manager yarn +``` + +If you want to skip installing dependencies, use the `--skip-install` option. + +```bash +npx create-docusaurus@latest my-website classic --skip-install +``` + ## Project structure {#project-structure} Assuming you chose the classic template and named your site `my-website`, you will see the following files generated under a new directory `my-website/`: