Repository: yiisoft/yii-runner-roadrunner
Pull request #95: Support PHP 8.4
Author: login: batyrmastyr
Created: 2025-04-08T20:16:26Z | Merged: 2025-04-16T07:32:51Z

| Q             | A
| ------------- | ---
| Is bugfix?    | ❌
| New feature?  | ❌
| Breaks BC?    | ✔️
| Fixed issues  | <!-- comma-separated list of tickets # fixed by the PR, if any -->



Diff:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index cf4851a..46e973e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -28,7 +28,7 @@ jobs:
     strategy:
       matrix:
         os: ['ubuntu-latest']
-        php: ['8.1', '8.2']
+        php: ['8.1', '8.2', '8.3', '8.4']
 
     steps:
       - name: Checkout.
diff --git a/.github/workflows/composer-require-checker.yml b/.github/workflows/composer-require-checker.yml
index 0474238..ada0cdd 100644
--- a/.github/workflows/composer-require-checker.yml
+++ b/.github/workflows/composer-require-checker.yml
@@ -30,4 +30,4 @@ jobs:
       os: >-
         ['ubuntu-latest']
       php: >-
-        ['8.1', '8.2']
+        ['8.1', '8.2', '8.3', '8.4']
diff --git a/.github/workflows/mutation.yml b/.github/workflows/mutation.yml
index 7686ded..c6ab8fa 100644
--- a/.github/workflows/mutation.yml
+++ b/.github/workflows/mutation.yml
@@ -28,7 +28,7 @@ jobs:
     strategy:
       matrix:
         os: ['ubuntu-latest']
-        php: ['8.3']
+        php: ['8.4']
 
     steps:
       - name: Checkout.
diff --git a/.github/workflows/rector.yml b/.github/workflows/rector.yml
index c9030d7..22df53e 100644
--- a/.github/workflows/rector.yml
+++ b/.github/workflows/rector.yml
@@ -1,5 +1,5 @@
 on:
-  pull_request:
+  pull_request_target:
     paths-ignore:
       - 'docs/**'
       - 'README.md'
@@ -14,8 +14,11 @@ name: rector
 jobs:
   rector:
     uses: yiisoft/actions/.github/workflows/rector.yml@master
+    secrets:
+      token: ${{ secrets.YIISOFT_GITHUB_TOKEN }}
     with:
+      repository: ${{ github.event.pull_request.head.repo.full_name }}
       os: >-
         ['ubuntu-latest']
       php: >-
-        ['8.1']
+        ['8.1']
\ No newline at end of file
diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml
index 873eeb5..9e12684 100644
--- a/.github/workflows/static.yml
+++ b/.github/workflows/static.yml
@@ -30,4 +30,4 @@ jobs:
       os: >-
         ['ubuntu-latest']
       php: >-
-        ['8.1', '8.2', '8.3']
+        ['8.1', '8.2', '8.3', '8.4']
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 106b469..392b517 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,10 @@
 # Yii RoadRunner Runner Change Log
 
-## 3.0.2 under development
+## 3.1.0 under development
 
-- no changes in this release.
+- Chg #95: Raise required version of `yiisoft/error-handler` to `^4.0` (@batyrmastyr)
+- Chg #95: Change PHP constraint in composer.json to 8.1 - 8.4 (@batyrmastyr)
+- Bug #95: Explicitly mark nullable parameters (@batyrmastyr)
 
 ## 3.0.1 April 23, 2024
 
diff --git a/composer.json b/composer.json
index 2435825..be4d68f 100644
--- a/composer.json
+++ b/composer.json
@@ -27,19 +27,19 @@
         }
     ],
     "require": {
-        "php": "^8.1",
+        "php": "8.1 - 8.4",
         "psr/container": "^2.0",
         "psr/http-factory": "^1.0",
-        "psr/http-message": "^1.0|^2.0",
-        "spiral/roadrunner": "^2023.1.0|^2024.1.0",
+        "psr/http-message": "^1.0 || ^2.0",
+        "spiral/roadrunner": "^2023.1.0 || ^2024.1.0",
         "spiral/roadrunner-http": "^v3.0.0",
         "spiral/roadrunner-worker": "^3.0.0",
         "spiral/roadrunner-cli": "^2.5.0",
         "spiral/roadrunner-grpc": "^3.0.0",
         "yiisoft/config": "^1.1",
-        "yiisoft/definitions": "^1.0|^2.0|^3.0",
+        "yiisoft/definitions": "^1.0 || ^2.0 || ^3.0",
         "yiisoft/di": "^1.0",
-        "yiisoft/error-handler": "^3.0",
+        "yiisoft/error-handler": "^4.0",
         "yiisoft/http": "^1.2",
         "yiisoft/log": "^2.0",
         "yiisoft/log-target-file": "^3.0",
@@ -51,19 +51,17 @@
         "maglnet/composer-require-checker": "^4.2",
         "phpunit/phpunit": "^10.3",
         "rector/rector": "^2.0.3",
-        "roave/infection-static-analysis-plugin": "^1.16",
+        "roave/infection-static-analysis-plugin": "^1.35",
         "spatie/phpunit-watcher": "^1.23",
         "temporal/sdk": "^2.11",
-        "vimeo/psalm": "^5.22",
+        "vimeo/psalm": "^5.22 || ^6.1",
         "yiisoft/middleware-dispatcher": "^5.0",
         "yiisoft/test-support": "^3.0",
         "grpc/grpc": "^1.50.0"
     },
     "suggest": {
         "grpc/grpc": "Needed for gRPC support",
-        "ext-grpc": "Needed for gRPC support"
-    },
-    "suggest": {
+        "ext-grpc": "Needed for gRPC support",
         "temporal/sdk": "Add Temporal support"
     },
     "autoload": {
@@ -99,7 +97,7 @@
         }
     },
     "scripts": {
-        "test": "phpunit --testdox --no-interaction",
+        "test": "phpunit --testdox",
         "test-watch": "phpunit-watcher watch"
     }
 }
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index a986aca..332e634 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -6,6 +6,7 @@
     colors="true"
     failOnRisky="true"
     failOnWarning="true"
+    failOnDeprecation="true"
     stopOnFailure="false"
     executionOrder="random"
     resolveDependencies="true"
diff --git a/psalm.xml b/psalm.xml
index b48c894..2b2e0b2 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -3,6 +3,7 @@
     errorLevel="1"
     findUnusedBaselineEntry="true"
     findUnusedCode="false"
+    ensureOverrideAttribute="false"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns="https://getpsalm.org/schema/config"
     xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
diff --git a/src/RoadRunnerHttpApplicationRunner.php b/src/RoadRunnerHttpApplicationRunner.php
index cc7b15a..e2f53c4 100644
--- a/src/RoadRunnerHttpApplicationRunner.php
+++ b/src/RoadRunnerHttpApplicationRunner.php
@@ -194,7 +194,7 @@ private function createTemporaryErrorHandler(): ErrorHandler
     /**
      * @throws ErrorException
      */
-    private function registerErrorHandler(ErrorHandler $registered, ErrorHandler $unregistered = null): void
+    private function registerErrorHandler(ErrorHandler $registered, ?ErrorHandler $unregistered = null): void
     {
         $unregistered?->unregister();
 
diff --git a/src/RoadRunnerHttpWorker.php b/src/RoadRunnerHttpWorker.php
index ab1656c..5f8bd1a 100644
--- a/src/RoadRunnerHttpWorker.php
+++ b/src/RoadRunnerHttpWorker.php
@@ -32,7 +32,7 @@ final class RoadRunnerHttpWorker
     private ErrorCatcher $errorCatcher;
     private ErrorHandler $errorHandler;
 
-    public function __construct(ContainerInterface $container, PSR7WorkerInterface $worker = null)
+    public function __construct(ContainerInterface $container, ?PSR7WorkerInterface $worker = null)
     {
         /** @psalm-var ResponseFactoryInterface $this->responseFactory */
         $this->responseFactory = $container->get(ResponseFactoryInterface::class);
@@ -54,7 +54,7 @@ public function respond(ResponseInterface $response): void
         $this->worker->respond($response);
     }
 
-    public function respondWithError(Throwable $throwable, ServerRequestInterface $request = null): ResponseInterface
+    public function respondWithError(Throwable $throwable, ?ServerRequestInterface $request = null): ResponseInterface
     {
         if ($request === null) {
             $errorData = $this->errorHandler->handle($throwable);
diff --git a/tests/Support/PlainTextRendererMock.php b/tests/Support/PlainTextRendererMock.php
index 875e474..33a1293 100644
--- a/tests/Support/PlainTextRendererMock.php
+++ b/tests/Support/PlainTextRendererMock.php
@@ -13,12 +13,12 @@
 
 final class PlainTextRendererMock implements ThrowableRendererInterface
 {
-    public function render(Throwable $t, ServerRequestInterface $request = null): ErrorData
+    public function render(Throwable $t, ?ServerRequestInterface $request = null): ErrorData
     {
         return $this->renderVerbose($t, $request);
     }
 
-    public function renderVerbose(Throwable $t, ServerRequestInterface $request = null): ErrorData
+    public function renderVerbose(Throwable $t, ?ServerRequestInterface $request = null): ErrorData
     {
         return new ErrorData(json_encode([
             'error-message' => $t->getMessage(),
diff --git a/tests/Support/Psr7WorkerMock.php b/tests/Support/Psr7WorkerMock.php
index 49c5585..125d9bf 100644
--- a/tests/Support/Psr7WorkerMock.php
+++ b/tests/Support/Psr7WorkerMock.php
@@ -68,12 +68,12 @@ public function stop(): void
             {
             }
 
-            public function hasPayload(string $class = null): bool
+            public function hasPayload(?string $class = null): bool
             {
                 return false;
             }
 
-            public function getPayload(string $class = null): ?Payload
+            public function getPayload(?string $class = null): ?Payload
             {
                 return null;
             }
diff --git a/tests/Support/config/di-web.php b/tests/Support/config/di-web.php
index 4eac49c..06ec660 100644
--- a/tests/Support/config/di-web.php
+++ b/tests/Support/config/di-web.php
@@ -23,9 +23,10 @@
 use Yiisoft\Definitions\DynamicReference;
 use Yiisoft\Definitions\Reference;
 use Yiisoft\ErrorHandler\ErrorHandler;
-use Yiisoft\ErrorHandler\Middleware\ErrorCatcher;
+use Yiisoft\ErrorHandler\Factory\ThrowableResponseFactory;
 use Yiisoft\ErrorHandler\Renderer\PlainTextRenderer;
 use Yiisoft\ErrorHandler\ThrowableRendererInterface;
+use Yiisoft\ErrorHandler\ThrowableResponseFactoryInterface;
 use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher;
 use Yiisoft\Test\Support\EventDispatcher\SimpleEventDispatcher;
 use Yiisoft\Test\Support\Log\SimpleLogger;
@@ -43,7 +44,8 @@
     UriFactoryInterface::class => UriFactory::class,
     UploadedFileFactoryInterface::class => UploadedFileFactory::class,
 
-    ErrorCatcher::class => [
+    ThrowableResponseFactoryInterface::class => ThrowableResponseFactory::class,
+    ThrowableResponseFactory::class => [
         'forceContentType()' => ['text/plain'],
         'withRenderer()' => ['text/plain', PlainTextRendererMock::class],
     ],
diff --git a/tests/TestCase.php b/tests/TestCase.php
index f28109c..a41625d 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -34,8 +34,9 @@
 use Yiisoft\Di\Container;
 use Yiisoft\Di\ContainerConfig;
 use Yiisoft\ErrorHandler\ErrorHandler;
-use Yiisoft\ErrorHandler\Middleware\ErrorCatcher;
+use Yiisoft\ErrorHandler\Factory\ThrowableResponseFactory;
 use Yiisoft\ErrorHandler\ThrowableRendererInterface;
+use Yiisoft\ErrorHandler\ThrowableResponseFactoryInterface;
 use Yiisoft\Http\Method;
 use Yiisoft\Http\Status;
 use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher;
@@ -72,7 +73,8 @@ protected function createContainer(bool $throwException = false): Container
             WorkerFactoryInterface::class => fn () => WorkerFactory::create(),
             HostConnectionInterface::class => fn () => new TemporalHostConnection(),
 
-            ErrorCatcher::class => [
+            ThrowableResponseFactoryInterface::class => ThrowableResponseFactory::class,
+            ThrowableResponseFactory::class => [
                 'forceContentType()' => ['text/plain'],
                 'withRenderer()' => ['text/plain', PlainTextRendererMock::class],
             ],


Reviews:
user: login: samdark
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-08T22:19:48Z
user: login: vjik
body: Tests are failed
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-09T07:38:48Z
user: login: batyrmastyr
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T07:40:23Z
user: login: vjik
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-09T07:46:52Z
user: login: batyrmastyr
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T07:49:33Z
user: login: batyrmastyr
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T08:06:23Z
user: login: batyrmastyr
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T08:14:26Z
user: login: vjik
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-09T08:16:06Z
user: login: batyrmastyr
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T10:42:35Z
user: login: batyrmastyr
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T10:43:03Z
user: login: batyrmastyr
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T11:13:09Z
user: login: batyrmastyr
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T12:51:46Z
user: login: vjik
body: Overall is OK. Just a few remarks.
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-16T05:01:43Z
user: login: vjik
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-16T07:32:08Z

Review comments:
diff_hunk: @@ -27,19 +27,19 @@
         }
     ],
     "require": {
-        "php": "^8.1",
+        "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
path: composer.json
user: login: vjik
body: ```suggestion
        "php": "8.1 - 8.4",
```
created_at: 2025-04-09T07:29:56Z
author_association: MEMBER
diff_hunk: @@ -27,19 +27,19 @@
         }
     ],
     "require": {
-        "php": "^8.1",
+        "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
         "psr/container": "^2.0",
         "psr/http-factory": "^1.0",
-        "psr/http-message": "^1.0|^2.0",
-        "spiral/roadrunner": "^2023.1.0|^2024.1.0",
+        "psr/http-message": "^1.0 || ^2.0",
+        "spiral/roadrunner": "^2023.1.0 || ^2024.1.0",
         "spiral/roadrunner-http": "^v3.0.0",
         "spiral/roadrunner-worker": "^3.0.0",
         "spiral/roadrunner-cli": "^2.5.0",
         "spiral/roadrunner-grpc": "^3.0.0",
         "yiisoft/config": "^1.1",
-        "yiisoft/definitions": "^1.0|^2.0|^3.0",
+        "yiisoft/definitions": "^1.0 || ^2.0 || ^3.0",
         "yiisoft/di": "^1.0",
-        "yiisoft/error-handler": "^3.0",
+        "yiisoft/error-handler": "^3.0 || ^4.0",
path: composer.json
user: login: vjik
body: Add this change to changelog
created_at: 2025-04-09T07:37:21Z
author_association: MEMBER
diff_hunk: @@ -99,7 +97,7 @@
         }
     },
     "scripts": {
-        "test": "phpunit --testdox --no-interaction",
+        "test": "phpunit --testdox --no-progress",
path: composer.json
user: login: vjik
body: Why `--no-progress` ?
created_at: 2025-04-09T07:37:53Z
author_association: MEMBER
diff_hunk: @@ -5,28 +5,20 @@
 use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
 use Rector\Config\RectorConfig;
 use Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector;
-use Rector\Set\ValueObject\LevelSetList;
+use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;
+use Rector\Php81\Rector\Property\ReadOnlyPropertyRector;
 
-return static function (RectorConfig $rectorConfig): void {
-    $rectorConfig->paths([
+return RectorConfig::configure()
+    ->withPaths([
         __DIR__ . '/src',
         __DIR__ . '/tests',
-    ]);
-
-    $rectorConfig->skip([
-        __DIR__ . '/tests/Support/Grpc/GPBMetadata',
-        __DIR__ . '/tests/Support/Grpc/Service',
-    ]);
-
-    // register a single rule
-    $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
-
-    // define sets of rules
-    $rectorConfig->sets([
-        LevelSetList::UP_TO_PHP_80,
-    ]);
-
-    $rectorConfig->skip([
+    ])
+    ->withPhpSets(php81: true)
path: rector.php
user: login: vjik
body: I suggest to update rector and apply his suggestions in separate PR.
created_at: 2025-04-09T07:38:32Z
author_association: MEMBER
diff_hunk: @@ -99,7 +97,7 @@
         }
     },
     "scripts": {
-        "test": "phpunit --testdox --no-interaction",
+        "test": "phpunit --testdox --no-progress",
path: composer.json
user: login: batyrmastyr
body: Because `--no-interaction` was removed in phpunit 10
created_at: 2025-04-09T07:40:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -99,7 +97,7 @@
         }
     },
     "scripts": {
-        "test": "phpunit --testdox --no-interaction",
+        "test": "phpunit --testdox --no-progress",
path: composer.json
user: login: vjik
body: But why need `--no-progress`. We use this command in local environment manually, right? So progress is OK.
created_at: 2025-04-09T07:46:52Z
author_association: MEMBER
diff_hunk: @@ -99,7 +97,7 @@
         }
     },
     "scripts": {
-        "test": "phpunit --testdox --no-interaction",
+        "test": "phpunit --testdox --no-progress",
path: composer.json
user: login: batyrmastyr
body: I'm fine to remove this option at all - at first I thought it is used in CI, but looks like I was wrong.
created_at: 2025-04-09T07:49:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -5,28 +5,20 @@
 use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
 use Rector\Config\RectorConfig;
 use Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector;
-use Rector\Set\ValueObject\LevelSetList;
+use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;
+use Rector\Php81\Rector\Property\ReadOnlyPropertyRector;
 
-return static function (RectorConfig $rectorConfig): void {
-    $rectorConfig->paths([
+return RectorConfig::configure()
+    ->withPaths([
         __DIR__ . '/src',
         __DIR__ . '/tests',
-    ]);
-
-    $rectorConfig->skip([
-        __DIR__ . '/tests/Support/Grpc/GPBMetadata',
-        __DIR__ . '/tests/Support/Grpc/Service',
-    ]);
-
-    // register a single rule
-    $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
-
-    // define sets of rules
-    $rectorConfig->sets([
-        LevelSetList::UP_TO_PHP_80,
-    ]);
-
-    $rectorConfig->skip([
+    ])
+    ->withPhpSets(php81: true)
path: rector.php
user: login: batyrmastyr
body: Ok
created_at: 2025-04-09T08:06:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -27,19 +27,19 @@
         }
     ],
     "require": {
-        "php": "^8.1",
+        "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
         "psr/container": "^2.0",
         "psr/http-factory": "^1.0",
-        "psr/http-message": "^1.0|^2.0",
-        "spiral/roadrunner": "^2023.1.0|^2024.1.0",
+        "psr/http-message": "^1.0 || ^2.0",
+        "spiral/roadrunner": "^2023.1.0 || ^2024.1.0",
         "spiral/roadrunner-http": "^v3.0.0",
         "spiral/roadrunner-worker": "^3.0.0",
         "spiral/roadrunner-cli": "^2.5.0",
         "spiral/roadrunner-grpc": "^3.0.0",
         "yiisoft/config": "^1.1",
-        "yiisoft/definitions": "^1.0|^2.0|^3.0",
+        "yiisoft/definitions": "^1.0 || ^2.0 || ^3.0",
         "yiisoft/di": "^1.0",
-        "yiisoft/error-handler": "^3.0",
+        "yiisoft/error-handler": "^3.0 || ^4.0",
path: composer.json
user: login: batyrmastyr
body: There is a question regarding `yiisoft /error-handler` - should I target `3.0.2` or `4.0`? 
In 4.0 overriding error format requires to redefine `ThrowableResponseFactory` instead of `ErrorCatcher`
 I'm not sure is it BC break or not.
<img width="1008" alt="Снимок экрана 2025-04-09 в 12 04 29" src="https://github.com/user-attachments/assets/98a00b0e-d765-4999-890d-6bb32cd6fae1" />

Same change in `yii-runner-http` was not considered as BC break though: https://github.com/yiisoft/yii-runner-http/pull/87
created_at: 2025-04-09T08:14:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -27,19 +27,19 @@
         }
     ],
     "require": {
-        "php": "^8.1",
+        "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
         "psr/container": "^2.0",
         "psr/http-factory": "^1.0",
-        "psr/http-message": "^1.0|^2.0",
-        "spiral/roadrunner": "^2023.1.0|^2024.1.0",
+        "psr/http-message": "^1.0 || ^2.0",
+        "spiral/roadrunner": "^2023.1.0 || ^2024.1.0",
         "spiral/roadrunner-http": "^v3.0.0",
         "spiral/roadrunner-worker": "^3.0.0",
         "spiral/roadrunner-cli": "^2.5.0",
         "spiral/roadrunner-grpc": "^3.0.0",
         "yiisoft/config": "^1.1",
-        "yiisoft/definitions": "^1.0|^2.0|^3.0",
+        "yiisoft/definitions": "^1.0 || ^2.0 || ^3.0",
         "yiisoft/di": "^1.0",
-        "yiisoft/error-handler": "^3.0",
+        "yiisoft/error-handler": "^3.0 || ^4.0",
path: composer.json
user: login: vjik
body: Bump to 4.0 for me is OK.
@samdark wdyt?
created_at: 2025-04-09T08:16:05Z
author_association: MEMBER
diff_hunk: @@ -5,28 +5,20 @@
 use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
 use Rector\Config\RectorConfig;
 use Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector;
-use Rector\Set\ValueObject\LevelSetList;
+use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;
+use Rector\Php81\Rector\Property\ReadOnlyPropertyRector;
 
-return static function (RectorConfig $rectorConfig): void {
-    $rectorConfig->paths([
+return RectorConfig::configure()
+    ->withPaths([
         __DIR__ . '/src',
         __DIR__ . '/tests',
-    ]);
-
-    $rectorConfig->skip([
-        __DIR__ . '/tests/Support/Grpc/GPBMetadata',
-        __DIR__ . '/tests/Support/Grpc/Service',
-    ]);
-
-    // register a single rule
-    $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
-
-    // define sets of rules
-    $rectorConfig->sets([
-        LevelSetList::UP_TO_PHP_80,
-    ]);
-
-    $rectorConfig->skip([
+    ])
+    ->withPhpSets(php81: true)
path: rector.php
user: login: batyrmastyr
body: Reverted rector.php, but updating workflow was required to pass tests
created_at: 2025-04-09T10:42:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -27,19 +27,19 @@
         }
     ],
     "require": {
-        "php": "^8.1",
+        "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
path: composer.json
user: login: batyrmastyr
body: Updated. Tests fixed now.
created_at: 2025-04-09T10:43:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -27,19 +27,19 @@
         }
     ],
     "require": {
-        "php": "^8.1",
+        "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
         "psr/container": "^2.0",
         "psr/http-factory": "^1.0",
-        "psr/http-message": "^1.0|^2.0",
-        "spiral/roadrunner": "^2023.1.0|^2024.1.0",
+        "psr/http-message": "^1.0 || ^2.0",
+        "spiral/roadrunner": "^2023.1.0 || ^2024.1.0",
         "spiral/roadrunner-http": "^v3.0.0",
         "spiral/roadrunner-worker": "^3.0.0",
         "spiral/roadrunner-cli": "^2.5.0",
         "spiral/roadrunner-grpc": "^3.0.0",
         "yiisoft/config": "^1.1",
-        "yiisoft/definitions": "^1.0|^2.0|^3.0",
+        "yiisoft/definitions": "^1.0 || ^2.0 || ^3.0",
         "yiisoft/di": "^1.0",
-        "yiisoft/error-handler": "^3.0",
+        "yiisoft/error-handler": "^3.0 || ^4.0",
path: composer.json
user: login: batyrmastyr
body: Changed to "yiisoft/error-handler": "^4.0" so that tests could make sense.
created_at: 2025-04-09T11:13:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -5,28 +5,20 @@
 use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
 use Rector\Config\RectorConfig;
 use Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector;
-use Rector\Set\ValueObject\LevelSetList;
+use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;
+use Rector\Php81\Rector\Property\ReadOnlyPropertyRector;
 
-return static function (RectorConfig $rectorConfig): void {
-    $rectorConfig->paths([
+return RectorConfig::configure()
+    ->withPaths([
         __DIR__ . '/src',
         __DIR__ . '/tests',
-    ]);
-
-    $rectorConfig->skip([
-        __DIR__ . '/tests/Support/Grpc/GPBMetadata',
-        __DIR__ . '/tests/Support/Grpc/Service',
-    ]);
-
-    // register a single rule
-    $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
-
-    // define sets of rules
-    $rectorConfig->sets([
-        LevelSetList::UP_TO_PHP_80,
-    ]);
-
-    $rectorConfig->skip([
+    ])
+    ->withPhpSets(php81: true)
path: rector.php
user: login: batyrmastyr
body: @vjik all done. 
created_at: 2025-04-11T12:51:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,8 +1,10 @@
 # Yii RoadRunner Runner Change Log
 
-## 3.0.2 under development
+## 4.0.0 under development
 
-- no changes in this release.
+- Chg #95: Raise required version of `yiisoft/error-handler` to `^4.0` (@batyrmastyr)
+- Chg #95: Change PHP constraint in composer.json to 8.1 - 8.4 (@batyrmastyr)
+- Chg #95: Explicitly mark nullable parameters (@batyrmastyr)
path: CHANGELOG.md
user: login: vjik
body: ```suggestion
- Bug #95: Explicitly mark nullable parameters (@batyrmastyr)
```
created_at: 2025-04-16T04:58:16Z
author_association: MEMBER
diff_hunk: @@ -1,8 +1,10 @@
 # Yii RoadRunner Runner Change Log
 
-## 3.0.2 under development
+## 4.0.0 under development
path: CHANGELOG.md
user: login: vjik
body: ```suggestion
## 3.1.0 under development
```
created_at: 2025-04-16T04:58:23Z
author_association: MEMBER
diff_hunk: @@ -7,6 +7,10 @@ application when you upgrade the package from one version to another.
 > to upgrade from version A to version C and there is version B between A and C, you need
 > to following the instructions for both A and B.
 
+## Upgrade from 3.x
+
+- If you defined custom `yiisoft/error-handler`'s `ErrorCatcher` DI configuration replace it with `ThrowableResponseFactory`.
+
path: UPGRADE.md
user: login: vjik
body: ```suggestion
```

This is relative to Yii Error Handler and it don't break BC for this package.
created_at: 2025-04-16T04:59:48Z
author_association: MEMBER

PR comments:
user: login: samdark
created_at: 2025-04-12T21:24:23Z
body: @vjik tests pass now.
author_association: MEMBER
user: login: vjik
created_at: 2025-04-16T07:33:05Z
body: @batyrmastyr thank you!
author_association: MEMBER