Skip to content

Commit 511e45c

Browse files
committed
styling fixes
1 parent d9819d1 commit 511e45c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+5233
-1786
lines changed

Dockerfile

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
1-
FROM spiralscout/roadrunner as roadrunner
1+
FROM spiralscout/roadrunner AS roadrunner
22
# OR
33
# FROM ghcr.io/roadrunner-server/roadrunner as roadrunner
44

5-
FROM php:8.5-cli
5+
FROM node:22-alpine AS node-build
6+
WORKDIR /app/examples
7+
COPY examples/package.json examples/package-lock.json* ./
8+
RUN npm ci
9+
COPY examples/resources ./resources
10+
COPY examples/app/views ./app/views
11+
COPY examples/vite.config.js ./
12+
RUN npm run build
13+
14+
FROM php:8.4-cli
615

716
WORKDIR /app
817

918
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
10-
RUN install-php-extensions @composer redis memcached pcov sockets mbstring
19+
RUN install-php-extensions @composer redis memcached pcov sockets mbstring grpc
1120

1221
COPY . /app
1322

23+
WORKDIR /app/examples
24+
1425
RUN composer install --no-interaction --prefer-dist --ignore-platform-reqs
1526

27+
COPY --from=node-build /app/examples/public/build ./public/build
1628
COPY --from=roadrunner /usr/bin/rr /usr/local/bin/rr
1729

1830
CMD ["rr", "serve"]

compose.yaml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,26 @@ services:
88
depends_on:
99
- php
1010
- mercure
11+
- centrifugo
1112

1213
php:
1314
build:
1415
context: .
1516
dockerfile: Dockerfile
16-
working_dir: /app
1717
environment:
1818
REDIS_HOST: redis
1919
REDIS_PORT: 6379
2020
MERCURE_HUB_URL: http://mercure/.well-known/mercure
2121
MERCURE_JWT_SECRET: ${MERCURE_JWT_SECRET:-airlock-mercure-secret-32chars-minimum}
2222
MERCURE_PUBLIC_URL: ${MERCURE_PUBLIC_URL:-http://localhost/.well-known/mercure}
23+
VITE_DEV: ${VITE_DEV:-false}
2324
volumes:
24-
- ./examples:/app
25+
- ./examples:/app/examples
26+
- ./src:/app/src
2527
depends_on:
2628
- redis
2729
- mercure
30+
- centrifugo
2831

2932
mercure:
3033
image: dunglas/mercure
@@ -37,6 +40,12 @@ services:
3740
MERCURE_ALLOW_ANONYMOUS: 1
3841
MERCURE_CORS_ALLOWED_ORIGINS: "*"
3942

43+
centrifugo:
44+
image: centrifugo/centrifugo:v5
45+
volumes:
46+
- ./examples/config.json:/centrifugo/config.json:ro
47+
command: centrifugo --config config.json
48+
4049
redis:
4150
image: redis:8.4.0
4251

examples/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@
99

1010
/.env
1111
/*.cache
12+
13+
/node_modules
14+
/public/build

examples/.rr.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ http:
1212
- .php
1313
- .htaccess
1414
pool:
15-
debug: true
16-
num_workers: 1
15+
debug: false
16+
num_workers: 4
1717
supervisor:
1818
max_worker_memory: 100
1919
server:

examples/Caddyfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
:80 {
22
reverse_proxy /.well-known/mercure* mercure:80
3+
reverse_proxy /connection/websocket centrifugo:8000
34
reverse_proxy php:8080
45
}

examples/app/config/centrifugo.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
use RoadRunner\Centrifugo\Request\RequestType;
4+
5+
return [
6+
/*'services' => [
7+
RequestType::Connect->value => ConnectService::class,
8+
RequestType::Subscribe->value => SubscribeService::class,
9+
RequestType::Refresh->value => RefreshService::class,
10+
RequestType::Publish->value => PublishService::class,
11+
RequestType::RPC->value => RPCService::class,
12+
],
13+
'interceptors' => [
14+
RequestType::Connect->value => [
15+
Interceptor\AuthInterceptor::class,
16+
],
17+
RequestType::Subscribe->value => [
18+
Interceptor\AuthInterceptor::class,
19+
],
20+
RequestType::RPC->value => [
21+
Interceptor\AuthInterceptor::class,
22+
],
23+
'*' => [
24+
Interceptor\TelemetryInterceptor::class,
25+
],
26+
],*/
27+
];
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
// phpcs:ignoreFile SlevomatCodingStandard.Variables.DisallowSuperGlobalVariable
4+
5+
declare(strict_types=1);
6+
7+
namespace App\Application\Bootloader;
8+
9+
use App\Application\Twig\ViteExtension;
10+
use Spiral\Boot\Bootloader\Bootloader;
11+
use Spiral\Boot\DirectoriesInterface;
12+
use Spiral\Twig\Bootloader\TwigBootloader;
13+
14+
final class ViteBootloader extends Bootloader
15+
{
16+
public function boot(TwigBootloader $twig, DirectoriesInterface $dirs): void
17+
{
18+
$publicPath = rtrim((string) $dirs->get('public'), '/');
19+
$isDev = filter_var($_ENV['VITE_DEV'] ?? 'false', FILTER_VALIDATE_BOOLEAN);
20+
21+
$twig->addExtension(new ViteExtension($publicPath, $isDev));
22+
}
23+
}

examples/app/src/Application/Kernel.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Spiral\Boot\Bootloader\CoreBootloader;
88
use Spiral\Bootloader as Framework;
99
use Spiral\Bootloader\Http\HttpBootloader;
10+
use Spiral\Broadcasting\Bootloader\BroadcastingBootloader;
1011
use Spiral\Cache\Bootloader\CacheBootloader;
1112
use Spiral\Debug\Bootloader\DumperBootloader;
1213
use Spiral\DotEnv\Bootloader\DotenvBootloader;
@@ -81,6 +82,9 @@ public function defineBootloaders(): array
8182
// Cache
8283
CacheBootloader::class,
8384

85+
// Broadcasting (Centrifugo is called directly via HTTP API)
86+
BroadcastingBootloader::class,
87+
8488
NyholmBootloader::class,
8589

8690
// Console commands
@@ -102,6 +106,7 @@ public function defineAppBootloaders(): array
102106
{
103107
return [
104108
Bootloader\RedisBootloader::class,
109+
Bootloader\ViteBootloader::class,
105110

106111
// Application domain
107112
Bootloader\AppBootloader::class,
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Application\Twig;
6+
7+
use Twig\Extension\AbstractExtension;
8+
use Twig\TwigFunction;
9+
10+
final class ViteExtension extends AbstractExtension
11+
{
12+
private ?array $manifest = null;
13+
14+
private ?int $manifestMtime = null;
15+
16+
public function __construct(
17+
private readonly string $publicPath,
18+
private readonly bool $isDev,
19+
) {
20+
}
21+
22+
public function getFunctions(): array
23+
{
24+
return [
25+
new TwigFunction('vite', [$this, 'vite'], ['is_safe' => ['html']]),
26+
];
27+
}
28+
29+
public function vite(string ...$entries): string
30+
{
31+
if ($this->isDev) {
32+
return $this->devTags($entries);
33+
}
34+
35+
return $this->prodTags($entries);
36+
}
37+
38+
private function devTags(array $entries): string
39+
{
40+
$html = '<script type="module" src="http://localhost:5173/@vite/client"></script>' . "\n";
41+
42+
foreach ($entries as $entry) {
43+
$html .= '<script type="module" src="http://localhost:5173/' . $entry . '"></script>' . "\n";
44+
}
45+
46+
return $html;
47+
}
48+
49+
private function prodTags(array $entries): string
50+
{
51+
$manifest = $this->loadManifest();
52+
$html = '';
53+
$emitted = [];
54+
55+
foreach ($entries as $entry) {
56+
if (!isset($manifest[$entry])) {
57+
continue;
58+
}
59+
60+
$html .= $this->emitChunk($manifest[$entry], $manifest, $emitted);
61+
}
62+
63+
return $html;
64+
}
65+
66+
private function emitChunk(array $chunk, array $manifest, array &$emitted): string
67+
{
68+
$html = '';
69+
70+
// Emit shared imports first (e.g. alerts.js)
71+
foreach ($chunk['imports'] ?? [] as $importKey) {
72+
if (isset($emitted[$importKey]) || !isset($manifest[$importKey])) {
73+
continue;
74+
}
75+
76+
$emitted[$importKey] = true;
77+
$html .= $this->emitChunk($manifest[$importKey], $manifest, $emitted);
78+
}
79+
80+
// Emit CSS files
81+
foreach ($chunk['css'] ?? [] as $cssFile) {
82+
if (isset($emitted[$cssFile])) {
83+
continue;
84+
}
85+
86+
$html .= '<link rel="stylesheet" href="/build/' . $cssFile . '">' . "\n";
87+
$emitted[$cssFile] = true;
88+
}
89+
90+
// Emit the JS file
91+
if (isset($chunk['file']) && !isset($emitted[$chunk['file']])) {
92+
$html .= '<script type="module" src="/build/' . $chunk['file'] . '"></script>' . "\n";
93+
$emitted[$chunk['file']] = true;
94+
}
95+
96+
return $html;
97+
}
98+
99+
private function loadManifest(): array
100+
{
101+
$path = $this->publicPath . '/build/.vite/manifest.json';
102+
103+
if (!file_exists($path)) {
104+
$this->manifestMtime = null;
105+
return $this->manifest = [];
106+
}
107+
108+
$mtime = filemtime($path);
109+
if ($this->manifest !== null && $this->manifestMtime === $mtime) {
110+
return $this->manifest;
111+
}
112+
113+
$this->manifestMtime = $mtime === false ? null : $mtime;
114+
$this->manifest = json_decode(file_get_contents($path), true) ?: [];
115+
116+
return $this->manifest;
117+
}
118+
}

examples/app/src/Endpoint/Web/GlobalLockController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace App\Endpoint\Web;
66

7-
use App\Service\GlobalLockService;
7+
use App\Examples\GlobalLock\GlobalLockService;
88
use Psr\Http\Message\ServerRequestInterface;
99
use Spiral\Prototype\Traits\PrototypeTrait;
1010
use Spiral\Router\Annotation\Route;

0 commit comments

Comments
 (0)