diff --git a/src/Tempest/CommandBus/src/HandleAsyncCommand.php b/src/Tempest/CommandBus/src/HandleAsyncCommand.php index 79ede0702..52a414c80 100644 --- a/src/Tempest/CommandBus/src/HandleAsyncCommand.php +++ b/src/Tempest/CommandBus/src/HandleAsyncCommand.php @@ -37,7 +37,7 @@ public function __invoke(?string $uuid = null): ExitCode if (! $command) { $this->error('No pending command found'); - return ExitCode::ERROR; + return ExitCode::error(); } $commandHandler = $this->commandBusConfig->handlers[$command::class] ?? null; @@ -46,7 +46,7 @@ public function __invoke(?string $uuid = null): ExitCode $commandClass = $command::class; $this->error("No handler found for command {$commandClass}"); - return ExitCode::ERROR; + return ExitCode::error(); } $commandHandler->handler->invokeArgs( @@ -57,12 +57,12 @@ public function __invoke(?string $uuid = null): ExitCode $this->repository->markAsDone($uuid); $this->success('Done'); - return ExitCode::SUCCESS; + return ExitCode::success(); } catch (Throwable $throwable) { $this->repository->markAsFailed($uuid); $this->error($throwable->getMessage()); - return ExitCode::ERROR; + return ExitCode::error(); } } } diff --git a/src/Tempest/Console/src/Actions/ExecuteConsoleCommand.php b/src/Tempest/Console/src/Actions/ExecuteConsoleCommand.php index a799c3105..7cb8a47f5 100644 --- a/src/Tempest/Console/src/Actions/ExecuteConsoleCommand.php +++ b/src/Tempest/Console/src/Actions/ExecuteConsoleCommand.php @@ -48,7 +48,11 @@ private function getCallable(array $commandMiddleware): ConsoleMiddlewareCallabl $inputBuilder->build(), ); - return $exitCode ?? ExitCode::SUCCESS; + if (is_int($exitCode)) { + $exitCode = new ExitCode($exitCode); + } + + return $exitCode ?? ExitCode::success(); }); $middlewareStack = [...$this->consoleConfig->middleware, ...$commandMiddleware]; diff --git a/src/Tempest/Console/src/ConsoleApplication.php b/src/Tempest/Console/src/ConsoleApplication.php index be1e155af..02fa107b5 100644 --- a/src/Tempest/Console/src/ConsoleApplication.php +++ b/src/Tempest/Console/src/ConsoleApplication.php @@ -57,7 +57,7 @@ public function run(): void try { $exitCode = ($this->container->get(ExecuteConsoleCommand::class))($this->argumentBag->getCommandName()); - $this->container->get(Kernel::class)->shutdown($exitCode->value); + $this->container->get(Kernel::class)->shutdown($exitCode->code); } catch (Throwable $throwable) { foreach ($this->appConfig->errorHandlers as $exceptionHandler) { $exceptionHandler->handleException($throwable); diff --git a/src/Tempest/Console/src/ExitCode.php b/src/Tempest/Console/src/ExitCode.php index 4fe2807ec..da6b7df82 100644 --- a/src/Tempest/Console/src/ExitCode.php +++ b/src/Tempest/Console/src/ExitCode.php @@ -4,10 +4,38 @@ namespace Tempest\Console; -enum ExitCode: int +final readonly class ExitCode { - case SUCCESS = 0; - case ERROR = 1; - case INVALID = 2; - case CANCELLED = 25; + public function __construct( + public int $code, + ) { + if ($this->code < 0 || $this->code > 255) { + throw new InvalidExitCode($this->code); + } + } + + public function equals(self $other): bool + { + return $this->code === $other->code; + } + + public static function success(): self + { + return new self(0); + } + + public static function error(): self + { + return new self(1); + } + + public static function invalid(): self + { + return new self(2); + } + + public static function cancelled(): self + { + return new self(25); + } } diff --git a/src/Tempest/Console/src/InvalidExitCode.php b/src/Tempest/Console/src/InvalidExitCode.php new file mode 100644 index 000000000..4e866cbbc --- /dev/null +++ b/src/Tempest/Console/src/InvalidExitCode.php @@ -0,0 +1,15 @@ +console->confirm('Caution! Do you wish to continue?'); if (! $continue) { - return ExitCode::CANCELLED; + return ExitCode::cancelled(); } } diff --git a/src/Tempest/Console/src/Middleware/ConsoleExceptionMiddleware.php b/src/Tempest/Console/src/Middleware/ConsoleExceptionMiddleware.php index 4fb7abf30..fc9ce9056 100644 --- a/src/Tempest/Console/src/Middleware/ConsoleExceptionMiddleware.php +++ b/src/Tempest/Console/src/Middleware/ConsoleExceptionMiddleware.php @@ -26,6 +26,6 @@ public function __invoke(Invocation $invocation, ConsoleMiddlewareCallable $next $consoleException->render($this->console); } - return ExitCode::ERROR; + return ExitCode::error(); } } diff --git a/src/Tempest/Console/src/Middleware/HelpMiddleware.php b/src/Tempest/Console/src/Middleware/HelpMiddleware.php index 0d53ca383..28bbd6654 100644 --- a/src/Tempest/Console/src/Middleware/HelpMiddleware.php +++ b/src/Tempest/Console/src/Middleware/HelpMiddleware.php @@ -24,7 +24,7 @@ public function __invoke(Invocation $invocation, ConsoleMiddlewareCallable $next if ($invocation->argumentBag->get('-h') || $invocation->argumentBag->get('help')) { $this->renderHelp($invocation->consoleCommand); - return ExitCode::SUCCESS; + return ExitCode::success(); } return $next($invocation); diff --git a/src/Tempest/Console/src/Middleware/OverviewMiddleware.php b/src/Tempest/Console/src/Middleware/OverviewMiddleware.php index 3381e4d81..83683c471 100644 --- a/src/Tempest/Console/src/Middleware/OverviewMiddleware.php +++ b/src/Tempest/Console/src/Middleware/OverviewMiddleware.php @@ -27,7 +27,7 @@ public function __invoke(Invocation $invocation, ConsoleMiddlewareCallable $next if (! $invocation->argumentBag->getCommandName()) { $this->renderOverview(showHidden: $invocation->argumentBag->has('--all', '-a')); - return ExitCode::SUCCESS; + return ExitCode::success(); } return $next($invocation); diff --git a/src/Tempest/Console/src/Middleware/ResolveOrRescueMiddleware.php b/src/Tempest/Console/src/Middleware/ResolveOrRescueMiddleware.php index 0d363989f..e9b002bcd 100644 --- a/src/Tempest/Console/src/Middleware/ResolveOrRescueMiddleware.php +++ b/src/Tempest/Console/src/Middleware/ResolveOrRescueMiddleware.php @@ -42,7 +42,7 @@ private function rescue(string $commandName): ExitCode $similarCommands = $this->getSimilarCommands($commandName); if ($similarCommands === []) { - return ExitCode::ERROR; + return ExitCode::error(); } if (count($similarCommands) === 1) { @@ -50,7 +50,7 @@ private function rescue(string $commandName): ExitCode return $this->runIntendedCommand($similarCommands[0]); } - return ExitCode::CANCELLED; + return ExitCode::cancelled(); } $intendedCommand = $this->console->ask( diff --git a/src/Tempest/Console/src/Testing/ConsoleTester.php b/src/Tempest/Console/src/Testing/ConsoleTester.php index effb93f06..565bbc37b 100644 --- a/src/Tempest/Console/src/Testing/ConsoleTester.php +++ b/src/Tempest/Console/src/Testing/ConsoleTester.php @@ -79,7 +79,7 @@ public function call(string|Closure|array $command): self if ($command instanceof Closure) { $fiber = new Fiber(function () use ($clone, $command, $console): void { - $clone->exitCode = $command($console) ?? ExitCode::SUCCESS; + $clone->exitCode = $command($console) ?? ExitCode::success(); }); } else { if (is_string($command) && class_exists($command)) { @@ -252,37 +252,37 @@ public function assertJson(): self public function assertExitCode(ExitCode $exitCode): self { - Assert::assertNotNull($this->exitCode, "Expected {$exitCode->name}, but instead no exit code was set — maybe you missed providing some input?"); + Assert::assertNotNull($this->exitCode, "Expected the exit code to be {$exitCode->code}, but instead no exit code was set — maybe you missed providing some input?"); - Assert::assertSame($exitCode, $this->exitCode, "Expected the exit code to be {$exitCode->name}, instead got {$this->exitCode->name}"); + Assert::assertTrue($exitCode->equals($this->exitCode), "Expected the exit code to be {$exitCode->code}, instead got {$this->exitCode->code}"); return $this; } public function assertSuccess(): self { - $this->assertExitCode(ExitCode::SUCCESS); + $this->assertExitCode(ExitCode::success()); return $this; } public function assertError(): self { - $this->assertExitCode(ExitCode::ERROR); + $this->assertExitCode(ExitCode::error()); return $this; } public function assertCancelled(): self { - $this->assertExitCode(ExitCode::CANCELLED); + $this->assertExitCode(ExitCode::cancelled()); return $this; } public function assertInvalid(): self { - $this->assertExitCode(ExitCode::INVALID); + $this->assertExitCode(ExitCode::invalid()); return $this; } diff --git a/src/Tempest/Framework/Commands/ConfigShowCommand.php b/src/Tempest/Framework/Commands/ConfigShowCommand.php index ce0c2f1a1..0c7d06935 100644 --- a/src/Tempest/Framework/Commands/ConfigShowCommand.php +++ b/src/Tempest/Framework/Commands/ConfigShowCommand.php @@ -46,7 +46,7 @@ public function __invoke( if (empty($configs)) { $this->console->error('No configuration found'); - return ExitCode::ERROR; + return ExitCode::error(); } match ($format) { @@ -55,7 +55,7 @@ public function __invoke( ConfigShowFormat::FILE => $this->file($configs), }; - return ExitCode::SUCCESS; + return ExitCode::success(); } /** diff --git a/tests/Integration/Console/Testing/ConsoleTesterTest.php b/tests/Integration/Console/Testing/ConsoleTesterTest.php index 1e6f41048..e0ba6a320 100644 --- a/tests/Integration/Console/Testing/ConsoleTesterTest.php +++ b/tests/Integration/Console/Testing/ConsoleTesterTest.php @@ -49,28 +49,28 @@ public function test_call_with_command(): void public function test_exit_code_success(): void { $this->console - ->call(fn () => ExitCode::SUCCESS) + ->call(fn () => ExitCode::success()) ->assertSuccess(); } public function test_exit_code_invalid(): void { $this->console - ->call(fn () => ExitCode::INVALID) + ->call(fn () => ExitCode::invalid()) ->assertInvalid(); } public function test_exit_code_error(): void { $this->console - ->call(fn () => ExitCode::ERROR) + ->call(fn () => ExitCode::error()) ->assertError(); } public function test_exit_code_cancelled(): void { $this->console - ->call(fn () => ExitCode::CANCELLED) + ->call(fn () => ExitCode::cancelled()) ->assertCancelled(); }