Skip to content

Commit 7094e65

Browse files
Pass flags for alternative Node package managers (#442)
* flags for other package managers * Update NewCommand.php --------- Co-authored-by: Taylor Otwell <[email protected]>
1 parent dcc4b0e commit 7094e65

File tree

2 files changed

+136
-27
lines changed

2 files changed

+136
-27
lines changed

src/Enums/NodePackageManager.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
namespace Laravel\Installer\Console\Enums;
4+
5+
enum NodePackageManager: string
6+
{
7+
case NPM = 'npm';
8+
case YARN = 'yarn';
9+
case PNPM = 'pnpm';
10+
case BUN = 'bun';
11+
12+
public function installCommand(): string
13+
{
14+
return match ($this) {
15+
self::NPM => 'npm install',
16+
self::YARN => 'yarn install',
17+
self::PNPM => 'pnpm install',
18+
self::BUN => 'bun install',
19+
};
20+
}
21+
22+
public function runCommand(): string
23+
{
24+
return match ($this) {
25+
self::NPM => 'npm run',
26+
self::YARN => 'yarn',
27+
self::PNPM => 'pnpm',
28+
self::BUN => 'bun run',
29+
};
30+
}
31+
32+
public function buildCommand(): string
33+
{
34+
return $this->runCommand().' build';
35+
}
36+
37+
public function runLocalOrRemoteCommand(): string
38+
{
39+
return match ($this) {
40+
self::NPM => 'npx',
41+
self::YARN => 'npx',
42+
self::PNPM => 'pnpm dlx',
43+
self::BUN => 'npx',
44+
};
45+
}
46+
47+
public static function allLockFiles(): array
48+
{
49+
return ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lock', 'bun.lockb'];
50+
}
51+
52+
public function lockFiles(): array
53+
{
54+
return match ($this) {
55+
self::NPM => ['package-lock.json'],
56+
self::YARN => ['yarn.lock'],
57+
self::PNPM => ['pnpm-lock.yaml'],
58+
self::BUN => ['bun.lock', 'bun.lockb'],
59+
};
60+
}
61+
}

src/NewCommand.php

Lines changed: 75 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Illuminate\Support\Composer;
77
use Illuminate\Support\ProcessUtils;
88
use Illuminate\Support\Str;
9+
use Laravel\Installer\Console\Enums\NodePackageManager;
910
use RecursiveDirectoryIterator;
1011
use RecursiveIteratorIterator;
1112
use RuntimeException;
@@ -64,6 +65,9 @@ protected function configure()
6465
->addOption('pest', null, InputOption::VALUE_NONE, 'Install the Pest testing framework')
6566
->addOption('phpunit', null, InputOption::VALUE_NONE, 'Install the PHPUnit testing framework')
6667
->addOption('npm', null, InputOption::VALUE_NONE, 'Install and build NPM dependencies')
68+
->addOption('pnpm', null, InputOption::VALUE_NONE, 'Install and build NPM dependencies via PNPM')
69+
->addOption('bun', null, InputOption::VALUE_NONE, 'Install and build NPM dependencies via Bun')
70+
->addOption('yarn', null, InputOption::VALUE_NONE, 'Install and build NPM dependencies via Yarn')
6771
->addOption('using', null, InputOption::VALUE_OPTIONAL, 'Install a custom starter kit from a community maintained package')
6872
->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces install even if the directory already exists');
6973
}
@@ -499,43 +503,35 @@ protected function execute(InputInterface $input, OutputInterface $output): int
499503
$output->writeln('');
500504
}
501505

502-
$this->configureComposerDevScript($directory);
506+
[$packageManager, $runPackageManager] = $this->determinePackageManager($directory, $input);
507+
508+
$this->configureComposerScripts($packageManager);
503509

504510
if ($input->getOption('pest')) {
505511
$output->writeln('');
506512
}
507513

508-
$packageInstall = 'npm install';
509-
$packageBuild = 'npm run build';
510-
511-
if (file_exists($directory.'/pnpm-lock.yaml')) {
512-
$packageInstall = 'pnpm install';
513-
$packageBuild = 'pnpm run build';
514-
} elseif (file_exists($directory.'/yarn.lock')) {
515-
$packageInstall = 'yarn install';
516-
$packageBuild = 'yarn run build';
517-
} elseif (file_exists($directory.'/bun.lock')) {
518-
$packageInstall = 'bun install';
519-
$packageBuild = 'bun run build';
514+
if (! $runPackageManager && $input->isInteractive()) {
515+
$runPackageManager = confirm(
516+
label: 'Would you like to run <options=bold>'.$packageManager->installCommand().'</> and <options=bold>'.$packageManager->buildCommand().'</>?'
517+
);
520518
}
521519

522-
$runNpm = $input->getOption('npm');
523-
524-
if (! $input->getOption('npm') && $input->isInteractive()) {
525-
$runNpm = confirm(
526-
label: 'Would you like to run <options=bold>'.$packageInstall.'</> and <options=bold>'.$packageBuild.'</>?'
527-
);
520+
foreach (NodePackageManager::allLockFiles() as $lockFile) {
521+
if (! in_array($lockFile, $packageManager->lockFiles()) && file_exists($directory.'/'.$lockFile)) {
522+
(new Filesystem())->delete($directory.'/'.$lockFile);
523+
}
528524
}
529525

530-
if ($runNpm) {
531-
$this->runCommands([$packageInstall, $packageBuild], $input, $output, workingPath: $directory);
526+
if ($runPackageManager) {
527+
$this->runCommands([$packageManager->installCommand(), $packageManager->buildCommand()], $input, $output, workingPath: $directory);
532528
}
533529

534530
$output->writeln(" <bg=blue;fg=white> INFO </> Application ready in <options=bold>[{$name}]</>. You can start your local development using:".PHP_EOL);
535531
$output->writeln('<fg=gray>➜</> <options=bold>cd '.$name.'</>');
536532

537-
if (! $runNpm) {
538-
$output->writeln('<fg=gray>➜</> <options=bold>'.$packageInstall.' && npm run build</>');
533+
if (! $runPackageManager) {
534+
$output->writeln('<fg=gray>➜</> <options=bold>'.$packageManager->installCommand().' && '.$packageManager->buildCommand().'</>');
539535
}
540536

541537
if ($this->isParkedOnHerdOrValet($directory)) {
@@ -553,6 +549,48 @@ protected function execute(InputInterface $input, OutputInterface $output): int
553549
return $process->getExitCode();
554550
}
555551

552+
/**
553+
* Determine the Node package manager to use.
554+
*
555+
* @param string $directory
556+
* @param \Symfony\Component\Console\Input\InputInterface $input
557+
* @return array{NodePackageManager, bool}
558+
*/
559+
protected function determinePackageManager(string $directory, InputInterface $input): array
560+
{
561+
// If they passed a specific flag, respect the user's choice...
562+
if ($input->getOption('pnpm')) {
563+
return [NodePackageManager::PNPM, true];
564+
}
565+
566+
if ($input->getOption('bun')) {
567+
return [NodePackageManager::BUN, true];
568+
}
569+
570+
if ($input->getOption('yarn')) {
571+
return [NodePackageManager::YARN, true];
572+
}
573+
574+
if ($input->getOption('npm')) {
575+
return [NodePackageManager::NPM, true];
576+
}
577+
578+
// Check for an existing lock file to determine the package manager...
579+
foreach (NodePackageManager::cases() as $packageManager) {
580+
if ($packageManager === NodePackageManager::NPM) {
581+
continue;
582+
}
583+
584+
foreach ($packageManager->lockFiles() as $lockFile) {
585+
if (file_exists($directory.'/'.$lockFile)) {
586+
return [$packageManager, false];
587+
}
588+
}
589+
}
590+
591+
return [NodePackageManager::NPM, false];
592+
}
593+
556594
/**
557595
* Return the local machine's default Git branch if set or default to `main`.
558596
*
@@ -920,21 +958,31 @@ protected function pushToGitHub(string $name, string $directory, InputInterface
920958
}
921959

922960
/**
923-
* Configure the Composer "dev" script.
961+
* Configure the Composer scripts for the selected package manager.
924962
*
925-
* @param string $directory
963+
* @param NodePackageManager $packageManager
926964
* @return void
927965
*/
928-
protected function configureComposerDevScript(string $directory): void
966+
protected function configureComposerScripts(NodePackageManager $packageManager): void
929967
{
930-
$this->composer->modify(function (array $content) {
968+
$this->composer->modify(function (array $content) use ($packageManager) {
931969
if (windows_os()) {
932970
$content['scripts']['dev'] = [
933971
'Composer\\Config::disableProcessTimeout',
934972
"npx concurrently -c \"#93c5fd,#c4b5fd,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"npm run dev\" --names='server,queue,vite'",
935973
];
936974
}
937975

976+
foreach (['dev', 'dev:ssr', 'setup'] as $scriptKey) {
977+
if (array_key_exists($scriptKey, $content['scripts'])) {
978+
$content['scripts'][$scriptKey] = str_replace(
979+
['npm', 'npx', 'ppnpm'],
980+
[$packageManager->value, $packageManager->runLocalOrRemoteCommand(), 'pnpm'],
981+
$content['scripts'][$scriptKey],
982+
);
983+
}
984+
}
985+
938986
return $content;
939987
});
940988
}

0 commit comments

Comments
 (0)