Browse Source

Adds support for Hypervel (#10058)

* init hypervel

* Hypervel Benchmark

* Dockerfile: optimize composer installation and artisan commands

* Delete useless files
silnex 3 weeks ago
parent
commit
6b5a3025f5
44 changed files with 1941 additions and 0 deletions
  1. 27 0
      frameworks/PHP/hypervel/.env
  2. 42 0
      frameworks/PHP/hypervel/README.md
  3. 26 0
      frameworks/PHP/hypervel/app/Console/Kernel.php
  4. 38 0
      frameworks/PHP/hypervel/app/Exceptions/Handler.php
  5. 9 0
      frameworks/PHP/hypervel/app/Http/Controllers/AbstractController.php
  6. 87 0
      frameworks/PHP/hypervel/app/Http/Controllers/IndexController.php
  7. 73 0
      frameworks/PHP/hypervel/app/Http/Kernel.php
  8. 14 0
      frameworks/PHP/hypervel/app/Models/Fortune.php
  9. 12 0
      frameworks/PHP/hypervel/app/Models/Model.php
  10. 20 0
      frameworks/PHP/hypervel/app/Models/User.php
  11. 14 0
      frameworks/PHP/hypervel/app/Models/World.php
  12. 18 0
      frameworks/PHP/hypervel/app/Providers/AppServiceProvider.php
  13. 34 0
      frameworks/PHP/hypervel/app/Providers/RouteServiceProvider.php
  14. 26 0
      frameworks/PHP/hypervel/artisan
  15. 28 0
      frameworks/PHP/hypervel/benchmark_config.json
  16. 40 0
      frameworks/PHP/hypervel/bootstrap/app.php
  17. 100 0
      frameworks/PHP/hypervel/composer.json
  18. 19 0
      frameworks/PHP/hypervel/config.toml
  19. 171 0
      frameworks/PHP/hypervel/config/app.php
  20. 103 0
      frameworks/PHP/hypervel/config/cache.php
  21. 137 0
      frameworks/PHP/hypervel/config/database.php
  22. 140 0
      frameworks/PHP/hypervel/config/logging.php
  23. 137 0
      frameworks/PHP/hypervel/config/queue.php
  24. 45 0
      frameworks/PHP/hypervel/config/server.php
  25. 20 0
      frameworks/PHP/hypervel/config/view.php
  26. 17 0
      frameworks/PHP/hypervel/config/watcher.php
  27. 16 0
      frameworks/PHP/hypervel/database/factories/UserFactory.php
  28. 32 0
      frameworks/PHP/hypervel/database/migrations/2023_08_03_000000_create_users_table.php
  29. 21 0
      frameworks/PHP/hypervel/database/seeders/DatabaseSeeder.php
  30. 22 0
      frameworks/PHP/hypervel/hypervel.dockerfile
  31. 197 0
      frameworks/PHP/hypervel/lang/en/validation.php
  32. 30 0
      frameworks/PHP/hypervel/phpunit.xml.dist
  33. 2 0
      frameworks/PHP/hypervel/public/robots.txt
  34. 13 0
      frameworks/PHP/hypervel/resources/views/fortunes.blade.php
  35. 8 0
      frameworks/PHP/hypervel/routes/api.php
  36. 20 0
      frameworks/PHP/hypervel/routes/channels.php
  37. 23 0
      frameworks/PHP/hypervel/routes/console.php
  38. 13 0
      frameworks/PHP/hypervel/routes/web.php
  39. 20 0
      frameworks/PHP/hypervel/tests/Feature/ExampleTest.php
  40. 39 0
      frameworks/PHP/hypervel/tests/Feature/RefreshDatabaseTest.php
  41. 13 0
      frameworks/PHP/hypervel/tests/TestCase.php
  42. 22 0
      frameworks/PHP/hypervel/tests/Unit/ExampleTest.php
  43. 38 0
      frameworks/PHP/hypervel/tests/bootstrap.php
  44. 15 0
      frameworks/PHP/hypervel/tests/helpers.php

+ 27 - 0
frameworks/PHP/hypervel/.env

@@ -0,0 +1,27 @@
+APP_NAME=Hypervel
+APP_ENV=production
+APP_DEBUG=false
+APP_KEY=base64:bZw/z/v+8K+n5GzPy/3hZkTlV/t2IOET7AGNmqO8W4E=
+
+LOG_CHANNEL=stdout
+
+DB_CONNECTION=mysql
+DB_HOST=tfb-database
+DB_PORT=3306
+DB_DATABASE=hello_world
+DB_USERNAME=benchmarkdbuser
+DB_PASSWORD=benchmarkdbpass
+
+SESSION_DRIVER=array
+SESSION_LIFETIME=120
+SESSION_ENCRYPT=false
+SESSION_PATH=/
+SESSION_DOMAIN=null
+
+BROADCAST_DRIVER=null
+
+CACHE_DRIVER=file
+
+QUEUE_DRIVER=sync
+
+JWT_SECRET=

+ 42 - 0
frameworks/PHP/hypervel/README.md

@@ -0,0 +1,42 @@
+<p align="center"><a href="https://hypervel.org" target="_blank"><img src="https://hypervel.org/logo.png" width="400"></a></p>
+
+<p align="center">
+<a href="https://github.com/hypervel/hypervel/actions"><img src="https://github.com/hypervel/hypervel/workflows/tests/badge.svg" alt="Build Status"></a>
+<a href="https://packagist.org/packages/hypervel/framework"><img src="https://img.shields.io/packagist/dt/hypervel/framework" alt="Total Downloads"></a>
+<a href="https://packagist.org/packages/hypervel/hypervel"><img src="https://img.shields.io/packagist/v/hypervel/hypervel" alt="Latest Stable Version"></a>
+<a href="https://packagist.org/packages/hypervel/hypervel"><img src="https://img.shields.io/packagist/l/hypervel/hypervel" alt="License"></a>
+</p>
+
+## Introduction
+
+**Hypervel** is a Laravel-style PHP framework with native coroutine support for ultra-high performance.
+
+Hypervel ports many core components from Laravel while maintaining familiar usage patterns, making it instantly accessible to Laravel developers. The framework combines the elegant and expressive development experience of Laravel with the powerful performance benefits of coroutine-based programming. If you're a Laravel developer, you'll feel right at home with this framework, requiring minimal learning curve.
+
+This is an ideal choice for building microservices, API gateways, and high-concurrency applications where traditional PHP frameworks often encounter performance constraints.
+
+## Why Hypervel?
+
+While Laravel Octane impressively enhances your Laravel application's performance, it's crucial to understand the nature of modern web applications. In most cases, the majority of latency stems from I/O operations, such as file operations, database queries, and API requests.
+
+However, Laravel doesn't support coroutines - the entire framework is designed for a blocking I/O environment. Applications heavily dependent on I/O operations will still face performance bottlenecks. Consider this scenario:
+
+Imagine building an AI-powered chatbot where each conversation API takes 3-5 seconds to respond. With 10 workers in Laravel Octane receiving 10 concurrent requests, all workers would be blocked until these requests complete.
+
+> You can see [benchmark comparison](https://hypervel.org/docs/introduction.html#benchmark) between Laravel Octane and Hypervel
+
+Even with Laravel Octane's improvements, your application's concurrent request handling capacity remains constrained by I/O operation duration. Hypervel addresses this limitation through coroutines, enabling efficient handling of concurrent I/O operations without blocking workers. This approach significantly enhances performance and concurrency for I/O-intensive applications.
+
+> See [this issue](https://github.com/laravel/octane/issues/765) for more discussions.
+
+## Documentation
+
+[https://hypervel.org/docs](https://hypervel.org/docs)
+
+Hypervel provides comprehensive and user-friendly documentation that allows you to quickly get started. From this documentation, you can learn how to use various components in Hypervel and understand the differences between this framework and Laravel.
+
+> Most of the content in this documentation is referenced from the official Laravel documentation. We appreciate the Laravel community's contributions.
+
+## License
+
+The Hypervel framework is open-sourced software licensed under the [MIT](https://opensource.org/licenses/MIT) license.

+ 26 - 0
frameworks/PHP/hypervel/app/Console/Kernel.php

@@ -0,0 +1,26 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Console;
+
+use Hypervel\Console\Scheduling\Schedule;
+use Hypervel\Foundation\Console\Kernel as ConsoleKernel;
+
+class Kernel extends ConsoleKernel
+{
+    /**
+     * Define the application's command schedule.
+     */
+    public function schedule(Schedule $schedule): void
+    {
+        // $schedule->command('demo:hi')->everyFiveSeconds();
+    }
+
+    public function commands(): void
+    {
+        $this->load(__DIR__ . '/Commands');
+
+        require base_path('routes/console.php');
+    }
+}

+ 38 - 0
frameworks/PHP/hypervel/app/Exceptions/Handler.php

@@ -0,0 +1,38 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Exceptions;
+
+use Hypervel\Foundation\Exceptions\Handler as ExceptionHandler;
+use Hypervel\Http\Request;
+use Throwable;
+
+class Handler extends ExceptionHandler
+{
+    /**
+     * The list of the inputs that are never flashed to the session on validation exceptions.
+     *
+     * @var array<int, string>
+     */
+    protected array $dontFlash = [
+        'current_password',
+        'password',
+        'password_confirmation',
+    ];
+
+    /**
+     * Register the exception handling callbacks for the application.
+     */
+    public function register(): void
+    {
+        // return json when path start with `api`
+        $this->shouldRenderJsonWhen(function (Request $request, Throwable $e) {
+            return str_starts_with($path = $request->path(), 'api')
+                && (strlen($path) === 3 || $path[3] === '/');
+        });
+
+        $this->reportable(function (Throwable $e) {
+        });
+    }
+}

+ 9 - 0
frameworks/PHP/hypervel/app/Http/Controllers/AbstractController.php

@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Http\Controllers;
+
+abstract class AbstractController
+{
+}

+ 87 - 0
frameworks/PHP/hypervel/app/Http/Controllers/IndexController.php

@@ -0,0 +1,87 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Http\Controllers;
+
+use App\Models\Fortune;
+use App\Models\World;
+
+class IndexController extends AbstractController
+{
+    public function json()
+    {
+        return response()->json(['message' => 'Hello, World!']);
+    }
+
+    public function db()
+    {
+        return response()->json(World::query()->find(self::randomInt()));
+    }
+
+    public function queries($queries = 1)
+    {
+        $queries = self::clamp($queries);
+
+        $rows = [];
+        while ($queries--) {
+            $rows[] = World::query()->find(self::randomInt());
+        }
+
+        return response()->json($rows);
+    }
+
+    public function fortunes()
+    {
+        $rows = Fortune::all();
+
+        $insert = new Fortune();
+        $insert->id = 0;
+        $insert->message = 'Additional fortune added at request time.';
+
+        $rows->add($insert);
+        $rows = $rows->sortBy('message');
+
+        return response(view('fortunes', ['rows' => $rows]), 200, ['Content-Type' => 'text/html; charset=UTF-8']);
+    }
+
+    public function updates($queries = 1)
+    {
+        $queries = self::clamp($queries);
+
+        $rows = [];
+
+        while ($queries--) {
+            $row = World::query()->find(self::randomInt());
+            while (($randomInt = self::randomInt()) === $row->randomNumber) {
+            }
+            $row->randomNumber = $randomInt;
+            $row->save();
+
+            $rows[] = $row;
+        }
+
+        return response()->json($rows);
+    }
+
+    public function plaintext()
+    {
+        return response('Hello, World!', 200, ['Content-Type' => 'text/plain']);
+    }
+
+    private static function randomInt()
+    {
+        return random_int(1, 10000);
+    }
+
+    private static function clamp($value)
+    {
+        if (!is_numeric($value) || $value < 1) {
+            return 1;
+        }
+        if ($value > 500) {
+            return 500;
+        }
+        return (int)$value;
+    }
+}

+ 73 - 0
frameworks/PHP/hypervel/app/Http/Kernel.php

@@ -0,0 +1,73 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Http;
+
+use Hypervel\Foundation\Http\Kernel as HttpKernel;
+
+class Kernel extends HttpKernel
+{
+    /**
+     * The application's global HTTP middleware stack.
+     *
+     * These middleware are run during every request to your application.
+     *
+     * @var array<int, class-string|string>
+     */
+    protected array $middleware = [
+        // \App\Http\Middleware\TrimStrings::class,
+        // \Hypervel\Http\Middleware\HandleCors::class,
+        // \App\Http\Middleware\ConvertEmptyStringsToNull::class
+    ];
+
+    /**
+     * The application's route middleware groups.
+     *
+     * @var array<string, array<int, class-string|string>>
+     */
+    protected array $middlewareGroups = [
+        'web' => [
+            // \Hypervel\Router\Middleware\SubstituteBindings::class,
+            // \Hypervel\Cookie\Middleware\AddQueuedCookiesToResponse::class,
+            // \Hypervel\Session\Middleware\StartSession::class,
+            // \Hypervel\View\Middleware\ShareErrorsFromSession::class,
+            // \App\Http\Middleware\VerifyCsrfToken::class,
+        ],
+
+        'api' => [
+            // 'throttle:60,1,api',
+            // \Hypervel\Router\Middleware\SubstituteBindings::class,
+        ],
+    ];
+
+    /**
+     * The application's middleware aliases.
+     *
+     * Aliases may be used instead of class names to conveniently assign middleware to routes and groups.
+     *
+     * @var array<string, class-string|string>
+     */
+    protected array $middlewareAliases = [
+        // 'auth' => \App\Http\Middleware\Authenticate::class,
+        // 'can' => \Hypervel\Auth\Middleware\Authorize::class,
+        // 'throttle' => \Hypervel\Router\Middleware\ThrottleRequests::class,
+        // 'bindings' => \Hypervel\Router\Middleware\SubstituteBindings::class,
+        // 'signed' => \App\Http\Middleware\ValidateSignature::class,
+    ];
+
+    /**
+     * The priority-sorted list of middleware.
+     *
+     * Forces non-global middleware to always be in the given order.
+     *
+     * @var string[]
+     */
+    protected array $middlewarePriority = [
+        // \Hypervel\Router\Middleware\ThrottleRequests::class,
+        // \Hypervel\Router\Middleware\SubstituteBindings::class,
+        // \Hypervel\Session\Middleware\StartSession::class,
+        // \Hypervel\View\Middleware\ShareErrorsFromSession::class,
+        // \App\Http\Middleware\VerifyCsrfToken::class,
+    ];
+}

+ 14 - 0
frameworks/PHP/hypervel/app/Models/Fortune.php

@@ -0,0 +1,14 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Models;
+
+use App\Models\Model;
+
+class Fortune extends Model
+{
+	protected ?string $table = 'Fortune';
+
+	public bool $timestamps = false;
+}

+ 12 - 0
frameworks/PHP/hypervel/app/Models/Model.php

@@ -0,0 +1,12 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Models;
+
+use Hypervel\Database\Eloquent\Model as BaseModel;
+
+abstract class Model extends BaseModel
+{
+    protected ?string $connection = null;
+}

+ 20 - 0
frameworks/PHP/hypervel/app/Models/User.php

@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Models;
+
+use Hypervel\Foundation\Auth\User as Authenticatable;
+
+class User extends Authenticatable
+{
+    /**
+     * The attributes that are mass assignable.
+     */
+    protected array $fillable = [
+        'name',
+        'email',
+        'email_verified_at',
+        'password',
+    ];
+}

+ 14 - 0
frameworks/PHP/hypervel/app/Models/World.php

@@ -0,0 +1,14 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Models;
+
+use App\Models\Model;
+
+class World extends Model
+{
+	protected ?string $table = 'World';
+
+	public bool $timestamps = false;
+}

+ 18 - 0
frameworks/PHP/hypervel/app/Providers/AppServiceProvider.php

@@ -0,0 +1,18 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Providers;
+
+use Hypervel\Support\ServiceProvider;
+
+class AppServiceProvider extends ServiceProvider
+{
+    public function boot(): void
+    {
+    }
+
+    public function register(): void
+    {
+    }
+}

+ 34 - 0
frameworks/PHP/hypervel/app/Providers/RouteServiceProvider.php

@@ -0,0 +1,34 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Providers;
+
+use Hypervel\Foundation\Support\Providers\RouteServiceProvider as BaseServiceProvider;
+use Hypervel\Support\Facades\Route;
+
+class RouteServiceProvider extends BaseServiceProvider
+{
+    /**
+     * The route files for the application.
+     */
+    protected array $routes = [
+    ];
+
+    public function boot(): void
+    {
+        parent::boot();
+
+        Route::group(
+            '/api',
+            base_path('routes/api.php'),
+            ['middleware' => 'api']
+        );
+
+        Route::group(
+            '/',
+            base_path('routes/web.php'),
+            ['middleware' => 'web']
+        );
+    }
+}

+ 26 - 0
frameworks/PHP/hypervel/artisan

@@ -0,0 +1,26 @@
+#!/usr/bin/env php
+<?php
+
+declare(strict_types=1);
+
+ini_set('display_errors', 'on');
+ini_set('display_startup_errors', 'on');
+ini_set('memory_limit', '1G');
+
+error_reporting(E_ALL);
+
+! defined('BASE_PATH') && define('BASE_PATH', __DIR__);
+
+require BASE_PATH . '/vendor/autoload.php';
+
+! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);
+
+// Self-called anonymous function that creates its own scope and keep the global namespace clean.
+(function () {
+    Hypervel\Foundation\ClassLoader::init();
+    /** @var Hypervel\Foundation\Contracts\Application $container */
+    $container = require BASE_PATH . '/bootstrap/app.php';
+
+    $application = $container->get(Hyperf\Contract\ApplicationInterface::class);
+    $application->run();
+})();

+ 28 - 0
frameworks/PHP/hypervel/benchmark_config.json

@@ -0,0 +1,28 @@
+{
+	"framework": "hypervel",
+	"tests": [{
+		"default": {
+			"json_url": "/json",
+			"db_url": "/db",
+			"query_url": "/queries/",
+			"fortune_url": "/fortunes",
+			"update_url": "/updates/",
+			"plaintext_url": "/plaintext",
+			"port": 9501,
+			"approach": "Realistic",
+			"classification": "Fullstack",
+			"database": "MySQL",
+			"framework": "lypervel",
+			"language": "PHP",
+			"flavor": "PHP8",
+			"orm": "Full",
+			"platform": "swoole",
+			"webserver": "none",
+			"os": "Linux",
+			"database_os": "Linux",
+			"display_name": "hypervel",
+			"notes": "",
+			"versus": "swoole"
+		}
+	}]
+}

+ 40 - 0
frameworks/PHP/hypervel/bootstrap/app.php

@@ -0,0 +1,40 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+|--------------------------------------------------------------------------
+| Create The Application
+|--------------------------------------------------------------------------
+|
+| The first thing we will do is create a new Hypervel application instance
+| which serves as the "glue" for all the components of Hypervel, and is
+| the IoC container for the system binding all of the various parts.
+|
+*/
+
+$app = new Hypervel\Foundation\Application();
+
+/*
+|--------------------------------------------------------------------------
+| Bind Important Interfaces
+|--------------------------------------------------------------------------
+|
+| Next, we need to bind some important interfaces into the container so
+| we will be able to resolve them when needed.
+|
+*/
+
+$app->bind(
+    Hypervel\Foundation\Console\Contracts\Kernel::class,
+    App\Console\Kernel::class
+);
+
+$app->bind(
+    Hypervel\Foundation\Exceptions\Contracts\ExceptionHandler::class,
+    App\Exceptions\Handler::class
+);
+
+Hypervel\Context\ApplicationContext::setContainer($app);
+
+return $app;

+ 100 - 0
frameworks/PHP/hypervel/composer.json

@@ -0,0 +1,100 @@
+{
+    "name": "hypervel/hypervel",
+    "type": "project",
+    "keywords": [
+        "php",
+        "swoole",
+        "framework",
+        "hyperf",
+        "microservice",
+        "laravel",
+        "hypervel"
+    ],
+    "description": "A Laravel-style PHP framework with native coroutine support for ultra-high performance.",
+    "license": "MIT",
+    "require": {
+        "php": ">=8.2",
+        "friendsofhyperf/tinker": "~3.1.0",
+        "hypervel/framework": "^0.2"
+    },
+    "require-dev": {
+        "fakerphp/faker": "^1.24.1",
+        "filp/whoops": "^2.15",
+        "friendsofphp/php-cs-fixer": "^3.57.2",
+        "hyperf/testing": "~3.1.0",
+        "hyperf/watcher": "~3.1.0",
+        "hypervel/devtool": "^0.2",
+        "mockery/mockery": "1.6.x-dev",
+        "nunomaduro/collision": "^8.5",
+        "phpstan/phpstan": "^1.11.5",
+        "phpunit/phpunit": "10.5.45",
+        "swoole/ide-helper": "~5.1.0"
+    },
+    "autoload": {
+        "psr-4": {
+            "App\\": "app/"
+        },
+        "files": []
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "Tests\\": "tests/"
+        },
+        "files": [
+            "tests/helpers.php"
+        ]
+    },
+    "minimum-stability": "dev",
+    "prefer-stable": true,
+    "suggest": {
+        "ext-redis": "Required to use Redis-based drivers, such as cache, session, queue, etc.",
+        "ext-fileinfo": "Required to use the Filesystem class.",
+        "ext-ftp": "Required to use the Flysystem FTP driver.",
+        "ext-hash": "Required to use the Filesystem class.",
+        "ext-pcntl": "Required to use all features of the queue worker.",
+        "ext-posix": "Required to use all features of the queue worker.",
+        "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).",
+        "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).",
+        "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.3).",
+        "league/flysystem-read-only": "Required to use read-only disks (^3.3)",
+        "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).",
+        "flysystem-google-cloud-storage": "Required to use the Flysystem Google Cloud Storage driver (^3.0).",
+        "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).",
+        "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).",
+        "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.322.9).",
+        "symfony/http-client": "Required to use the Symfony API mail transports (^6.2).",
+        "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^6.2).",
+        "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^6.2).",
+        "pda/pheanstalk": "Required to use the Beanstalk queue driver (^5.0)."
+    },
+    "config": {
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "extra": {
+        "hypervel": {
+            "dont-discover": []
+        }
+    },
+    "scripts": {
+        "post-root-package-install": [
+            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
+        ],
+        "post-create-project-cmd": [
+            "@php artisan key:generate --ansi",
+            "@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"",
+            "@php artisan migrate --graceful --ansi"
+        ],
+        "post-autoload-dump": [
+            "rm -rf runtime/container"
+        ],
+        "test": "phpunit -c phpunit.xml.dist --colors=always",
+        "cs-diff": "php-cs-fixer fix --path-mode=intersection `git diff --name-only --diff-filter=ACMRTUXB origin/main..HEAD`",
+        "cs-fix": "php-cs-fixer fix $1",
+        "analyse": "phpstan analyse --memory-limit 300M -c phpstan.neon",
+        "start": [
+            "Composer\\Config::disableProcessTimeout",
+            "php artisan start"
+        ]
+    }
+}

+ 19 - 0
frameworks/PHP/hypervel/config.toml

@@ -0,0 +1,19 @@
+[framework]
+name = "hypervel"
+
+[hypervel]
+urls.plaintext = "/plaintext"
+urls.json = "/json"
+urls.db = "/db"
+urls.query = "/queries/"
+urls.update = "/updates/"
+urls.fortune = "/fortunes"
+approach = "Realistic"
+classification = "Fullstack"
+database = "MySQL"
+database_os = "Linux"
+os = "Linux"
+orm = "Full"
+platform = "swoole"
+webserver = "none"
+versus = "swoole"

+ 171 - 0
frameworks/PHP/hypervel/config/app.php

@@ -0,0 +1,171 @@
+<?php
+
+declare(strict_types=1);
+
+use Hypervel\Support\Facades\Facade;
+use Hypervel\Support\ServiceProvider;
+use Psr\Log\LogLevel;
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | Application Name
+    |--------------------------------------------------------------------------
+    |
+    | This value is the name of your application. This value is used when the
+    | framework needs to place the application's name in a notification or
+    | any other location as required by the application or its packages.
+    |
+    */
+
+    'name' => env('APP_NAME', 'Hypervel'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Application Environment
+    |--------------------------------------------------------------------------
+    |
+    | This value determines the "environment" your application is currently
+    | running in. This may determine how you prefer to configure various
+    | services the application utilizes. Set "APP_ENV" in your ".env" file.
+    |
+    */
+
+    'env' => env('APP_ENV', 'production'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Application Debug Mode
+    |--------------------------------------------------------------------------
+    |
+    | When your application is in debug mode, detailed error messages with
+    | stack traces will be shown on every error that occurs within your
+    | application. If disabled, a simple generic error page is shown.
+    | Set "APP_DEBUG" in your ".env" file.
+    |
+    */
+
+    'debug' => (bool) env('APP_DEBUG', false),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Cacheable Flag for Annotations Scanning
+    |--------------------------------------------------------------------------
+    |
+    | Enabling this option will cache the annotations scanning result. It
+    | can boost the performance of the framework initialization.
+    | Please disable it in the development environment.
+    |
+    */
+    'scan_cacheable' => env('SCAN_CACHEABLE', false),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Log Levels for StdoutLogger
+    |--------------------------------------------------------------------------
+    |
+    | This value only determines the log levels that are written to the stdout logger.
+    | It does not affect the log levels that are written to the other loggers.
+    |
+    */
+    'stdout_log_level' => [
+        LogLevel::ALERT,
+        LogLevel::CRITICAL,
+        // LogLevel::DEBUG,
+        LogLevel::EMERGENCY,
+        LogLevel::ERROR,
+        LogLevel::INFO,
+        LogLevel::NOTICE,
+        LogLevel::WARNING,
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Application URL
+    |--------------------------------------------------------------------------
+    |
+    | This URL is used by the console to properly generate URLs when using
+    | the Artisan command line tool. You should set this to the root of
+    | your application so that it is used when running Artisan tasks.
+    |
+    */
+
+    'url' => env('APP_URL', 'http://localhost'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Application Timezone
+    |--------------------------------------------------------------------------
+    |
+    | Here you may specify the default timezone for your application, which
+    | will be used by the PHP date and date-time functions. We have gone
+    | ahead and set this to a sensible default for you out of the box.
+    |
+    */
+
+    'timezone' => env('APP_TIMEZONE', 'UTC'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Application Locale Configuration
+    |--------------------------------------------------------------------------
+    |
+    | The application locale determines the default locale that will be used
+    | by the translation service provider. You are free to set this value
+    | to any of the locales which will be supported by the application.
+    |
+    */
+
+    'locale' => env('APP_LOCALE', 'en'),
+
+    'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Encryption Key
+    |--------------------------------------------------------------------------
+    |
+    | This key is utilized by Laravel's encryption services and should be set
+    | to a random, 32 character string to ensure that all encrypted values
+    | are secure. You should do this prior to deploying the application.
+    |
+    */
+
+    'cipher' => 'AES-256-CBC',
+
+    'key' => env('APP_KEY'),
+
+    'previous_keys' => [
+        ...array_filter(
+            explode(',', env('APP_PREVIOUS_KEYS', ''))
+        ),
+    ],
+
+    'providers' => ServiceProvider::defaultProviders()->merge([
+        /*
+         * Package Service Providers...
+         */
+
+        /*
+         * Application Service Providers...
+         */
+        App\Providers\AppServiceProvider::class,
+        // App\Providers\BroadcastServiceProvider::class,
+        // App\Providers\EventServiceProvider::class,
+        App\Providers\RouteServiceProvider::class,
+    ])->toArray(),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Class Aliases
+    |--------------------------------------------------------------------------
+    |
+    | This array of class aliases will be registered when this application
+    | is started.
+    |
+    */
+
+    'aliases' => Facade::defaultAliases()->merge([
+        // 'Example' => App\Facades\Example::class,
+    ])->toArray(),
+];

+ 103 - 0
frameworks/PHP/hypervel/config/cache.php

@@ -0,0 +1,103 @@
+<?php
+
+declare(strict_types=1);
+
+use Hypervel\Cache\SwooleStore;
+use Hypervel\Support\Str;
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | Default Cache Store
+    |--------------------------------------------------------------------------
+    |
+    | This option controls the default cache connection that gets used while
+    | using this caching library. This connection is used when another is
+    | not explicitly specified when executing a given caching function.
+    |
+    */
+
+    'default' => env('CACHE_DRIVER', 'array'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Cache Stores
+    |--------------------------------------------------------------------------
+    |
+    | Here you may define all of the cache "stores" for your application as
+    | well as their drivers. You may even define multiple stores for the
+    | same cache driver to group types of items stored in your caches.
+    |
+    | Supported drivers: "array", "file", "redis", "swoole", "stack", "null"
+    |
+    */
+
+    'stores' => [
+        'array' => [
+            'driver' => 'array',
+            'serialize' => false,
+        ],
+
+        'file' => [
+            'driver' => 'file',
+            'path' => storage_path('cache/data'),
+            'lock_path' => storage_path('cache/data'),
+        ],
+
+        'redis' => [
+            'driver' => 'redis',
+            'connection' => 'default',
+            'lock_connection' => 'default',
+        ],
+
+        'swoole' => [
+            'driver' => 'swoole',
+            'table' => 'default',
+            'memory_limit_buffer' => 0.05,
+            'eviction_policy' => SwooleStore::EVICTION_POLICY_LRU,
+            'eviction_proportion' => 0.05,
+            'eviction_interval' => 10000, // milliseconds
+        ],
+
+        'stack' => [
+            'driver' => 'stack',
+            'stores' => [
+                'swoole' => [
+                    'ttl' => 3, // seconds
+                ],
+                'redis',
+            ],
+        ],
+
+        'database' => [
+            'driver' => 'database',
+            'connection' => env('DB_CACHE_CONNECTION', env('DB_CONNECTION', 'default')),
+            'table' => env('DB_CACHE_TABLE', 'cache'),
+            'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'),
+            'lock_table' => env('DB_CACHE_LOCK_TABLE', 'cache_locks'),
+            'lock_lottery' => [2, 100],
+            'lock_timeout' => 86400,
+        ],
+    ],
+
+    'swoole_tables' => [
+        'default' => [
+            'rows' => 1024,
+            'bytes' => 10240,
+            'conflict_proportion' => 0.2,
+        ],
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Cache Key Prefix
+    |--------------------------------------------------------------------------
+    |
+    | When utilizing a RAM based store such as APC or Memcached, there might
+    | be other applications utilizing the same cache. So, we'll specify a
+    | value to get prefixed to all our keys so we can avoid collisions.
+    |
+    */
+
+    'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'hypervel'), '_') . '_cache'),
+];

+ 137 - 0
frameworks/PHP/hypervel/config/database.php

@@ -0,0 +1,137 @@
+<?php
+
+declare(strict_types=1);
+
+use Hypervel\Support\Str;
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | Default Database Connection Name
+    |--------------------------------------------------------------------------
+    |
+    | Here you may specify which of the database connections below you wish
+    | to use as your default connection for database operations. This is
+    | the connection which will be utilized unless another connection
+    | is explicitly specified when you execute a query / statement.
+    |
+    */
+
+    'default' => env('DB_CONNECTION', 'mysql'),
+
+    'connections' => [
+        'mysql' => [
+            'driver' => env('DB_DRIVER', 'mysql'),
+            'host' => env('DB_HOST', 'localhost'),
+            'database' => env('DB_DATABASE', 'hypervel'),
+            'port' => env('DB_PORT', 3306),
+            'username' => env('DB_USERNAME', 'root'),
+            'password' => env('DB_PASSWORD', ''),
+            'charset' => env('DB_CHARSET', 'utf8mb4'),
+            'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
+            'prefix' => env('DB_PREFIX', ''),
+            'pool' => [
+                'min_connections' => 1,
+                'max_connections' => env('DB_MAX_CONNECTIONS', 10),
+                'connect_timeout' => 10.0,
+                'wait_timeout' => 3.0,
+                'heartbeat' => -1,
+                'max_idle_time' => (float) env('DB_MAX_IDLE_TIME', 60),
+            ],
+        ],
+
+        'pgsql' => [
+            'driver' => env('DB_DRIVER', 'pgsql'),
+            'host' => env('DB_HOST', 'localhost'),
+            'database' => env('DB_DATABASE', 'hypervel'),
+            'schema' => env('DB_SCHEMA', 'public'),
+            'port' => env('DB_PORT', 5432),
+            'username' => env('DB_USERNAME', 'root'),
+            'password' => env('DB_PASSWORD', ''),
+            'charset' => env('DB_CHARSET', 'utf8'),
+            'pool' => [
+                'min_connections' => 1,
+                'max_connections' => env('DB_MAX_CONNECTIONS', 10),
+                'connect_timeout' => 10.0,
+                'wait_timeout' => 3.0,
+                'heartbeat' => -1,
+                'max_idle_time' => (float) env('DB_MAX_IDLE_TIME', 60),
+            ],
+        ],
+
+        'sqlite' => [
+            'driver' => 'sqlite',
+            'url' => env('DATABASE_URL'),
+            'database' => env('DB_DATABASE', database_path('database.sqlite')),
+            'prefix' => '',
+            'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
+        ],
+
+        'sqlite_testing' => [
+            'driver' => 'sqlite',
+            'database' => ':memory:',
+            'prefix' => '',
+            'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
+        ],
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Migration Repository Table
+    |--------------------------------------------------------------------------
+    |
+    | This table keeps track of all the migrations that have already run for
+    | your application. Using this information, we can determine which of
+    | the migrations on disk haven't actually been run on the database.
+    |
+    */
+
+    'migrations' => 'migrations',
+
+    /*
+    |--------------------------------------------------------------------------
+    | Redis Databases
+    |--------------------------------------------------------------------------
+    |
+    | Redis is an open source, fast, and advanced key-value store that also
+    | provides a richer body of commands than a typical key-value system
+    | such as Memcached. You may define your connection settings here.
+    |
+    */
+
+    'redis' => [
+        'options' => [
+            'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'hypervel'), '_') . '_database_'),
+        ],
+
+        'default' => [
+            'host' => env('REDIS_HOST', 'localhost'),
+            'auth' => env('REDIS_AUTH', null),
+            'port' => (int) env('REDIS_PORT', 6379),
+            'db' => (int) env('REDIS_DB', 0),
+            'pool' => [
+                'min_connections' => 1,
+                'max_connections' => 10,
+                'connect_timeout' => 10.0,
+                'wait_timeout' => 3.0,
+                'heartbeat' => -1,
+                'max_idle_time' => (float) env('REDIS_MAX_IDLE_TIME', 60),
+            ],
+        ],
+
+        'queue' => [
+            'host' => env('REDIS_HOST', 'localhost'),
+            'auth' => env('REDIS_AUTH', null),
+            'port' => (int) env('REDIS_PORT', 6379),
+            'db' => (int) env('REDIS_DB', 0),
+            'pool' => [
+                'min_connections' => 1,
+                'max_connections' => 10,
+                'connect_timeout' => 10.0,
+                'wait_timeout' => 3.0,
+                'heartbeat' => -1,
+                'max_idle_time' => (float) env('REDIS_MAX_IDLE_TIME', 60),
+            ],
+        ],
+    ],
+];

+ 140 - 0
frameworks/PHP/hypervel/config/logging.php

@@ -0,0 +1,140 @@
+<?php
+
+declare(strict_types=1);
+
+use Monolog\Handler\NullHandler;
+use Monolog\Handler\StreamHandler;
+use Monolog\Handler\SyslogUdpHandler;
+use Monolog\Processor\PsrLogMessageProcessor;
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | Default Log Channel
+    |--------------------------------------------------------------------------
+    |
+    | This option defines the default log channel that gets used when writing
+    | messages to the logs. The name specified in this option should match
+    | one of the channels defined in the "channels" configuration array.
+    |
+    */
+
+    'default' => env('LOG_CHANNEL', 'stack'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Deprecations Log Channel
+    |--------------------------------------------------------------------------
+    |
+    | This option controls the log channel that should be used to log warnings
+    | regarding deprecated PHP and library features. This allows you to get
+    | your application ready for upcoming major versions of dependencies.
+    |
+    */
+
+    'deprecations' => [
+        'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
+        'trace' => false,
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Log Channels
+    |--------------------------------------------------------------------------
+    |
+    | Here you may configure the log channels for your application. Out of
+    | the box, Laravel uses the Monolog PHP logging library. This gives
+    | you a variety of powerful log handlers / formatters to utilize.
+    |
+    | Available Drivers: "single", "daily", "slack", "syslog",
+    |                    "errorlog", "monolog",
+    |                    "custom", "stack"
+    |
+    */
+
+    'channels' => [
+        'stack' => [
+            'driver' => 'stack',
+            'channels' => ['single'],
+            'ignore_exceptions' => false,
+        ],
+
+        'single' => [
+            'driver' => 'single',
+            'path' => storage_path('logs/hypervel.log'),
+            'level' => env('LOG_LEVEL', 'debug'),
+            'replace_placeholders' => true,
+        ],
+
+        'daily' => [
+            'driver' => 'daily',
+            'path' => storage_path('logs/hypervel.log'),
+            'level' => env('LOG_LEVEL', 'debug'),
+            'days' => 14,
+            'replace_placeholders' => true,
+        ],
+
+        'slack' => [
+            'driver' => 'slack',
+            'url' => env('LOG_SLACK_WEBHOOK_URL'),
+            'username' => 'Laravel Log',
+            'emoji' => ':boom:',
+            'level' => env('LOG_LEVEL', 'critical'),
+            'replace_placeholders' => true,
+        ],
+
+        'papertrail' => [
+            'driver' => 'monolog',
+            'level' => env('LOG_LEVEL', 'debug'),
+            'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),
+            'handler_with' => [
+                'host' => env('PAPERTRAIL_URL'),
+                'port' => env('PAPERTRAIL_PORT'),
+                'connectionString' => 'tls://' . env('PAPERTRAIL_URL') . ':' . env('PAPERTRAIL_PORT'),
+            ],
+            'processors' => [PsrLogMessageProcessor::class],
+        ],
+
+        'stdout' => [
+            'driver' => 'monolog',
+            'handler' => StreamHandler::class,
+            'formatter' => env('LOG_STDOUT_FORMATTER'),
+            'with' => [
+                'stream' => 'php://stdout',
+            ],
+        ],
+
+        'stderr' => [
+            'driver' => 'monolog',
+            'level' => env('LOG_LEVEL', 'debug'),
+            'handler' => StreamHandler::class,
+            'formatter' => env('LOG_STDERR_FORMATTER'),
+            'with' => [
+                'stream' => 'php://stderr',
+            ],
+            'processors' => [PsrLogMessageProcessor::class],
+        ],
+
+        'syslog' => [
+            'driver' => 'syslog',
+            'level' => env('LOG_LEVEL', 'debug'),
+            'facility' => LOG_USER,
+            'replace_placeholders' => true,
+        ],
+
+        'errorlog' => [
+            'driver' => 'errorlog',
+            'level' => env('LOG_LEVEL', 'debug'),
+            'replace_placeholders' => true,
+        ],
+
+        'null' => [
+            'driver' => 'monolog',
+            'handler' => NullHandler::class,
+        ],
+
+        'emergency' => [
+            'path' => storage_path('logs/hypervel.log'),
+        ],
+    ],
+];

+ 137 - 0
frameworks/PHP/hypervel/config/queue.php

@@ -0,0 +1,137 @@
+<?php
+
+declare(strict_types=1);
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | Default Queue Connection Name
+    |--------------------------------------------------------------------------
+    |
+    | Hypervel's queue supports a variety of backends via a single, unified
+    | API, giving you convenient access to each backend using identical
+    | syntax for each. The default queue connection is defined below.
+    |
+    */
+
+    'default' => env('QUEUE_CONNECTION', 'database'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Concurrency Number
+    |--------------------------------------------------------------------------
+    |
+    | This value determines the number of jobs that will be processed at once
+    | by every worker.
+    |
+    */
+    'concurrency_number' => env('QUEUE_CONCURRENCY_NUMBER', 1),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Queue Connections
+    |--------------------------------------------------------------------------
+    |
+    | Here you may configure the connection options for every queue backend
+    | used by your application. An example configuration is provided for
+    | each backend supported by Hypervel. You're also free to add more.
+    |
+    | Drivers: "sync", "defer", "database", "beanstalkd", "sqs", "redis", "null"
+    |
+    */
+
+    'connections' => [
+        'sync' => [
+            'driver' => 'sync',
+        ],
+
+        'defer' => [
+            'driver' => 'defer',
+        ],
+
+        'database' => [
+            'driver' => 'database',
+            'connection' => env('DB_QUEUE_CONNECTION'),
+            'table' => env('DB_QUEUE_TABLE', 'jobs'),
+            'queue' => env('DB_QUEUE', 'default'),
+            'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90),
+            'after_commit' => false,
+        ],
+
+        'beanstalkd' => [
+            'driver' => 'beanstalkd',
+            'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'),
+            'queue' => env('BEANSTALKD_QUEUE', 'default'),
+            'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90),
+            'block_for' => 0,
+            'after_commit' => false,
+            'pool' => [
+                'min_objects' => 1,
+                'max_objects' => 10,
+                'wait_timeout' => 3.0,
+                'max_lifetime' => 60.0,
+            ],
+        ],
+
+        'sqs' => [
+            'driver' => 'sqs',
+            'key' => env('AWS_ACCESS_KEY_ID'),
+            'secret' => env('AWS_SECRET_ACCESS_KEY'),
+            'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
+            'queue' => env('SQS_QUEUE', 'default'),
+            'suffix' => env('SQS_SUFFIX'),
+            'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
+            'after_commit' => false,
+            'pool' => [
+                'min_objects' => 1,
+                'max_objects' => 10,
+                'wait_timeout' => 3.0,
+                'max_lifetime' => 60.0,
+            ],
+        ],
+
+        'redis' => [
+            'driver' => 'redis',
+            'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),
+            'queue' => env('REDIS_QUEUE', 'default'),
+            'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90),
+            'block_for' => null,
+            'after_commit' => false,
+        ],
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Job Batching
+    |--------------------------------------------------------------------------
+    |
+    | The following options configure the database and table that store job
+    | batching information. These options can be updated to any database
+    | connection and table which has been defined by your application.
+    |
+    */
+
+    'batching' => [
+        'database' => env('DB_CONNECTION', 'sqlite'),
+        'table' => 'job_batches',
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Failed Queue Jobs
+    |--------------------------------------------------------------------------
+    |
+    | These options configure the behavior of failed queue job logging so you
+    | can control how and where failed jobs are stored. Hypervel ships with
+    | support for storing failed jobs in a simple file or in a database.
+    |
+    | Supported drivers: "database-uuids", "dynamodb", "file", "null"
+    |
+    */
+
+    'failed' => [
+        'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
+        'database' => env('DB_CONNECTION', 'sqlite'),
+        'table' => 'failed_jobs',
+    ],
+];

+ 45 - 0
frameworks/PHP/hypervel/config/server.php

@@ -0,0 +1,45 @@
+<?php
+
+declare(strict_types=1);
+
+use App\Http\Kernel as HttpKernel;
+use Hyperf\Server\Event;
+use Hyperf\Server\Server;
+use Swoole\Constant;
+
+return [
+    'mode' => SWOOLE_PROCESS,
+    'servers' => [
+        [
+            'name' => 'http',
+            'type' => Server::SERVER_HTTP,
+            'host' => env('HTTP_SERVER_HOST', '0.0.0.0'),
+            'port' => (int) env('HTTP_SERVER_PORT', 9501),
+            'sock_type' => SWOOLE_SOCK_TCP,
+            'callbacks' => [
+                Event::ON_REQUEST => [HttpKernel::class, 'onRequest'],
+            ],
+        ],
+    ],
+    'kernels' => [
+        'http' => HttpKernel::class,
+    ],
+    'settings' => [
+        'document_root' => base_path('public'),
+        'enable_static_handler' => true,
+        Constant::OPTION_ENABLE_COROUTINE => true,
+        Constant::OPTION_WORKER_NUM => env('SERVER_WORKERS_NUMBER', swoole_cpu_num()),
+        Constant::OPTION_PID_FILE => base_path('runtime/hypervel.pid'),
+        Constant::OPTION_OPEN_TCP_NODELAY => true,
+        Constant::OPTION_MAX_COROUTINE => 100000,
+        Constant::OPTION_OPEN_HTTP2_PROTOCOL => true,
+        Constant::OPTION_MAX_REQUEST => 100000,
+        Constant::OPTION_SOCKET_BUFFER_SIZE => 2 * 1024 * 1024,
+        Constant::OPTION_BUFFER_OUTPUT_SIZE => 2 * 1024 * 1024,
+    ],
+    'callbacks' => [
+        Event::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
+        Event::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
+        Event::ON_WORKER_EXIT => [Hyperf\Framework\Bootstrap\WorkerExitCallback::class, 'onWorkerExit'],
+    ],
+];

+ 20 - 0
frameworks/PHP/hypervel/config/view.php

@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+use Hyperf\View\Mode;
+use Hyperf\ViewEngine\HyperfViewEngine;
+
+return [
+    'engine' => HyperfViewEngine::class,
+    'mode' => Mode::SYNC,
+    'config' => [
+        'view_path' => base_path('resources/views'),
+        'cache_path' => storage_path('framework/views'),
+    ],
+    'event' => [
+        'enable' => false,
+    ],
+    'components' => [
+    ],
+];

+ 17 - 0
frameworks/PHP/hypervel/config/watcher.php

@@ -0,0 +1,17 @@
+<?php
+
+declare(strict_types=1);
+
+use Hyperf\Watcher\Driver\ScanFileDriver;
+
+return [
+    'driver' => ScanFileDriver::class,
+    'bin' => PHP_BINARY,
+    'command' => 'artisan serve',
+    'watch' => [
+        'dir' => ['app', 'config', 'routes', 'resources'],
+        'file' => ['.env'],
+        'scan_interval' => 2000,
+    ],
+    'ext' => ['.php', '.env'],
+];

+ 16 - 0
frameworks/PHP/hypervel/database/factories/UserFactory.php

@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+use App\Models\User;
+use Carbon\Carbon;
+use Faker\Generator as Faker;
+
+$factory->define(User::class, function (Faker $faker) {
+    return [
+        'name' => $faker->unique()->name(),
+        'email' => $faker->unique()->safeEmail(),
+        'email_verified_at' => Carbon::now(),
+        'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
+    ];
+});

+ 32 - 0
frameworks/PHP/hypervel/database/migrations/2023_08_03_000000_create_users_table.php

@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+use Hyperf\Database\Schema\Blueprint;
+use Hypervel\Database\Migrations\Migration;
+use Hypervel\Support\Facades\Schema;
+
+return new class extends Migration {
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::create('users', function (Blueprint $table) {
+            $table->id();
+            $table->string('name');
+            $table->string('email')->unique();
+            $table->timestamp('email_verified_at')->nullable();
+            $table->string('password');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('users');
+    }
+};

+ 21 - 0
frameworks/PHP/hypervel/database/seeders/DatabaseSeeder.php

@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+use Hyperf\Database\Seeders\Seeder;
+
+class DatabaseSeeder extends Seeder
+{
+    /**
+     * Seed the application's database.
+     */
+    public function run(): void
+    {
+        // \App\Models\User::factory(10)->create();
+
+        // \App\Models\User::factory()->create([
+        //     'name' => 'Test User',
+        //     'email' => '[email protected]',
+        // ]);
+    }
+}

+ 22 - 0
frameworks/PHP/hypervel/hypervel.dockerfile

@@ -0,0 +1,22 @@
+FROM phpswoole/swoole:php8.4
+
+RUN docker-php-ext-install pcntl opcache curl > /dev/null
+
+RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
+RUN echo "opcache.jit=1205" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
+RUN echo "opcache.jit_buffer_size=128M" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
+
+WORKDIR /hypervel
+COPY --link . .
+
+RUN mkdir -p bootstrap/cache \
+            storage/logs \
+            storage/framework/sessions \
+            storage/framework/views \
+            storage/framework/cache
+
+RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet
+
+EXPOSE 9501
+
+ENTRYPOINT ["php", "artisan", "serve"]

+ 197 - 0
frameworks/PHP/hypervel/lang/en/validation.php

@@ -0,0 +1,197 @@
+<?php
+
+declare(strict_types=1);
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | Validation Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines contain the default error messages used by
+    | the validator class. Some of these rules have multiple versions such
+    | as the size rules. Feel free to tweak each of these messages here.
+    |
+    */
+
+    'accepted' => 'The :attribute must be accepted.',
+    'accepted_if' => 'The :attribute must be accepted when :other is :value.',
+    'active_url' => 'The :attribute is not a valid URL.',
+    'after' => 'The :attribute must be a date after :date.',
+    'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
+    'alpha' => 'The :attribute may only contain letters.',
+    'alpha_dash' => 'The :attribute may only contain letters, numbers, and dashes.',
+    'alpha_num' => 'The :attribute may only contain letters and numbers.',
+    'array' => 'The :attribute must be an array.',
+    'ascii' => 'The :attribute must only contain single-byte alphanumeric characters and symbols.',
+    'before' => 'The :attribute must be a date before :date.',
+    'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
+    'between' => [
+        'numeric' => 'The :attribute must be between :min and :max.',
+        'file' => 'The :attribute must be between :min and :max kilobytes.',
+        'string' => 'The :attribute must be between :min and :max characters.',
+        'array' => 'The :attribute must have between :min and :max items.',
+    ],
+    'boolean' => 'The :attribute field must be true or false.',
+    'confirmed' => 'The :attribute confirmation does not match.',
+    'date' => 'The :attribute is not a valid date.',
+    'date_equals' => 'The :attribute must be a date equal to :date.',
+    'date_format' => 'The :attribute does not match the format :format.',
+    'decimal' => 'The :attribute must have :decimal decimal places.',
+    'declined' => 'The :attribute must be declined.',
+    'declined_if' => 'The :attribute must be declined when :other is :value.',
+    'different' => 'The :attribute and :other must be different.',
+    'digits' => 'The :attribute must be :digits digits.',
+    'digits_between' => 'The :attribute must be between :min and :max digits.',
+    'dimensions' => 'The :attribute has invalid image dimensions.',
+    'distinct' => 'The :attribute field has a duplicate value.',
+    'doesnt_end_with' => 'The :attribute must not end with one of the following: :values.',
+    'doesnt_start_with' => 'The :attribute must not start with one of the following: :values.',
+    'email' => 'The :attribute must be a valid email address.',
+    'ends_with' => 'The :attribute must end with one of the following: :values.',
+    'exists' => 'The selected :attribute is invalid.',
+    'file' => 'The :attribute must be a file.',
+    'filled' => 'The :attribute field is required.',
+    'gt' => [
+        'numeric' => 'The :attribute must be greater than :value',
+        'file' => 'The :attribute must be greater than :value kb',
+        'string' => 'The :attribute must be greater than :value characters',
+        'array' => 'The :attribute must be greater than :value items',
+    ],
+    'gte' => [
+        'numeric' => 'The :attribute must be great than or equal to :value',
+        'file' => 'The :attribute must be great than or equal to :value kb',
+        'string' => 'The :attribute must be great than or equal to :value characters',
+        'array' => 'The :attribute must be great than or equal to :value items',
+    ],
+    'image' => 'The :attribute must be an image.',
+    'in' => 'The selected :attribute is invalid.',
+    'in_array' => 'The :attribute field does not exist in :other.',
+    'integer' => 'The :attribute must be an integer.',
+    'ip' => 'The :attribute must be a valid IP address.',
+    'ipv4' => 'The :attribute must be a valid IPv4 address.',
+    'ipv6' => 'The :attribute must be a valid IPv6 address.',
+    'json' => 'The :attribute must be a valid JSON string.',
+    'list' => 'The :attribute must be a list.',
+    'lowercase' => 'The :attribute must be lowercase.',
+    'lt' => [
+        'numeric' => 'The :attribute must be less than :value',
+        'file' => 'The :attribute must be less than :value kb',
+        'string' => 'The :attribute must be less than :value characters',
+        'array' => 'The :attribute must be less than :value items',
+    ],
+    'lte' => [
+        'numeric' => 'The :attribute must be less than or equal to :value',
+        'file' => 'The :attribute must be less than or equal to :value kb',
+        'string' => 'The :attribute must be less than or equal to :value characters',
+        'array' => 'The :attribute must be less than or equal to :value items',
+    ],
+    'max' => [
+        'numeric' => 'The :attribute may not be greater than :max.',
+        'file' => 'The :attribute may not be greater than :max kilobytes.',
+        'string' => 'The :attribute may not be greater than :max characters.',
+        'array' => 'The :attribute may not have more than :max items.',
+    ],
+    'max_digits' => 'The :attribute must not have more than :max digits.',
+    'mimes' => 'The :attribute must be a file of type: :values.',
+    'mimetypes' => 'The :attribute must be a file of type: :values.',
+    'min' => [
+        'numeric' => 'The :attribute must be at least :min.',
+        'file' => 'The :attribute must be at least :min kilobytes.',
+        'string' => 'The :attribute must be at least :min characters.',
+        'array' => 'The :attribute must have at least :min items.',
+    ],
+    'min_digits' => 'The :attribute must have at least :min digits.',
+    'missing' => 'The :attribute must be missing.',
+    'missing_if' => 'The :attribute must be missing when :other is :value.',
+    'missing_unless' => 'The :attribute must be missing unless :other is :value.',
+    'missing_with' => 'The :attribute must be missing when :values is present.',
+    'missing_with_all' => 'The :attribute must be missing when :values are present.',
+    'multiple_of' => 'The :attribute must be a multiple of :value.',
+    'not_in' => 'The selected :attribute is invalid.',
+    'not_regex' => 'The :attribute cannot match a given regular rule.',
+    'numeric' => 'The :attribute must be a number.',
+    'present' => 'The :attribute field must be present.',
+    'prohibits' => 'The :attribute field must be present.',
+    'regex' => 'The :attribute format is invalid.',
+    'required' => 'The :attribute field is required.',
+    'required_if' => 'The :attribute field is required when :other is :value.',
+    'required_unless' => 'The :attribute field is required unless :other is in :values.',
+    'required_with' => 'The :attribute field is required when :values is present.',
+    'required_with_all' => 'The :attribute field is required when :values is present.',
+    'required_without' => 'The :attribute field is required when :values is not present.',
+    'required_without_all' => 'The :attribute field is required when none of :values are present.',
+    'exclude' => 'The :attribute field is excluded.',
+    'exclude_if' => 'The :attribute field is excluded when :other is :value.',
+    'exclude_unless' => 'The :attribute field is excluded unless :other is in :values.',
+    'exclude_with' => 'The :attribute field is excluded when :values is present.',
+    'exclude_without' => 'The :attribute field is excluded when :values is not present.',
+    'same' => 'The :attribute and :other must match.',
+    'size' => [
+        'numeric' => 'The :attribute must be :size.',
+        'file' => 'The :attribute must be :size kilobytes.',
+        'string' => 'The :attribute must be :size characters.',
+        'array' => 'The :attribute must contain :size items.',
+    ],
+    'starts_with' => 'The :attribute must be start with :values ',
+    'string' => 'The :attribute must be a string.',
+    'timezone' => 'The :attribute must be a valid zone.',
+    'unique' => 'The :attribute has already been taken.',
+    'uploaded' => 'The :attribute failed to upload.',
+    'uppercase' => 'The :attribute must be uppercase.',
+    'url' => 'The :attribute format is invalid.',
+    'ulid' => 'The :attribute must be a valid ULID.',
+    'uuid' => 'The :attribute is invalid UUID.',
+    'max_if' => [
+        'numeric' => 'The :attribute may not be greater than :max when :other is :value.',
+        'file' => 'The :attribute may not be greater than :max kilobytes when :other is :value.',
+        'string' => 'The :attribute may not be greater than :max characters when :other is :value.',
+        'array' => 'The :attribute may not have more than :max items when :other is :value.',
+    ],
+    'min_if' => [
+        'numeric' => 'The :attribute must be at least :min when :other is :value.',
+        'file' => 'The :attribute must be at least :min kilobytes when :other is :value.',
+        'string' => 'The :attribute must be at least :min characters when :other is :value.',
+        'array' => 'The :attribute must have at least :min items when :other is :value.',
+    ],
+    'between_if' => [
+        'numeric' => 'The :attribute must be between :min and :max when :other is :value.',
+        'file' => 'The :attribute must be between :min and :max kilobytes when :other is :value.',
+        'string' => 'The :attribute must be between :min and :max characters when :other is :value.',
+        'array' => 'The :attribute must have between :min and :max items when :other is :value.',
+    ],
+    /*
+    |--------------------------------------------------------------------------
+    | Custom Validation Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | Here you may specify custom validation messages for attributes using the
+    | convention "attribute.rule" to name the lines. This makes it quick to
+    | specify a specific custom language line for a given attribute rule.
+    |
+    */
+
+    'custom' => [
+        'attribute-name' => [
+            'rule-name' => 'custom-message',
+        ],
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Custom Validation Attributes
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines are used to swap attribute place-holders
+    | with something more reader friendly such as E-Mail Address instead
+    | of "email". This simply helps us make messages a little cleaner.
+    |
+    */
+
+    'attributes' => [],
+    'phone_number' => 'The :attribute must be a valid phone number',
+    'telephone_number' => 'The :attribute must be a valid telephone number',
+
+    'chinese_word' => 'The :attribute must contain valid characters(chinese/english character, number, underscore)',
+    'sequential_array' => 'The :attribute must be sequential array',
+];

+ 30 - 0
frameworks/PHP/hypervel/phpunit.xml.dist

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
+         bootstrap="tests/bootstrap.php"
+         backupGlobals="false"
+         colors="true"
+         processIsolation="false"
+         stopOnFailure="false"
+         cacheDirectory=".phpunit.cache"
+         backupStaticProperties="false">
+    <testsuites>
+        <testsuite name="Unit">
+            <directory>tests/Unit</directory>
+        </testsuite>
+        <testsuite name="Feature">
+            <directory>tests/Feature</directory>
+        </testsuite>
+    </testsuites>
+    <source>
+        <include>
+            <directory suffix=".php">app</directory>
+        </include>
+    </source>
+    <php>
+        <env name="APP_ENV" value="testing" force="true"/>
+        <env name="DB_CONNECTION" value="sqlite_testing" force="true"/>
+        <env name="CACHE_DRIVER" value="array" force="true"/>
+        <env name="QUEUE_CONNECTION" value="sync"/>
+    </php>
+</phpunit>

+ 2 - 0
frameworks/PHP/hypervel/public/robots.txt

@@ -0,0 +1,2 @@
+User-agent: *
+Disallow:

+ 13 - 0
frameworks/PHP/hypervel/resources/views/fortunes.blade.php

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head><title>Fortunes</title></head>
+<body>
+<table>
+	<tr><th>id</th><th>message</th></tr>
+
+	@foreach($rows as $row)
+		<tr><td>{{$row->id}}</td><td>{{$row->message}}</td></tr>
+	@endforeach
+</table>
+</body>
+</html>

+ 8 - 0
frameworks/PHP/hypervel/routes/api.php

@@ -0,0 +1,8 @@
+<?php
+
+declare(strict_types=1);
+
+use App\Http\Controllers\IndexController;
+use Hypervel\Support\Facades\Route;
+
+Route::any('/', [IndexController::class, 'index']);

+ 20 - 0
frameworks/PHP/hypervel/routes/channels.php

@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+use Hypervel\Support\Facades\Broadcast;
+
+/*
+|--------------------------------------------------------------------------
+| Broadcast Channels
+|--------------------------------------------------------------------------
+|
+| Here you may register all of the event broadcasting channels that your
+| application supports. The given channel authorization callbacks are
+| used to check if an authenticated user can listen to the channel.
+|
+*/
+
+Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
+    return (int) $user->id === (int) $id;
+});

+ 23 - 0
frameworks/PHP/hypervel/routes/console.php

@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+use Hypervel\Support\Facades\Artisan;
+use Hypervel\Support\Facades\Schedule;
+
+/*
+|--------------------------------------------------------------------------
+| Console Routes
+|--------------------------------------------------------------------------
+|
+| This file is where you may define all of your Closure based console
+| commands. Each Closure is bound to a command instance allowing a
+| simple approach to interacting with each command's IO methods.
+|
+*/
+
+Artisan::command('hello', function () {
+    $this->comment('Hypervel is awesome!');
+})->purpose('This is a demo closure command.');
+
+// Schedule::command('hello')->everyFiveSeconds();

+ 13 - 0
frameworks/PHP/hypervel/routes/web.php

@@ -0,0 +1,13 @@
+<?php
+
+declare(strict_types=1);
+
+use App\Http\Controllers\IndexController;
+use Hypervel\Support\Facades\Route;
+
+Route::get('/json', [IndexController::class, 'json']);
+Route::get('/db', [IndexController::class, 'db']);
+Route::get('/queries[/{queries}]', [IndexController::class, 'queries']);
+Route::get('/fortunes', [IndexController::class, 'fortunes']);
+Route::get('/updates[/{queries}]', [IndexController::class, 'updates']);
+Route::get('/plaintext', [IndexController::class, 'plaintext']);

+ 20 - 0
frameworks/PHP/hypervel/tests/Feature/ExampleTest.php

@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Tests\Feature;
+
+use Tests\TestCase;
+
+/**
+ * @internal
+ * @coversNothing
+ */
+class ExampleTest extends TestCase
+{
+    public function testTheApplicationReturnsSuccessfulResponse()
+    {
+        $this->get('/')
+            ->assertSuccessful();
+    }
+}

+ 39 - 0
frameworks/PHP/hypervel/tests/Feature/RefreshDatabaseTest.php

@@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Tests\Feature;
+
+use App\Models\User;
+use Hypervel\Foundation\Testing\RefreshDatabase;
+use Tests\TestCase;
+
+/**
+ * @internal
+ * @coversNothing
+ */
+class RefreshDatabaseTest extends TestCase
+{
+    use RefreshDatabase;
+
+    public function testCreateUser()
+    {
+        $user = factory(User::class)->create();
+
+        $this->assertDatabaseHas('users', [
+            'id' => $user->id,
+        ]);
+    }
+
+    public function testCreateMultipleUsers()
+    {
+        factory(User::class, $count = 5)->create();
+
+        $this->assertDatabaseCount('users', $count);
+    }
+
+    public function testZeroUserAfterRefresh()
+    {
+        $this->assertSame(0, User::count());
+    }
+}

+ 13 - 0
frameworks/PHP/hypervel/tests/TestCase.php

@@ -0,0 +1,13 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Tests;
+
+use Hypervel\Foundation\Testing\Concerns\RunTestsInCoroutine;
+use Hypervel\Foundation\Testing\TestCase as BaseTestCase;
+
+abstract class TestCase extends BaseTestCase
+{
+    use RunTestsInCoroutine;
+}

+ 22 - 0
frameworks/PHP/hypervel/tests/Unit/ExampleTest.php

@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Tests\Unit;
+
+use Hypervel\Foundation\Testing\TestCase;
+
+/**
+ * @internal
+ * @coversNothing
+ */
+class ExampleTest extends TestCase
+{
+    /**
+     * A basic test example.
+     */
+    public function testThatTrueIsTrue(): void
+    {
+        $this->assertTrue(true);
+    }
+}

+ 38 - 0
frameworks/PHP/hypervel/tests/bootstrap.php

@@ -0,0 +1,38 @@
+<?php
+
+declare(strict_types=1);
+
+use Hypervel\Foundation\Testing\TestScanHandler;
+
+ini_set('display_errors', 'on');
+ini_set('display_startup_errors', 'on');
+
+error_reporting(E_ALL);
+
+! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);
+
+$dir = __DIR__;
+$lastDir = '';
+if (! defined('BASE_PATH')) {
+    while (! file_exists($dir . '/composer.json') && $dir !== dirname($dir)) {
+        if ($lastDir === $dir) {
+            break;
+        }
+        $lastDir = $dir;
+        $dir = dirname($dir);
+    }
+}
+
+if (! file_exists($dir . '/composer.json')) {
+    throw new RuntimeException('Unable to find base path (directory with composer.json)');
+}
+
+define('BASE_PATH', $dir);
+
+require BASE_PATH . '/vendor/autoload.php';
+
+Hypervel\Foundation\ClassLoader::init(null, null, new TestScanHandler());
+
+$app = require BASE_PATH . '/bootstrap/app.php';
+
+$app->get(Hyperf\Contract\ApplicationInterface::class);

+ 15 - 0
frameworks/PHP/hypervel/tests/helpers.php

@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+use Hyperf\Testing\ModelFactory;
+use Hypervel\Context\ApplicationContext;
+
+if (! function_exists('factory')) {
+    function factory(string $class, mixed ...$arguments)
+    {
+        return ApplicationContext::getContainer()
+            ->get(ModelFactory::class)
+            ->factory($class, ...$arguments);
+    }
+}