feat(create): better detection of package manager preference (#6679)

Co-authored-by: sebastienlorber <lorber.sebastien@gmail.com>
This commit is contained in:
Alexey Pyltsyn 2022-02-23 18:22:40 +03:00 committed by GitHub
parent c3370be64d
commit 26d223dbeb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 101 additions and 18 deletions

View file

@ -17,12 +17,56 @@ import {fileURLToPath} from 'url';
const RecommendedTemplate = 'classic';
const TypeScriptTemplateSuffix = '-typescript';
function hasYarn() {
try {
return shell.exec('yarnpkg --version', {silent: true}).code === 0;
} catch (e) {
return false;
const DefaultPackageManager = 'npm';
const SupportedPackageManagers = {
npm: 'package-lock.json',
yarn: 'yarn.lock',
pnpm: 'pnpm-lock.yaml',
};
type SupportedPackageManager = keyof typeof SupportedPackageManagers;
const PackageManagersList = Object.keys(
SupportedPackageManagers,
) as SupportedPackageManager[];
async function findPackageManagerFromLockFile(): Promise<
SupportedPackageManager | undefined
> {
for (const packageManager of PackageManagersList) {
const lockFilePath = path.resolve(
process.cwd(),
SupportedPackageManagers[packageManager],
);
if (await fs.pathExists(lockFilePath)) {
return packageManager;
}
}
return undefined;
}
function findPackageManagerFromUserAgent():
| SupportedPackageManager
| undefined {
return PackageManagersList.find((packageManager) =>
process.env.npm_config_user_agent?.startsWith(packageManager),
);
}
async function getPackageManager(
forceUseNpm?: boolean,
): Promise<SupportedPackageManager> {
// TODO replace --use-npm by --package-manager option
if (forceUseNpm) {
return 'npm';
}
return (
(await findPackageManagerFromLockFile()) ??
findPackageManagerFromUserAgent() ??
DefaultPackageManager
);
}
function isValidGitRepoUrl(gitRepoUrl: string) {
@ -131,14 +175,13 @@ export default async function init(
gitStrategy: typeof gitStrategies[number];
}> = {},
): Promise<void> {
const useYarn = cliOptions.useNpm ? false : hasYarn();
const pkgManager = await getPackageManager(cliOptions.useNpm);
const templatesDir = fileURLToPath(new URL('../templates', import.meta.url));
const templates = await readTemplates(templatesDir);
const hasTS = (templateName: string) =>
fs.pathExists(
path.resolve(templatesDir, `${templateName}${TypeScriptTemplateSuffix}`),
);
let name = siteName;
// Prompt if siteName is not passed from CLI.
@ -313,21 +356,23 @@ export default async function init(
await fs.remove(path.join(dest, 'gitignore'));
}
const pkgManager = useYarn ? 'yarn' : 'npm';
// Display the most elegant way to cd.
const cdpath = path.relative('.', dest);
if (!cliOptions.skipInstall) {
shell.cd(dest);
logger.info`Installing dependencies with name=${pkgManager}...`;
if (
shell.exec(useYarn ? 'yarn' : 'npm install --color always', {
env: {
...process.env,
// Force coloring the output, since the command is invoked by shelljs,
// which is not the interactive shell
...(supportsColor.stdout ? {FORCE_COLOR: '1'} : {}),
shell.exec(
pkgManager === 'yarn' ? 'yarn' : `${pkgManager} install --color always`,
{
env: {
...process.env,
// Force coloring the output, since the command is invoked,
// by shelljs which is not the interactive shell
...(supportsColor.stdout ? {FORCE_COLOR: '1'} : {}),
},
},
}).code !== 0
).code !== 0
) {
logger.error('Dependency installation failed.');
logger.info`The site directory has already been created, and you can retry by typing:
@ -338,16 +383,17 @@ export default async function init(
}
}
const useNpm = pkgManager === 'npm';
logger.success`Created path=${cdpath}.`;
logger.info`Inside that directory, you can run several commands:
code=${`${pkgManager} start`}
Starts the development server.
code=${`${pkgManager} ${useYarn ? '' : 'run '}build`}
code=${`${pkgManager} ${useNpm ? 'run ' : ''}build`}
Bundles your website into static files for production.
code=${`${pkgManager} ${useYarn ? '' : 'run '}serve`}
code=${`${pkgManager} ${useNpm ? 'run ' : ''}serve`}
Serves the built website locally.
code=${`${pkgManager} deploy`}