diff --git a/.ai/foundation.blade.php b/.ai/foundation.blade.php index 8dbc49b..82fcf5d 100644 --- a/.ai/foundation.blade.php +++ b/.ai/foundation.blade.php @@ -27,7 +27,7 @@ - Do not change the application's dependencies without approval. ## Frontend Bundling -- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `npm run build`, `npm run dev`, or `composer run dev`. Ask them. +- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `{{ $assist->nodePackageManager() }} run build`, `{{ $assist->nodePackageManager() }} run dev`, or `composer run dev`. Ask them. ## Replies - Be concise in your explanations - focus on what's important rather than explaining obvious details. diff --git a/.ai/laravel/core.blade.php b/.ai/laravel/core.blade.php index 6c27ba6..de91549 100644 --- a/.ai/laravel/core.blade.php +++ b/.ai/laravel/core.blade.php @@ -39,4 +39,4 @@ - When creating tests, make use of `php artisan make:test [options] ` to create a feature test, and pass `--unit` to create a unit test. Most tests should be feature tests. ### Vite Error -- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `npm run build` or ask the user to run `npm run dev` or `composer run dev`. +- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `{{ $assist->nodePackageManager() }} run build` or ask the user to run `{{ $assist->nodePackageManager() }} run dev` or `composer run dev`. diff --git a/src/Install/GuidelineAssist.php b/src/Install/GuidelineAssist.php index ce7b597..c9b88e5 100644 --- a/src/Install/GuidelineAssist.php +++ b/src/Install/GuidelineAssist.php @@ -19,11 +19,20 @@ class GuidelineAssist protected static array $classes = []; + protected string $nodePackageManager = 'npm'; + public function __construct() { $this->modelPaths = $this->discover(fn ($reflection) => ($reflection->isSubclassOf(Model::class) && ! $reflection->isAbstract())); $this->controllerPaths = $this->discover(fn (ReflectionClass $reflection) => (stripos($reflection->getName(), 'controller') !== false || stripos($reflection->getNamespaceName(), 'controller') !== false)); $this->enumPaths = $this->discover(fn ($reflection) => $reflection->isEnum()); + $this->nodePackageManager = match (true) { + file_exists(base_path('package-lock.json')) => 'npm', + file_exists(base_path('pnpm-lock.yaml')) => 'pnpm', + file_exists(base_path('yarn.lock')) => 'yarn', + file_exists(base_path('bun.lockb')) => 'bun', + default => 'npm', + }; } /** @@ -156,4 +165,9 @@ public function enumContents(): string return file_get_contents(current($this->enumPaths)); } + + public function nodePackageManager(): string + { + return $this->nodePackageManager; + } } diff --git a/tests/Feature/Install/GuidelineAssistTest.php b/tests/Feature/Install/GuidelineAssistTest.php new file mode 100644 index 0000000..52cd618 --- /dev/null +++ b/tests/Feature/Install/GuidelineAssistTest.php @@ -0,0 +1,68 @@ +nodePackageManager())->toBe('npm'); +}); + +test('it detects pnpm when pnpm-lock.yaml exists', function () { + file_put_contents(base_path('pnpm-lock.yaml'), 'lockfileVersion: 6.0'); + + $assist = new GuidelineAssist(); + expect($assist->nodePackageManager())->toBe('pnpm'); +}); + +test('it detects yarn when yarn.lock exists', function () { + file_put_contents(base_path('yarn.lock'), '# This is yarn lock file'); + + $assist = new GuidelineAssist(); + expect($assist->nodePackageManager())->toBe('yarn'); +}); + +test('it detects bun when bun.lockb exists', function () { + file_put_contents(base_path('bun.lockb'), 'bun binary lock file'); + + $assist = new GuidelineAssist(); + expect($assist->nodePackageManager())->toBe('bun'); +}); + +test('it defaults to npm when no lock files exist', function () { + $assist = new GuidelineAssist(); + expect($assist->nodePackageManager())->toBe('npm'); +});