Skip to content

Commit f63b8d2

Browse files
authored
refactor(router): improve static page generation console command output (#1100)
1 parent e06dd63 commit f63b8d2

16 files changed

+320
-49
lines changed

src/Tempest/Router/src/RouteConfig.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
namespace Tempest\Router;
66

7-
use Tempest\Reflection\ClassReflector;
8-
97
final class RouteConfig
108
{
119
public function __construct(
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Tempest\Router\Static\Exceptions;
4+
5+
use Tempest\Http\Status;
6+
7+
final class InvalidStatusCodeException extends StaticPageException
8+
{
9+
public function __construct(
10+
string $uri,
11+
public readonly Status $status,
12+
) {
13+
parent::__construct("HTTP {$status->value}", $uri);
14+
}
15+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Tempest\Router\Static\Exceptions;
4+
5+
final class NoTextualBodyException extends StaticPageException
6+
{
7+
public function __construct(
8+
string $uri,
9+
) {
10+
parent::__construct('No textual body', $uri);
11+
}
12+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Tempest\Router\Static\Exceptions;
4+
5+
use Exception;
6+
7+
abstract class StaticPageException extends Exception
8+
{
9+
public function __construct(
10+
string $message,
11+
public readonly string $uri,
12+
) {
13+
parent::__construct($message);
14+
}
15+
}

src/Tempest/Router/src/Static/StaticCleanCommand.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
use Tempest\Console\Middleware\CautionMiddleware;
1414
use Tempest\Console\Middleware\ForceMiddleware;
1515
use Tempest\Core\Kernel;
16+
use Tempest\EventBus\EventBus;
1617

1718
final readonly class StaticCleanCommand
1819
{
1920
use HasConsole;
2021

2122
public function __construct(
2223
private Kernel $kernel,
24+
private EventBus $eventBus,
2325
) {}
2426

2527
#[ConsoleCommand(
@@ -29,13 +31,22 @@ public function __construct(
2931
)]
3032
public function __invoke(): void
3133
{
34+
$this->console->header('Cleaning static pages');
35+
3236
$directoryIterator = new RecursiveDirectoryIterator($this->kernel->root . '/public');
3337
$directoryIterator->setFlags(FilesystemIterator::SKIP_DOTS);
3438

39+
$removed = 0;
40+
41+
$this->eventBus->listen(StaticPageRemoved::class, function (StaticPageRemoved $event) use (&$removed): void {
42+
$removed++;
43+
$this->keyValue("<style='fg-gray'>{$event->path}</style>", "<style='fg-green'>REMOVED</style>");
44+
});
45+
3546
$this->removeFiles($directoryIterator);
3647
$this->removeEmptyDirectories($directoryIterator);
3748

38-
$this->success('Done.');
49+
$this->keyValue('Static pages removed', "<style='fg-green'>{$removed}</style>");
3950
}
4051

4152
private function removeFiles(RecursiveDirectoryIterator $directoryIterator): void
@@ -55,7 +66,7 @@ private function removeFiles(RecursiveDirectoryIterator $directoryIterator): voi
5566

5667
$pathName = str_replace('\\', '/', $file->getPathname());
5768

58-
$this->writeln("- <u>{$pathName}</u> removed");
69+
$this->eventBus->dispatch(new StaticPageRemoved($pathName));
5970
}
6071
}
6172

@@ -72,10 +83,6 @@ private function removeEmptyDirectories(RecursiveDirectoryIterator $directoryIte
7283
}
7384

7485
rmdir($file->getPathname());
75-
76-
$pathName = str_replace('\\', '/', $file->getPathname());
77-
78-
$this->writeln("- <u>{$pathName}</u> directory removed");
7986
}
8087
}
8188
}

src/Tempest/Router/src/Static/StaticGenerateCommand.php

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,24 @@
55
namespace Tempest\Router\Static;
66

77
use Tempest\Console\Console;
8+
use Tempest\Console\ConsoleArgument;
89
use Tempest\Console\ConsoleCommand;
10+
use Tempest\Console\ExitCode;
911
use Tempest\Console\HasConsole;
1012
use Tempest\Container\Container;
1113
use Tempest\Core\Kernel;
14+
use Tempest\EventBus\EventBus;
1215
use Tempest\Http\Method;
1316
use Tempest\Http\Status;
1417
use Tempest\Router\DataProvider;
1518
use Tempest\Router\GenericRequest;
1619
use Tempest\Router\Router;
20+
use Tempest\Router\Static\Exceptions\InvalidStatusCodeException;
21+
use Tempest\Router\Static\Exceptions\NoTextualBodyException;
22+
use Tempest\View\Exceptions\ViewCompilationError;
1723
use Tempest\View\View;
1824
use Tempest\View\ViewRenderer;
25+
use Tempest\Vite\Exceptions\ManifestNotFoundException;
1926
use Throwable;
2027

2128
use function Tempest\Support\path;
@@ -32,16 +39,44 @@ public function __construct(
3239
private StaticPageConfig $staticPageConfig,
3340
private Router $router,
3441
private ViewRenderer $viewRenderer,
42+
private EventBus $eventBus,
3543
) {}
3644

37-
#[ConsoleCommand(
38-
name: 'static:generate',
39-
description: 'Compiles static pages',
40-
)]
41-
public function __invoke(?string $filter = null): void
42-
{
45+
#[ConsoleCommand(name: 'static:generate', description: 'Compiles static pages')]
46+
public function __invoke(
47+
?string $filter = null,
48+
#[ConsoleArgument(aliases: ['v'])]
49+
bool $verbose = false,
50+
): ExitCode {
4351
$publicPath = path($this->kernel->root, 'public');
4452

53+
$generated = 0;
54+
$failures = 0;
55+
56+
$this->console->header('Generating static pages');
57+
58+
$this->eventBus->listen(StaticPageGenerated::class, function (StaticPageGenerated $event) use (&$generated): void {
59+
$generated++;
60+
$this->keyValue("<style='fg-gray'>{$event->uri}</style>", "<style='fg-green'>{$event->path}</style>");
61+
});
62+
63+
$this->eventBus->listen(StaticPageGenerationFailed::class, function (StaticPageGenerationFailed $event) use (&$failures, $verbose): void {
64+
$failures++;
65+
66+
match (true) {
67+
$event->exception instanceof InvalidStatusCodeException => $this->keyValue(
68+
"<style='fg-gray'>{$event->path}</style>",
69+
"<style='fg-red'>HTTP {$event->exception->status->value}</style>",
70+
),
71+
$event->exception instanceof NoTextualBodyException => $this->keyValue(
72+
"<style='fg-gray'>{$event->path}</style>",
73+
"<style='fg-red'>NO CONTENT</style>",
74+
),
75+
$verbose === true => $this->error("Failed to generate static page: {$event->exception->getMessage()}"),
76+
default => $this->keyValue("<style='fg-gray'>{$event->path}</style>", "<style='fg-red'>FAILED</style>"),
77+
};
78+
});
79+
4580
foreach ($this->staticPageConfig->staticPages as $staticPage) {
4681
/** @var DataProvider $dataProvider */
4782
$dataProvider = $this->container->get($staticPage->dataProviderClass ?? GenericDataProvider::class);
@@ -72,9 +107,7 @@ public function __invoke(?string $filter = null): void
72107
);
73108

74109
if ($response->status !== Status::OK) {
75-
$this->writeln("- <error>{$uri}</error> > {$response->status->value}");
76-
77-
continue;
110+
throw new InvalidStatusCodeException($uri, $response->status);
78111
}
79112

80113
$body = $response->body;
@@ -84,9 +117,7 @@ public function __invoke(?string $filter = null): void
84117
: $body;
85118

86119
if (! is_string($content)) {
87-
$this->error("<u>{$uri}</u> No textual body");
88-
89-
continue;
120+
throw new NoTextualBodyException($uri);
90121
}
91122

92123
$directory = $file->dirname();
@@ -97,17 +128,32 @@ public function __invoke(?string $filter = null): void
97128

98129
file_put_contents($file->toString(), $content);
99130

100-
$this->writeln("- <em>{$uri}</em> > <u>{$file}</u>");
101-
} catch (Throwable $e) {
102-
$this->error("<u>{$uri}</u> {$e->getMessage()}");
131+
$this->eventBus->dispatch(new StaticPageGenerated($uri, $file->toString(), $content));
132+
} catch (Throwable $exception) {
133+
if (ob_get_contents()) {
134+
ob_clean();
135+
}
103136

104-
ob_get_clean();
137+
if ($exception instanceof ViewCompilationError && $exception->getPrevious() instanceof ManifestNotFoundException) {
138+
$this->error("A Vite build is needed for [{$uri}]. Run <code>vite build</code> first.");
139+
return ExitCode::ERROR;
140+
}
141+
142+
$this->eventBus->dispatch(new StaticPageGenerationFailed($uri, $exception));
105143

106144
continue;
107145
}
108146
}
109147
}
110148

111-
$this->success('Done');
149+
if ($failures) {
150+
$this->keyValue('Failures', "<style='fg-red'>{$failures}</style>");
151+
}
152+
153+
$this->keyValue('Static pages generated', "<style='fg-green'>{$generated}</style>");
154+
155+
return $failures > 0
156+
? ExitCode::ERROR
157+
: ExitCode::SUCCESS;
112158
}
113159
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Tempest\Router\Static;
4+
5+
final readonly class StaticPageGenerated
6+
{
7+
public function __construct(
8+
public string $uri,
9+
public string $path,
10+
public string $content,
11+
) {}
12+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Tempest\Router\Static;
4+
5+
use Throwable;
6+
7+
final readonly class StaticPageGenerationFailed
8+
{
9+
public function __construct(
10+
public string $path,
11+
public Throwable $exception,
12+
) {}
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Tempest\Router\Static;
4+
5+
final readonly class StaticPageRemoved
6+
{
7+
public function __construct(
8+
public string $path,
9+
) {}
10+
}

tests/Fixtures/Controllers/StaticPageController.php

Lines changed: 0 additions & 21 deletions
This file was deleted.

0 commit comments

Comments
 (0)