diff --git a/.devcontainer/cli/Dockerfile b/.devcontainer/cli/Dockerfile index d2c44b1..908acef 100644 --- a/.devcontainer/cli/Dockerfile +++ b/.devcontainer/cli/Dockerfile @@ -1,5 +1,5 @@ # From official php image. -FROM php:8.4-cli-alpine +FROM php:8.3-cli-alpine # Create a user group and account under id 1000. RUN addgroup -g 1000 -S user && adduser -u 1000 -D user -G user # Install quality-of-life packages. @@ -9,27 +9,21 @@ RUN apk add --no-cache composer # Add Chromium and Image Magick for puppeteer. RUN apk add --no-cache \ imagemagick-dev \ - chromium \ - libzip-dev \ - freetype-dev \ - libpng-dev \ - libjpeg-turbo-dev + chromium ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium ENV PUPPETEER_DOCKER=1 RUN mkdir -p /usr/src/php/ext/imagick RUN chmod 777 /usr/src/php/ext/imagick -RUN curl -fsSL https://github.com/Imagick/imagick/archive/refs/tags/3.8.0.tar.gz | tar xvz -C "/usr/src/php/ext/imagick" --strip 1 - -RUN docker-php-ext-configure gd --with-freetype --with-jpeg +RUN curl -fsSL https://github.com/Imagick/imagick/archive/refs/tags/3.7.0.tar.gz | tar xvz -C "/usr/src/php/ext/imagick" --strip 1 # Install PHP extensions -RUN docker-php-ext-install imagick zip gd +RUN docker-php-ext-install imagick # Composer uses its php binary, but we want it to use the container's one -RUN rm -f /usr/bin/php84 -RUN ln -s /usr/local/bin/php /usr/bin/php84 +RUN rm -f /usr/bin/php83 +RUN ln -s /usr/local/bin/php /usr/bin/php83 # Install postgres pdo driver. # RUN apk add --no-cache postgresql-dev && docker-php-ext-install pdo_pgsql # Install redis driver. diff --git a/.devcontainer/fpm/Dockerfile b/.devcontainer/fpm/Dockerfile index d8ce6cc..b9770e3 100644 --- a/.devcontainer/fpm/Dockerfile +++ b/.devcontainer/fpm/Dockerfile @@ -1,5 +1,5 @@ # From official php image. -FROM php:8.4-fpm-alpine +FROM php:8.3-fpm-alpine RUN addgroup -g 1000 -S user && adduser -u 1000 -D user -G user # Install postgres pdo driver. # RUN apk add --no-cache postgresql-dev && docker-php-ext-install pdo_pgsql @@ -14,24 +14,17 @@ RUN apk add --no-cache \ nodejs \ npm \ imagemagick-dev \ - chromium \ - libzip-dev \ - freetype-dev \ - libpng-dev \ - libjpeg-turbo-dev - + chromium ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium ENV PUPPETEER_DOCKER=1 RUN mkdir -p /usr/src/php/ext/imagick RUN chmod 777 /usr/src/php/ext/imagick -RUN curl -fsSL https://github.com/Imagick/imagick/archive/refs/tags/3.8.0.tar.gz | tar xvz -C "/usr/src/php/ext/imagick" --strip 1 - -RUN docker-php-ext-configure gd --with-freetype --with-jpeg +RUN curl -fsSL https://github.com/Imagick/imagick/archive/refs/tags/3.7.0.tar.gz | tar xvz -C "/usr/src/php/ext/imagick" --strip 1 # Install PHP extensions -RUN docker-php-ext-install imagick zip gd +RUN docker-php-ext-install imagick -RUN rm -f /usr/bin/php84 -RUN ln -s /usr/local/bin/php /usr/bin/php84 +RUN rm -f /usr/bin/php83 +RUN ln -s /usr/local/bin/php /usr/bin/php83 diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index a4ff129..048db51 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -42,7 +42,8 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | - type=semver,pattern={{version}} + type=ref,event=tag + latest - name: Build and push Docker image uses: docker/build-push-action@v6 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 78e4fbb..fd03705 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,7 +22,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.4 + php-version: 8.3 coverage: xdebug - name: Setup Node diff --git a/.gitignore b/.gitignore index 0eb46d3..33806df 100644 --- a/.gitignore +++ b/.gitignore @@ -22,18 +22,3 @@ yarn-error.log /.vscode /.zed /database/seeders/PersonalDeviceSeeder.php -/.junie/mcp/mcp.json -/.cursor/mcp.json -/.cursor/rules/laravel-boost.mdc -/.github/copilot-instructions.md -/.junie/guidelines.md -/CLAUDE.md -/.mcp.json -/.ai -.DS_Store -/boost.json -/.gemini -/GEMINI.md -/.claude -/AGENTS.md -/opencode.json diff --git a/Dockerfile b/Dockerfile index 2d761ed..6a9931d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ ######################## # Base Image ######################## -FROM bnussbau/serversideup-php:8.4-fpm-nginx-alpine-imagick-chromium@sha256:52ac545fdb57b2ab7568b1c7fc0a98cb1a69a275d8884249778a80914272fa48 AS base +FROM bnussbau/serversideup-php:8.3-fpm-nginx-alpine-imagick-chromium AS base LABEL org.opencontainers.image.source=https://github.com/usetrmnl/byos_laravel LABEL org.opencontainers.image.description="TRMNL BYOS Laravel" @@ -12,14 +12,9 @@ ENV APP_VERSION=${APP_VERSION} ENV AUTORUN_ENABLED="true" -# Mark trmnl-liquid-cli as installed -ENV TRMNL_LIQUID_ENABLED=1 - # Switch to the root user so we can do root things USER root -COPY --chown=www-data:www-data --from=bnussbau/trmnl-liquid-cli:0.1.0 /usr/local/bin/trmnl-liquid-cli /usr/local/bin/ - # Set the working directory WORKDIR /var/www/html @@ -53,5 +48,6 @@ FROM base AS production # Copy the assets from the assets image COPY --chown=www-data:www-data --from=assets /app/public/build /var/www/html/public/build COPY --chown=www-data:www-data --from=assets /app/node_modules /var/www/html/node_modules + # Drop back to the www-data user USER www-data diff --git a/README.md b/README.md index acb0b5c..95ed5c8 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,9 @@ [![tests](https://github.com/usetrmnl/byos_laravel/actions/workflows/test.yml/badge.svg)](https://github.com/usetrmnl/byos_laravel/actions/workflows/test.yml) TRMNL BYOS Laravel is a self-hostable implementation of a TRMNL server, built with Laravel. -It allows you to manage TRMNL devices, generate screens using **native plugins** (Screens API, Markup), **recipes** (120+ from the [OSS community catalog](https://bnussbau.github.io/trmnl-recipe-catalog/), 600+ from the [TRMNL catalog](https://usetrmnl.com/recipes), or your own), or the **API**, and can also act as a **proxy** for the native cloud service (Core). With over 40k downloads and 160+ stars, it’s the most popular community-driven BYOS. +It enables you to manage TRMNL devices, generate screens dynamically, and can act as a proxy for the native cloud service (native plugins, recipes). + +If you are looking for a Laravel package designed to streamline the development of both public and private TRMNL plugins, check out [bnussbau/trmnl-laravel](https://github.com/bnussbau/laravel-trmnl). ![Screenshot](README_byos-screenshot.png) ![Screenshot](README_byos-screenshot-dark.png) @@ -14,32 +16,21 @@ It allows you to manage TRMNL devices, generate screens using **native plugins** * πŸ“‘ Device Information – Display battery status, WiFi strength, firmware version, and more. * πŸ” Auto-Join – Automatically detects and adds devices from your local network. -* πŸ–₯️ Screen Generation – Supports Plugins (including Mashups), Recipes, API, Markup, or updates via Code. - * Support for TRMNL [Design Framework](https://usetrmnl.com/framework) - * Compatible open-source recipes are available in the [community catalog](https://bnussbau.github.io/trmnl-recipe-catalog/) - * Import from the [TRMNL community recipe catalog](https://usetrmnl.com/recipes) - * Supported Devices - * TRMNL OG (1-bit & 2-bit) - * SeeedStudio TRMNL 7,5" (OG) DIY Kit - * Seeed Studio (XIAO 7.5" ePaper Panel) - * reTerminal E1001 Monochrome ePaper Display - * Custom ESP32 with TRMNL firmware - * E-Reader Devices - * KOReader ([trmnl-koreader](https://github.com/usetrmnl/trmnl-koreader)) - * Kindle ([trmnl-kindle](https://github.com/usetrmnl/byos_laravel/pull/27)) - * Nook ([trmnl-nook](https://github.com/usetrmnl/trmnl-nook)) - * Kobo ([trmnl-kobo](https://github.com/usetrmnl/trmnl-kobo)) - * Android Devices with [trmnl-android](https://github.com/usetrmnl/trmnl-android) - * Raspberry Pi (HDMI output) [trmnl-display](https://github.com/usetrmnl/trmnl-display) +* πŸ–₯️ Screen Generation – Supports Plugins (even Mashups), Recipes, API, Markup, or updates via Code. + * Supported Devices / Apps: TRMNL, ESP32 with TRMNL firmware, [trmnl-android](https://github.com/usetrmnl/trmnl-android), [trmnl-kindle](https://github.com/usetrmnl/byos_laravel/pull/27), … * πŸ”„ TRMNL API Proxy – Can act as a proxy for the native cloud service (requires TRMNL Developer Edition). * This enables a hybrid setup – for example, you can update your custom Train Monitor every 5 minutes in the morning, while displaying native TRMNL plugins throughout the day. * πŸŒ™ Dark Mode – Switch between light and dark mode. * 🐳 Deployment – Dockerized setup for easier hosting (Dockerfile, docker-compose). -* πŸ’Ύ Flexible Database configuration – uses SQLite by default, also compatible with MySQL or PostgreSQL * πŸ› οΈ Devcontainer support for easier development. ![Devices](README_byos-devices.jpeg) +### 🎯 Target Audience + +This project is for developers who are looking for a self-hosted server for devices running the TRMNL firmware. +It serves as a starter kit, giving you the flexibility to build and extend it however you like. + ### Support ❀️ This repo is maintained voluntarily by [@bnussbau](https://github.com/bnussbau). @@ -49,8 +40,6 @@ or [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/bnussbau) -[GitHub Sponsors](https://github.com/sponsors/bnussbau/) - ### Hosting Run everywhere, where Docker is supported: Raspberry Pi, VPS, NAS, Container Cloud Service (Cloud Run, ...). @@ -76,12 +65,9 @@ docker compose up -d If you’re using a VPS (e.g., Hetzner) and prefer an alternative to native Docker, you can install Dokploy and deploy BYOS Laravel using the integrated [Template](https://templates.dokploy.com/?q=trmnl+byos+laravel). It’s a quick way to get started without having to manually manage Docker setup. -#### PikaPods +### PikaPods You can vote for TRMNL BYOS Laravel to be included as PikaPods Template here: [feedback.pikapods.com](https://feedback.pikapods.com/posts/842/add-app-trmnl-byos-laravel) -#### Umbrel -Umbrel is supported through a community store, [see](http://github.com/bnussbau/umbrel-store). - #### Other Hosting Options Laravel Forge, or bare metal PHP server with Nginx or Apache is also supported. @@ -124,7 +110,6 @@ php artisan db:seed --class=ExampleRecipesSeeder | `FORCE_HTTPS` | If your server handles SSL termination, enforce HTTPS. | 0 | | `PHP_OPCACHE_ENABLE` | Enable PHP Opcache | 0 | | `TRMNL_IMAGE_URL_TIMEOUT` | How long TRMNL waits for a response on the display endpoint. (sec) | 30 | -| `APP_TIMEZONE` | Default timezone, which will be used by the PHP date functions | UTC | #### Login @@ -218,12 +203,6 @@ You can dynamically update screens by sending a POST request. } ``` -### Releated Work -* [bnussbau/laravel-trmnl-blade](https://github.com/bnussbau/laravel-trmnl-blade) – Blade Components on top of the TRMNL Design System -* [bnussbau/trmnl-pipeline-php](https://github.com/bnussbau/trmnl-pipeline-php) – Browser Rendering and Image Conversion Pipeline with support for TRMNL Models API -* [bnussbau/trmnl-recipe-catalog](https://github.com/bnussbau/trmnl-recipe-catalog) – A community-driven catalog of public repositories containing trmnlp-compatible recipes. - - ### 🀝 Contribution Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details. diff --git a/app/Actions/Fortify/CreateNewUser.php b/app/Actions/Fortify/CreateNewUser.php deleted file mode 100644 index 3c7c00c..0000000 --- a/app/Actions/Fortify/CreateNewUser.php +++ /dev/null @@ -1,33 +0,0 @@ - $input - */ - public function create(array $input): User - { - Validator::make($input, [ - ...$this->profileRules(), - 'password' => $this->passwordRules(), - ])->validate(); - - return User::create([ - 'name' => $input['name'], - 'email' => $input['email'], - 'password' => $input['password'], - ]); - } -} diff --git a/app/Actions/Fortify/ResetUserPassword.php b/app/Actions/Fortify/ResetUserPassword.php deleted file mode 100644 index 8fda5dd..0000000 --- a/app/Actions/Fortify/ResetUserPassword.php +++ /dev/null @@ -1,29 +0,0 @@ - $input - */ - public function reset(User $user, array $input): void - { - Validator::make($input, [ - 'password' => $this->passwordRules(), - ])->validate(); - - $user->forceFill([ - 'password' => $input['password'], - ])->save(); - } -} diff --git a/app/Concerns/PasswordValidationRules.php b/app/Concerns/PasswordValidationRules.php deleted file mode 100644 index 9b45ef0..0000000 --- a/app/Concerns/PasswordValidationRules.php +++ /dev/null @@ -1,28 +0,0 @@ -|string> - */ - protected function passwordRules(): array - { - return ['required', 'string', Password::default(), 'confirmed']; - } - - /** - * Get the validation rules used to validate the current password. - * - * @return array|string> - */ - protected function currentPasswordRules(): array - { - return ['required', 'string', 'current_password']; - } -} diff --git a/app/Concerns/ProfileValidationRules.php b/app/Concerns/ProfileValidationRules.php deleted file mode 100644 index 46e19ba..0000000 --- a/app/Concerns/ProfileValidationRules.php +++ /dev/null @@ -1,50 +0,0 @@ -|string>> - */ - protected function profileRules(?int $userId = null): array - { - return [ - 'name' => $this->nameRules(), - 'email' => $this->emailRules($userId), - ]; - } - - /** - * Get the validation rules used to validate user names. - * - * @return array|string> - */ - protected function nameRules(): array - { - return ['required', 'string', 'max:255']; - } - - /** - * Get the validation rules used to validate user emails. - * - * @return array|string> - */ - protected function emailRules(?int $userId = null): array - { - return [ - 'required', - 'string', - 'email', - 'max:255', - $userId === null - ? Rule::unique(User::class) - : Rule::unique(User::class)->ignore($userId), - ]; - } -} diff --git a/app/Console/Commands/FetchDeviceModelsCommand.php b/app/Console/Commands/FetchDeviceModelsCommand.php deleted file mode 100644 index 78dd02a..0000000 --- a/app/Console/Commands/FetchDeviceModelsCommand.php +++ /dev/null @@ -1,46 +0,0 @@ -info('Dispatching FetchDeviceModelsJob...'); - - try { - FetchDeviceModelsJob::dispatchSync(); - - $this->info('FetchDeviceModelsJob has been dispatched successfully.'); - - return self::SUCCESS; - } catch (Exception $e) { - $this->error('Failed to dispatch FetchDeviceModelsJob: '.$e->getMessage()); - - return self::FAILURE; - } - } -} diff --git a/app/Console/Commands/FirmwareCheckCommand.php b/app/Console/Commands/FirmwareCheckCommand.php index 91922ba..f407314 100644 --- a/app/Console/Commands/FirmwareCheckCommand.php +++ b/app/Console/Commands/FirmwareCheckCommand.php @@ -23,7 +23,7 @@ class FirmwareCheckCommand extends Command ); $latestFirmware = Firmware::getLatest(); - if ($latestFirmware instanceof Firmware) { + if ($latestFirmware) { table( rows: [ ['Latest Version', $latestFirmware->version_tag], diff --git a/app/Console/Commands/FirmwareUpdateCommand.php b/app/Console/Commands/FirmwareUpdateCommand.php index bd43786..97d9d58 100644 --- a/app/Console/Commands/FirmwareUpdateCommand.php +++ b/app/Console/Commands/FirmwareUpdateCommand.php @@ -42,14 +42,15 @@ class FirmwareUpdateCommand extends Command label: 'Which devices should be updated?', options: [ 'all' => 'ALL Devices', - ...Device::all()->mapWithKeys(fn ($device): array => + ...Device::all()->mapWithKeys(function ($device) { // without _ returns index - ["_$device->id" => "$device->name (Current version: $device->last_firmware_version)"])->toArray(), + return ["_$device->id" => "$device->name (Current version: $device->last_firmware_version)"]; + })->toArray(), ], scroll: 10 ); - if ($devices === []) { + if (empty($devices)) { $this->error('No devices selected. Aborting.'); return; @@ -58,7 +59,9 @@ class FirmwareUpdateCommand extends Command if (in_array('all', $devices)) { $devices = Device::pluck('id')->toArray(); } else { - $devices = array_map(fn ($selected): int => (int) str_replace('_', '', $selected), $devices); + $devices = array_map(function ($selected) { + return (int) str_replace('_', '', $selected); + }, $devices); } foreach ($devices as $deviceId) { diff --git a/app/Console/Commands/GenerateDefaultImagesCommand.php b/app/Console/Commands/GenerateDefaultImagesCommand.php deleted file mode 100644 index e2887df..0000000 --- a/app/Console/Commands/GenerateDefaultImagesCommand.php +++ /dev/null @@ -1,201 +0,0 @@ -info('Starting generation of default images for all device models...'); - - $deviceModels = DeviceModel::all(); - - if ($deviceModels->isEmpty()) { - $this->warn('No device models found in the database.'); - - return self::SUCCESS; - } - - $this->info("Found {$deviceModels->count()} device models to process."); - - // Create the target directory - $targetDir = 'images/default-screens'; - if (! Storage::disk('public')->exists($targetDir)) { - Storage::disk('public')->makeDirectory($targetDir); - $this->info("Created directory: {$targetDir}"); - } - - $successCount = 0; - $skipCount = 0; - $errorCount = 0; - - foreach ($deviceModels as $deviceModel) { - $this->info("Processing device model: {$deviceModel->label} (ID: {$deviceModel->id})"); - - try { - // Process setup-logo - $setupResult = $this->transformImage('setup-logo', $deviceModel, $targetDir); - if ($setupResult) { - ++$successCount; - } else { - ++$skipCount; - } - - // Process sleep - $sleepResult = $this->transformImage('sleep', $deviceModel, $targetDir); - if ($sleepResult) { - ++$successCount; - } else { - ++$skipCount; - } - - } catch (Exception $e) { - $this->error("Error processing device model {$deviceModel->label}: ".$e->getMessage()); - ++$errorCount; - } - } - - $this->info("\nGeneration completed!"); - $this->info("Successfully processed: {$successCount} images"); - $this->info("Skipped (already exist): {$skipCount} images"); - $this->info("Errors: {$errorCount} images"); - - return self::SUCCESS; - } - - /** - * Transform a single image for a device model using Blade templates - */ - private function transformImage(string $imageType, DeviceModel $deviceModel, string $targetDir): bool - { - // Generate filename: {width}_{height}_{bit_depth}_{rotation}.{extension} - $extension = $deviceModel->mime_type === 'image/bmp' ? 'bmp' : 'png'; - $filename = "{$deviceModel->width}_{$deviceModel->height}_{$deviceModel->bit_depth}_{$deviceModel->rotation}.{$extension}"; - $targetPath = "{$targetDir}/{$imageType}_{$filename}"; - - // Check if target already exists and force is not set - if (Storage::disk('public')->exists($targetPath) && ! $this->option('force')) { - $this->line(" Skipping {$imageType} - already exists: {$filename}"); - - return false; - } - - try { - // Create custom Browsershot instance if using AWS Lambda - $browsershotInstance = null; - if (config('app.puppeteer_mode') === 'sidecar-aws') { - $browsershotInstance = new BrowsershotLambda(); - } - - // Generate HTML from Blade template - $html = $this->generateHtmlFromTemplate($imageType, $deviceModel); - // dump($html); - - $browserStage = new BrowserStage($browsershotInstance); - $browserStage->html($html); - - // Set timezone from app config (no user context in this command) - $browserStage->timezone(config('app.timezone')); - - $browserStage - ->width($deviceModel->width) - ->height($deviceModel->height); - - $browserStage->setBrowsershotOption('waitUntil', 'networkidle0'); - - if (config('app.puppeteer_docker')) { - $browserStage->setBrowsershotOption('args', ['--no-sandbox', '--disable-setuid-sandbox', '--disable-gpu']); - } - - $outputPath = Storage::disk('public')->path($targetPath); - - $imageStage = new ImageStage(); - $imageStage->format($extension) - ->width($deviceModel->width) - ->height($deviceModel->height) - ->colors($deviceModel->colors) - ->bitDepth($deviceModel->bit_depth) - ->rotation($deviceModel->rotation) - // ->offsetX($deviceModel->offset_x) - // ->offsetY($deviceModel->offset_y) - ->outputPath($outputPath); - - (new TrmnlPipeline())->pipe($browserStage) - ->pipe($imageStage) - ->process(); - - if (! file_exists($outputPath)) { - throw new RuntimeException('Image file was not created: '.$outputPath); - } - - if (filesize($outputPath) === 0) { - throw new RuntimeException('Image file is empty: '.$outputPath); - } - - $this->line(" βœ“ Generated {$imageType}: {$filename}"); - - return true; - - } catch (Exception $e) { - $this->error(" βœ— Failed to generate {$imageType} for {$deviceModel->label}: ".$e->getMessage()); - - return false; - } - } - - /** - * Generate HTML from Blade template for the given image type and device model - */ - private function generateHtmlFromTemplate(string $imageType, DeviceModel $deviceModel): string - { - // Map image type to template name - $templateName = match ($imageType) { - 'setup-logo' => 'default-screens.setup', - 'sleep' => 'default-screens.sleep', - default => throw new InvalidArgumentException("Invalid image type: {$imageType}") - }; - - // Determine device properties from DeviceModel - $deviceVariant = $deviceModel->name ?? 'og'; - $colorDepth = $deviceModel->color_depth ?? '1bit'; // Use the accessor method - $scaleLevel = $deviceModel->scale_level; // Use the accessor method - $darkMode = $imageType === 'sleep'; // Sleep mode uses dark mode, setup uses light mode - - // Render the Blade template - return view($templateName, [ - 'noBleed' => false, - 'darkMode' => $darkMode, - 'deviceVariant' => $deviceVariant, - 'colorDepth' => $colorDepth, - 'scaleLevel' => $scaleLevel, - ])->render(); - } -} diff --git a/app/Console/Commands/MashupCreateCommand.php b/app/Console/Commands/MashupCreateCommand.php index 7201274..d6f1378 100644 --- a/app/Console/Commands/MashupCreateCommand.php +++ b/app/Console/Commands/MashupCreateCommand.php @@ -9,6 +9,9 @@ use App\Models\Plugin; use Illuminate\Console\Command; use Illuminate\Support\Collection; +use function Laravel\Prompts\select; +use function Laravel\Prompts\text; + class MashupCreateCommand extends Command { /** @@ -28,17 +31,17 @@ class MashupCreateCommand extends Command /** * Execute the console command. */ - public function handle(): int + public function handle() { // Select device $device = $this->selectDevice(); - if (! $device instanceof Device) { + if (! $device) { return 1; } // Select playlist $playlist = $this->selectPlaylist($device); - if (! $playlist instanceof Playlist) { + if (! $playlist) { return 1; } @@ -85,9 +88,9 @@ class MashupCreateCommand extends Command return null; } - $deviceId = $this->choice( - 'Select a device', - $devices->mapWithKeys(fn ($device): array => [$device->id => $device->name])->toArray() + $deviceId = select( + label: 'Select a device', + options: $devices->mapWithKeys(fn ($device) => [$device->id => $device->name])->toArray() ); return $devices->firstWhere('id', $deviceId); @@ -103,9 +106,9 @@ class MashupCreateCommand extends Command return null; } - $playlistId = $this->choice( - 'Select a playlist', - $playlists->mapWithKeys(fn (Playlist $playlist): array => [$playlist->id => $playlist->name])->toArray() + $playlistId = select( + label: 'Select a playlist', + options: $playlists->mapWithKeys(fn (Playlist $playlist) => [$playlist->id => $playlist->name])->toArray() ); return $playlists->firstWhere('id', $playlistId); @@ -113,29 +116,24 @@ class MashupCreateCommand extends Command protected function selectLayout(): ?string { - return $this->choice( - 'Select a layout', - PlaylistItem::getAvailableLayouts() + return select( + label: 'Select a layout', + options: PlaylistItem::getAvailableLayouts() ); } protected function getMashupName(): ?string { - $name = $this->ask('Enter a name for this mashup', 'Mashup'); - - if (mb_strlen((string) $name) < 2) { - $this->error('The name must be at least 2 characters.'); - - return null; - } - - if (mb_strlen((string) $name) > 50) { - $this->error('The name must not exceed 50 characters.'); - - return null; - } - - return $name; + return text( + label: 'Enter a name for this mashup', + required: true, + default: 'Mashup', + validate: fn (string $value) => match (true) { + mb_strlen($value) < 1 => 'The name must be at least 2 characters.', + mb_strlen($value) > 50 => 'The name must not exceed 50 characters.', + default => null, + } + ); } protected function selectPlugins(string $layout): Collection @@ -150,7 +148,7 @@ class MashupCreateCommand extends Command } $selectedPlugins = collect(); - $availablePlugins = $plugins->mapWithKeys(fn ($plugin): array => [$plugin->id => $plugin->name])->toArray(); + $availablePlugins = $plugins->mapWithKeys(fn ($plugin) => [$plugin->id => $plugin->name])->toArray(); for ($i = 0; $i < $requiredCount; ++$i) { $position = match ($i) { @@ -161,9 +159,9 @@ class MashupCreateCommand extends Command default => ($i + 1).'th' }; - $pluginId = $this->choice( - "Select the $position plugin", - $availablePlugins + $pluginId = select( + label: "Select the $position plugin", + options: $availablePlugins ); $selectedPlugins->push($plugins->firstWhere('id', $pluginId)); diff --git a/app/Console/Commands/OidcTestCommand.php b/app/Console/Commands/OidcTestCommand.php deleted file mode 100644 index 81dff0b..0000000 --- a/app/Console/Commands/OidcTestCommand.php +++ /dev/null @@ -1,104 +0,0 @@ -info('Testing OIDC Configuration...'); - $this->newLine(); - - // Check if OIDC is enabled - $enabled = config('services.oidc.enabled'); - $this->line('OIDC Enabled: '.($enabled ? 'βœ… Yes' : '❌ No')); - - // Check configuration values - $endpoint = config('services.oidc.endpoint'); - $clientId = config('services.oidc.client_id'); - $clientSecret = config('services.oidc.client_secret'); - $redirect = config('services.oidc.redirect'); - if (! $redirect) { - $redirect = config('app.url', 'http://localhost').'/auth/oidc/callback'; - } - $scopes = config('services.oidc.scopes', []); - $defaultScopes = ['openid', 'profile', 'email']; - $effectiveScopes = empty($scopes) ? $defaultScopes : $scopes; - - $this->line('OIDC Endpoint: '.($endpoint ? "βœ… {$endpoint}" : '❌ Not set')); - $this->line('Client ID: '.($clientId ? "βœ… {$clientId}" : '❌ Not set')); - $this->line('Client Secret: '.($clientSecret ? 'βœ… Set' : '❌ Not set')); - $this->line('Redirect URL: '.($redirect ? "βœ… {$redirect}" : '❌ Not set')); - $this->line('Scopes: βœ… '.implode(', ', $effectiveScopes)); - - $this->newLine(); - - // Test driver registration - try { - // Only test driver if we have basic configuration - if ($endpoint && $clientId && $clientSecret) { - $driver = Socialite::driver('oidc'); - $this->line('OIDC Driver: βœ… Successfully registered and accessible'); - - if ($enabled) { - $this->info('βœ… OIDC is fully configured and ready to use!'); - $this->line('You can test the login flow at: /auth/oidc/redirect'); - } else { - $this->warn('⚠️ OIDC driver is working but OIDC_ENABLED is false.'); - } - } else { - $this->line('OIDC Driver: βœ… Registered (configuration test skipped due to missing values)'); - $this->warn('⚠️ OIDC driver is registered but missing required configuration.'); - $this->line('Please set the following environment variables:'); - if (! $enabled) { - $this->line(' - OIDC_ENABLED=true'); - } - if (! $endpoint) { - $this->line(' - OIDC_ENDPOINT=https://your-oidc-provider.com (base URL)'); - $this->line(' OR'); - $this->line(' - OIDC_ENDPOINT=https://your-oidc-provider.com/.well-known/openid-configuration (full URL)'); - } - if (! $clientId) { - $this->line(' - OIDC_CLIENT_ID=your-client-id'); - } - if (! $clientSecret) { - $this->line(' - OIDC_CLIENT_SECRET=your-client-secret'); - } - } - } catch (InvalidArgumentException $e) { - if (str_contains($e->getMessage(), 'Driver [oidc] not supported')) { - $this->error('❌ OIDC Driver registration failed: Driver not supported'); - } else { - $this->error('❌ OIDC Driver error: '.$e->getMessage()); - } - } catch (Exception $e) { - $this->warn('⚠️ OIDC Driver registered but configuration error: '.$e->getMessage()); - } - - $this->newLine(); - - return Command::SUCCESS; - } -} diff --git a/app/Console/Commands/ScreenGeneratorCommand.php b/app/Console/Commands/ScreenGeneratorCommand.php index c0a2cc3..ac74fba 100644 --- a/app/Console/Commands/ScreenGeneratorCommand.php +++ b/app/Console/Commands/ScreenGeneratorCommand.php @@ -25,7 +25,7 @@ class ScreenGeneratorCommand extends Command /** * Execute the console command. */ - public function handle(): int + public function handle() { $deviceId = $this->argument('deviceId'); $view = $this->argument('view'); diff --git a/app/Enums/ImageFormat.php b/app/Enums/ImageFormat.php index 67e9b79..75a7307 100644 --- a/app/Enums/ImageFormat.php +++ b/app/Enums/ImageFormat.php @@ -8,7 +8,6 @@ enum ImageFormat: string case PNG_8BIT_GRAYSCALE = 'png_8bit_grayscale'; case BMP3_1BIT_SRGB = 'bmp3_1bit_srgb'; case PNG_8BIT_256C = 'png_8bit_256c'; - case PNG_2BIT_4C = 'png_2bit_4c'; public function label(): string { @@ -17,7 +16,6 @@ enum ImageFormat: string self::PNG_8BIT_GRAYSCALE => 'PNG 8-bit Grayscale Gray 2c', self::BMP3_1BIT_SRGB => 'BMP3 1-bit sRGB 2c', self::PNG_8BIT_256C => 'PNG 8-bit Grayscale Gray 256c', - self::PNG_2BIT_4C => 'PNG 2-bit Grayscale 4c', }; } } diff --git a/app/Facades/QrCode.php b/app/Facades/QrCode.php deleted file mode 100644 index 00de934..0000000 --- a/app/Facades/QrCode.php +++ /dev/null @@ -1,24 +0,0 @@ -route('login')->withErrors(['oidc' => 'OIDC authentication is not enabled.']); - } - - // Check if all required OIDC configuration is present - $requiredConfig = ['endpoint', 'client_id', 'client_secret']; - foreach ($requiredConfig as $key) { - if (! config("services.oidc.{$key}")) { - Log::error("OIDC configuration missing: {$key}"); - - return redirect()->route('login')->withErrors(['oidc' => 'OIDC is not properly configured.']); - } - } - - try { - return Socialite::driver('oidc')->redirect(); - } catch (Exception $e) { - Log::error('OIDC redirect error: '.$e->getMessage()); - - return redirect()->route('login')->withErrors(['oidc' => 'Failed to initiate OIDC authentication.']); - } - } - - /** - * Obtain the user information from the OIDC provider. - */ - public function callback(Request $request) - { - if (! config('services.oidc.enabled')) { - return redirect()->route('login')->withErrors(['oidc' => 'OIDC authentication is not enabled.']); - } - - // Check if all required OIDC configuration is present - $requiredConfig = ['endpoint', 'client_id', 'client_secret']; - foreach ($requiredConfig as $key) { - if (! config("services.oidc.{$key}")) { - Log::error("OIDC configuration missing: {$key}"); - - return redirect()->route('login')->withErrors(['oidc' => 'OIDC is not properly configured.']); - } - } - - try { - $oidcUser = Socialite::driver('oidc')->user(); - - // Find or create the user - $user = $this->findOrCreateUser($oidcUser); - - // Log the user in - Auth::login($user, true); - - return redirect()->intended(route('dashboard', absolute: false)); - - } catch (Exception $e) { - Log::error('OIDC callback error: '.$e->getMessage()); - - return redirect()->route('login')->withErrors(['oidc' => 'Failed to authenticate with OIDC provider.']); - } - } - - /** - * Find or create a user based on OIDC information. - */ - protected function findOrCreateUser($oidcUser) - { - // First, try to find user by OIDC subject ID - $user = User::where('oidc_sub', $oidcUser->getId())->first(); - - if ($user) { - // Update user information from OIDC - $user->update([ - 'name' => $oidcUser->getName() ?: $user->name, - 'email' => $oidcUser->getEmail() ?: $user->email, - ]); - - return $user; - } - - // If not found by OIDC sub, try to find by email - if ($oidcUser->getEmail()) { - $user = User::where('email', $oidcUser->getEmail())->first(); - - if ($user) { - // Link the existing user with OIDC - $user->update([ - 'oidc_sub' => $oidcUser->getId(), - 'name' => $oidcUser->getName() ?: $user->name, - ]); - - return $user; - } - } - - // Create new user - return User::create([ - 'oidc_sub' => $oidcUser->getId(), - 'name' => $oidcUser->getName() ?: 'OIDC User', - 'email' => $oidcUser->getEmail() ?: $oidcUser->getId().'@oidc.local', - 'password' => bcrypt(Str::random(32)), // Random password since we're using OIDC - 'email_verified_at' => now(), // OIDC users are considered verified - ]); - } -} diff --git a/app/Jobs/CleanupDeviceLogsJob.php b/app/Jobs/CleanupDeviceLogsJob.php index d2f1dd9..b49f507 100644 --- a/app/Jobs/CleanupDeviceLogsJob.php +++ b/app/Jobs/CleanupDeviceLogsJob.php @@ -18,7 +18,7 @@ class CleanupDeviceLogsJob implements ShouldQueue */ public function handle(): void { - Device::each(function ($device): void { + Device::each(function ($device) { $keepIds = $device->logs()->latest('device_timestamp')->take(50)->pluck('id'); // Delete all other logs for this device diff --git a/app/Jobs/FetchDeviceModelsJob.php b/app/Jobs/FetchDeviceModelsJob.php deleted file mode 100644 index 475c5c7..0000000 --- a/app/Jobs/FetchDeviceModelsJob.php +++ /dev/null @@ -1,247 +0,0 @@ -processPalettes(); - - $response = Http::timeout(30)->get(self::API_URL); - - if (! $response->successful()) { - Log::error('Failed to fetch device models from API', [ - 'status' => $response->status(), - 'body' => $response->body(), - ]); - - return; - } - - $data = $response->json('data', []); - - if (! is_array($data)) { - Log::error('Invalid response format from device models API', [ - 'response' => $response->json(), - ]); - - return; - } - - $this->processDeviceModels($data); - - Log::info('Successfully fetched and updated device models', [ - 'count' => count($data), - ]); - - } catch (Exception $e) { - Log::error('Exception occurred while fetching device models', [ - 'message' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), - ]); - } - } - - /** - * Process palettes from API and update/create records. - */ - private function processPalettes(): void - { - try { - $response = Http::timeout(30)->get(self::PALETTES_API_URL); - - if (! $response->successful()) { - Log::error('Failed to fetch palettes from API', [ - 'status' => $response->status(), - 'body' => $response->body(), - ]); - - return; - } - - $data = $response->json('data', []); - - if (! is_array($data)) { - Log::error('Invalid response format from palettes API', [ - 'response' => $response->json(), - ]); - - return; - } - - foreach ($data as $paletteData) { - try { - $this->updateOrCreatePalette($paletteData); - } catch (Exception $e) { - Log::error('Failed to process palette', [ - 'palette_data' => $paletteData, - 'error' => $e->getMessage(), - ]); - } - } - - Log::info('Successfully fetched and updated palettes', [ - 'count' => count($data), - ]); - - } catch (Exception $e) { - Log::error('Exception occurred while fetching palettes', [ - 'message' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), - ]); - } - } - - /** - * Update or create a palette record. - */ - private function updateOrCreatePalette(array $paletteData): void - { - $name = $paletteData['id'] ?? null; - - if (! $name) { - Log::warning('Palette data missing id field', [ - 'palette_data' => $paletteData, - ]); - - return; - } - - $attributes = [ - 'name' => $name, - 'description' => $paletteData['name'] ?? '', - 'grays' => $paletteData['grays'] ?? 2, - 'colors' => $paletteData['colors'] ?? null, - 'framework_class' => $paletteData['framework_class'] ?? '', - 'source' => 'api', - ]; - - DevicePalette::updateOrCreate( - ['name' => $name], - $attributes - ); - } - - /** - * Process the device models data and update/create records. - */ - private function processDeviceModels(array $deviceModels): void - { - foreach ($deviceModels as $modelData) { - try { - $this->updateOrCreateDeviceModel($modelData); - } catch (Exception $e) { - Log::error('Failed to process device model', [ - 'model_data' => $modelData, - 'error' => $e->getMessage(), - ]); - } - } - } - - /** - * Update or create a device model record. - */ - private function updateOrCreateDeviceModel(array $modelData): void - { - $name = $modelData['name'] ?? null; - - if (! $name) { - Log::warning('Device model data missing name field', [ - 'model_data' => $modelData, - ]); - - return; - } - - $attributes = [ - 'label' => $modelData['label'] ?? '', - 'description' => $modelData['description'] ?? '', - 'width' => $modelData['width'] ?? 0, - 'height' => $modelData['height'] ?? 0, - 'colors' => $modelData['colors'] ?? 0, - 'bit_depth' => $modelData['bit_depth'] ?? 0, - 'scale_factor' => $modelData['scale_factor'] ?? 1, - 'rotation' => $modelData['rotation'] ?? 0, - 'mime_type' => $modelData['mime_type'] ?? '', - 'offset_x' => $modelData['offset_x'] ?? 0, - 'offset_y' => $modelData['offset_y'] ?? 0, - 'published_at' => $modelData['published_at'] ?? null, - 'kind' => $modelData['kind'] ?? null, - 'source' => 'api', - ]; - - // Set palette_id to the first palette from the model's palettes array - $firstPaletteId = $this->getFirstPaletteId($modelData); - if ($firstPaletteId) { - $attributes['palette_id'] = $firstPaletteId; - } - - DeviceModel::updateOrCreate( - ['name' => $name], - $attributes - ); - } - - /** - * Get the first palette ID from model data. - */ - private function getFirstPaletteId(array $modelData): ?int - { - $paletteName = null; - - // Check for palette_ids array - if (isset($modelData['palette_ids']) && is_array($modelData['palette_ids']) && $modelData['palette_ids'] !== []) { - $paletteName = $modelData['palette_ids'][0]; - } - - // Check for palettes array (array of objects with id) - if (! $paletteName && isset($modelData['palettes']) && is_array($modelData['palettes']) && $modelData['palettes'] !== []) { - $firstPalette = $modelData['palettes'][0]; - if (is_array($firstPalette) && isset($firstPalette['id'])) { - $paletteName = $firstPalette['id']; - } - } - - if (! $paletteName) { - return null; - } - - // Look up palette by name to get the integer ID - $palette = DevicePalette::where('name', $paletteName)->first(); - - return $palette?->id; - } -} diff --git a/app/Jobs/FetchProxyCloudResponses.php b/app/Jobs/FetchProxyCloudResponses.php index ac23130..ece2808 100644 --- a/app/Jobs/FetchProxyCloudResponses.php +++ b/app/Jobs/FetchProxyCloudResponses.php @@ -23,7 +23,7 @@ class FetchProxyCloudResponses implements ShouldQueue */ public function handle(): void { - Device::where('proxy_cloud', true)->each(function ($device): void { + Device::where('proxy_cloud', true)->each(function ($device) { if (! $device->getNextPlaylistItem()) { try { $response = Http::withHeaders([ @@ -78,30 +78,22 @@ class FetchProxyCloudResponses implements ShouldQueue Log::info("Successfully updated proxy cloud response for device: {$device->mac_address}"); if ($device->last_log_request) { - try { - Http::withHeaders([ - 'id' => $device->mac_address, - 'access-token' => $device->api_key, - 'width' => 800, - 'height' => 480, - 'rssi' => $device->last_rssi_level, - 'battery_voltage' => $device->last_battery_voltage, - 'refresh-rate' => $device->default_refresh_interval, - 'fw-version' => $device->last_firmware_version, - 'accept-encoding' => 'identity;q=1,chunked;q=0.1,*;q=0', - 'user-agent' => 'ESP32HTTPClient', - ])->post(config('services.trmnl.proxy_base_url').'/api/log', $device->last_log_request); + Http::withHeaders([ + 'id' => $device->mac_address, + 'access-token' => $device->api_key, + 'width' => 800, + 'height' => 480, + 'rssi' => $device->last_rssi_level, + 'battery_voltage' => $device->last_battery_voltage, + 'refresh-rate' => $device->default_refresh_interval, + 'fw-version' => $device->last_firmware_version, + 'accept-encoding' => 'identity;q=1,chunked;q=0.1,*;q=0', + 'user-agent' => 'ESP32HTTPClient', + ])->post(config('services.trmnl.proxy_base_url').'/api/log', $device->last_log_request); - // Only clear the pending log request if the POST succeeded - $device->update([ - 'last_log_request' => null, - ]); - } catch (Exception $e) { - // Do not fail the entire proxy fetch if the log upload fails - Log::error("Failed to upload device log for device: {$device->mac_address}", [ - 'error' => $e->getMessage(), - ]); - } + $device->update([ + 'last_log_request' => null, + ]); } } catch (Exception $e) { diff --git a/app/Jobs/FirmwareDownloadJob.php b/app/Jobs/FirmwareDownloadJob.php index dfc851d..6b4fc36 100644 --- a/app/Jobs/FirmwareDownloadJob.php +++ b/app/Jobs/FirmwareDownloadJob.php @@ -18,7 +18,12 @@ class FirmwareDownloadJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - public function __construct(private Firmware $firmware) {} + private Firmware $firmware; + + public function __construct(Firmware $firmware) + { + $this->firmware = $firmware; + } public function handle(): void { @@ -28,25 +33,16 @@ class FirmwareDownloadJob implements ShouldQueue try { $filename = "FW{$this->firmware->version_tag}.bin"; - $response = Http::get($this->firmware->url); + Http::sink(storage_path("app/public/firmwares/$filename")) + ->get($this->firmware->url); - if (! $response->successful()) { - throw new Exception('HTTP request failed with status: '.$response->status()); - } - - // Save the response content to file - Storage::disk('public')->put("firmwares/$filename", $response->body()); - - // Only update storage location if download was successful $this->firmware->update([ 'storage_location' => "firmwares/$filename", ]); } catch (ConnectionException $e) { Log::error('Firmware download failed: '.$e->getMessage()); - // Don't update storage_location on failure } catch (Exception $e) { Log::error('An unexpected error occurred: '.$e->getMessage()); - // Don't update storage_location on failure } } } diff --git a/app/Jobs/FirmwarePollJob.php b/app/Jobs/FirmwarePollJob.php index c1a2267..7110b9c 100644 --- a/app/Jobs/FirmwarePollJob.php +++ b/app/Jobs/FirmwarePollJob.php @@ -17,7 +17,12 @@ class FirmwarePollJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - public function __construct(private bool $download = false) {} + private bool $download; + + public function __construct(bool $download = false) + { + $this->download = $download; + } public function handle(): void { diff --git a/app/Jobs/NotifyDeviceBatteryLowJob.php b/app/Jobs/NotifyDeviceBatteryLowJob.php index 9b1001b..2508365 100644 --- a/app/Jobs/NotifyDeviceBatteryLowJob.php +++ b/app/Jobs/NotifyDeviceBatteryLowJob.php @@ -15,6 +15,8 @@ class NotifyDeviceBatteryLowJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + public function __construct() {} + public function handle(): void { $devices = Device::all(); @@ -30,11 +32,9 @@ class NotifyDeviceBatteryLowJob implements ShouldQueue continue; } + // Skip if battery is not low or notification was already sent - if ($batteryPercent > $batteryThreshold) { - continue; - } - if ($device->battery_notification_sent) { + if ($batteryPercent > $batteryThreshold || $device->battery_notification_sent) { continue; } diff --git a/app/Liquid/FileSystems/InlineTemplatesFileSystem.php b/app/Liquid/FileSystems/InlineTemplatesFileSystem.php deleted file mode 100644 index dbde888..0000000 --- a/app/Liquid/FileSystems/InlineTemplatesFileSystem.php +++ /dev/null @@ -1,62 +0,0 @@ - - */ - protected array $templates = []; - - /** - * Register a template with the given name and content - */ - public function register(string $name, string $content): void - { - $this->templates[$name] = $content; - } - - /** - * Check if a template exists - */ - public function hasTemplate(string $templateName): bool - { - return isset($this->templates[$templateName]); - } - - /** - * Get all registered template names - * - * @return array - */ - public function getTemplateNames(): array - { - return array_keys($this->templates); - } - - /** - * Clear all registered templates - */ - public function clear(): void - { - $this->templates = []; - } - - public function readTemplateFile(string $templateName): string - { - if (! isset($this->templates[$templateName])) { - throw new InvalidArgumentException("Template '{$templateName}' not found in inline templates"); - } - - return $this->templates[$templateName]; - } -} diff --git a/app/Liquid/Filters/Data.php b/app/Liquid/Filters/Data.php deleted file mode 100644 index 2387ac5..0000000 --- a/app/Liquid/Filters/Data.php +++ /dev/null @@ -1,136 +0,0 @@ -subDays($days)->toDateString(); - } - - /** - * Format a date string with ordinal day (1st, 2nd, 3rd, etc.) - * - * @param string $dateStr The date string to parse - * @param string $strftimeExp The strftime format string with <> placeholder - * @return string The formatted date with ordinal day - */ - public function ordinalize(string $dateStr, string $strftimeExp): string - { - $date = Carbon::parse($dateStr); - $ordinalDay = $date->ordinal('day'); - - // Convert strftime format to PHP date format - $phpFormat = ExpressionUtils::strftimeToPhpFormat($strftimeExp); - - // Split the format string by the ordinal day placeholder - $parts = explode('<>', $phpFormat); - - if (count($parts) === 2) { - $before = $date->format($parts[0]); - $after = $date->format($parts[1]); - - return $before.$ordinalDay.$after; - } - - // Fallback: if no placeholder found, just format normally - return $date->format($phpFormat); - } -} diff --git a/app/Liquid/Filters/Localization.php b/app/Liquid/Filters/Localization.php deleted file mode 100644 index c91c75b..0000000 --- a/app/Liquid/Filters/Localization.php +++ /dev/null @@ -1,52 +0,0 @@ -locale($locale); - } - - return $carbon->translatedFormat($format); - } - - /** - * Translate a common word to another language - * - * @param string $word The word to translate - * @param string $locale The locale to translate to - * @return string The translated word - */ - public function l_word(string $word, string $locale): string - { - $translation = trans('custom_plugins.'.mb_strtolower($word), locale: $locale); - - if ($translation === 'custom_plugins.'.mb_strtolower($word)) { - return $word; - } - - return $translation; - } -} diff --git a/app/Liquid/Filters/Numbers.php b/app/Liquid/Filters/Numbers.php deleted file mode 100644 index 0e31de1..0000000 --- a/app/Liquid/Filters/Numbers.php +++ /dev/null @@ -1,50 +0,0 @@ -convert($markdown); - } catch (CommonMarkException $e) { - Log::error('Markdown conversion error: '.$e->getMessage()); - } - - return null; - } - - /** - * Strip HTML tags from a string - * - * @param string $html The HTML string to strip - * @return string The string without HTML tags - */ - public function strip_html(string $html): string - { - return strip_tags($html); - } - - /** - * Generate a QR code as SVG from the input text - * - * @param string $text The text to encode in the QR code - * @param int|null $moduleSize Optional module size (defaults to 11, which equals 319px) - * @param string|null $errorCorrection Optional error correction level: 'l', 'm', 'q', 'h' (defaults to 'm') - * @return string The SVG QR code - */ - public function qr_code(string $text, ?int $moduleSize = null, ?string $errorCorrection = null): string - { - // Default module_size is 11 - // Size calculation: (21 modules for QR code + 4 modules margin on each side * 2) * module_size - // = (21 + 8) * module_size = 29 * module_size - $moduleSize ??= 11; - $size = 29 * $moduleSize; - - $qrCode = QrCode::format('svg') - ->size($size); - - // Set error correction level if provided - if ($errorCorrection !== null) { - $qrCode->errorCorrection($errorCorrection); - } - - return $qrCode->generate($text); - } -} diff --git a/app/Liquid/Filters/Uniqueness.php b/app/Liquid/Filters/Uniqueness.php deleted file mode 100644 index 35378b3..0000000 --- a/app/Liquid/Filters/Uniqueness.php +++ /dev/null @@ -1,43 +0,0 @@ -generateRandomString(); - } - - /** - * Generate a random string - * - * @param int $length The length of the random string - * @return string A random string - */ - private function generateRandomString(int $length = 4): string - { - $characters = 'abcdefghijklmnopqrstuvwxyz0123456789'; - $randomString = ''; - - for ($i = 0; $i < $length; ++$i) { - $randomString .= $characters[random_int(0, mb_strlen($characters) - 1)]; - } - - return $randomString; - } -} diff --git a/app/Liquid/Tags/TemplateTag.php b/app/Liquid/Tags/TemplateTag.php deleted file mode 100644 index 94e08c1..0000000 --- a/app/Liquid/Tags/TemplateTag.php +++ /dev/null @@ -1,100 +0,0 @@ -params->expression(); - - $this->templateName = match (true) { - is_string($templateNameExpression) => mb_trim($templateNameExpression), - is_numeric($templateNameExpression) => (string) $templateNameExpression, - $templateNameExpression instanceof VariableLookup => (string) $templateNameExpression, - default => throw new SyntaxException('Template name must be a string, number, or variable'), - }; - - // Validate template name (letters, numbers, underscores, and slashes only) - if (! preg_match('/^[a-zA-Z0-9_\/]+$/', $this->templateName)) { - throw new SyntaxException("Invalid template name '{$this->templateName}' - template names must contain only letters, numbers, underscores, and slashes"); - } - - $context->params->assertEnd(); - - assert($context->body instanceof BodyNode); - - $body = $context->body->children()[0] ?? null; - $this->body = match (true) { - $body instanceof Raw => $body, - default => throw new SyntaxException('template tag must have a single raw body'), - }; - - // Register the template with the file system during parsing - $fileSystem = $context->getParseContext()->environment->fileSystem; - if ($fileSystem instanceof InlineTemplatesFileSystem) { - // Store the raw content for later rendering - $fileSystem->register($this->templateName, $this->body->value); - } - - return $this; - } - - public function render(RenderContext $context): string - { - // Get the file system from the environment - $fileSystem = $context->environment->fileSystem; - - if (! $fileSystem instanceof InlineTemplatesFileSystem) { - // If no inline file system is available, just return empty string - // This allows the template to be used in contexts where inline templates aren't supported - return ''; - } - - // Register the template with the file system - $fileSystem->register($this->templateName, $this->body->render($context)); - - // Return empty string as template tags don't output anything - return ''; - } - - public function getTemplateName(): string - { - return $this->templateName; - } - - public function getBody(): Raw - { - return $this->body; - } -} diff --git a/app/Liquid/Utils/ExpressionUtils.php b/app/Liquid/Utils/ExpressionUtils.php deleted file mode 100644 index 8a5bdb0..0000000 --- a/app/Liquid/Utils/ExpressionUtils.php +++ /dev/null @@ -1,210 +0,0 @@ - 'and', - 'left' => self::parseCondition(mb_trim($parts[0])), - 'right' => self::parseCondition(mb_trim($parts[1])), - ]; - } - - if (str_contains($expression, ' or ')) { - $parts = explode(' or ', $expression, 2); - - return [ - 'type' => 'or', - 'left' => self::parseCondition(mb_trim($parts[0])), - 'right' => self::parseCondition(mb_trim($parts[1])), - ]; - } - - // Handle comparison operators - $operators = ['>=', '<=', '!=', '==', '>', '<', '=']; - - foreach ($operators as $operator) { - if (str_contains($expression, $operator)) { - $parts = explode($operator, $expression, 2); - - return [ - 'type' => 'comparison', - 'left' => mb_trim($parts[0]), - 'operator' => $operator === '=' ? '==' : $operator, - 'right' => mb_trim($parts[1]), - ]; - } - } - - // If no operator found, treat as a simple expression - return [ - 'type' => 'simple', - 'expression' => $expression, - ]; - } - - /** - * Evaluate a condition against an object - */ - public static function evaluateCondition(array $condition, string $variable, mixed $object): bool - { - switch ($condition['type']) { - case 'and': - return self::evaluateCondition($condition['left'], $variable, $object) && - self::evaluateCondition($condition['right'], $variable, $object); - - case 'or': - if (self::evaluateCondition($condition['left'], $variable, $object)) { - return true; - } - - return self::evaluateCondition($condition['right'], $variable, $object); - - case 'comparison': - $leftValue = self::resolveValue($condition['left'], $variable, $object); - $rightValue = self::resolveValue($condition['right'], $variable, $object); - - return match ($condition['operator']) { - '==' => $leftValue === $rightValue, - '!=' => $leftValue !== $rightValue, - '>' => $leftValue > $rightValue, - '<' => $leftValue < $rightValue, - '>=' => $leftValue >= $rightValue, - '<=' => $leftValue <= $rightValue, - default => false, - }; - - case 'simple': - $value = self::resolveValue($condition['expression'], $variable, $object); - - return (bool) $value; - - default: - return false; - } - } - - /** - * Resolve a value from an expression, variable, or literal - */ - public static function resolveValue(string $expression, string $variable, mixed $object): mixed - { - $expression = mb_trim($expression); - - // If it's the variable name, return the object - if ($expression === $variable) { - return $object; - } - - // If it's a property access (e.g., "n.age"), resolve it - if (str_starts_with($expression, $variable.'.')) { - $property = mb_substr($expression, mb_strlen($variable) + 1); - if (is_array($object) && array_key_exists($property, $object)) { - return $object[$property]; - } - if (is_object($object) && property_exists($object, $property)) { - return $object->$property; - } - - return null; - } - - // Try to parse as a number - if (is_numeric($expression)) { - return str_contains($expression, '.') ? (float) $expression : (int) $expression; - } - - // Try to parse as boolean - if (in_array(mb_strtolower($expression), ['true', 'false'])) { - return mb_strtolower($expression) === 'true'; - } - - // Try to parse as null - if (mb_strtolower($expression) === 'null') { - return null; - } - - // Return as string (remove quotes if present) - if ((str_starts_with($expression, '"') && str_ends_with($expression, '"')) || - (str_starts_with($expression, "'") && str_ends_with($expression, "'"))) { - return mb_substr($expression, 1, -1); - } - - return $expression; - } - - /** - * Convert strftime format string to PHP date format string - * - * @param string $strftimeFormat The strftime format string - * @return string The PHP date format string - */ - public static function strftimeToPhpFormat(string $strftimeFormat): string - { - $conversions = [ - // Special Ruby format cases - '%N' => 'u', // Microseconds (Ruby) -> microseconds (PHP) - '%u' => 'u', // Microseconds (Ruby) -> microseconds (PHP) - '%-m' => 'n', // Month without leading zero (Ruby) -> month without leading zero (PHP) - '%-d' => 'j', // Day without leading zero (Ruby) -> day without leading zero (PHP) - '%-H' => 'G', // Hour without leading zero (Ruby) -> hour without leading zero (PHP) - '%-I' => 'g', // Hour 12h without leading zero (Ruby) -> hour 12h without leading zero (PHP) - '%-M' => 'i', // Minute without leading zero (Ruby) -> minute without leading zero (PHP) - '%-S' => 's', // Second without leading zero (Ruby) -> second without leading zero (PHP) - '%z' => 'O', // Timezone offset (Ruby) -> timezone offset (PHP) - '%Z' => 'T', // Timezone name (Ruby) -> timezone name (PHP) - - // Standard strftime conversions - '%A' => 'l', // Full weekday name - '%a' => 'D', // Abbreviated weekday name - '%B' => 'F', // Full month name - '%b' => 'M', // Abbreviated month name - '%Y' => 'Y', // Full year (4 digits) - '%y' => 'y', // Year without century (2 digits) - '%m' => 'm', // Month as decimal number (01-12) - '%d' => 'd', // Day of month as decimal number (01-31) - '%H' => 'H', // Hour in 24-hour format (00-23) - '%I' => 'h', // Hour in 12-hour format (01-12) - '%M' => 'i', // Minute as decimal number (00-59) - '%S' => 's', // Second as decimal number (00-59) - '%p' => 'A', // AM/PM - '%P' => 'a', // am/pm - '%j' => 'z', // Day of year as decimal number (001-366) - '%w' => 'w', // Weekday as decimal number (0-6, Sunday is 0) - '%U' => 'W', // Week number of year (00-53, Sunday is first day) - '%W' => 'W', // Week number of year (00-53, Monday is first day) - '%c' => 'D M j H:i:s Y', // Date and time representation - '%x' => 'm/d/Y', // Date representation - '%X' => 'H:i:s', // Time representation - ]; - - return str_replace(array_keys($conversions), array_values($conversions), $strftimeFormat); - } -} diff --git a/app/Livewire/Actions/DeviceAutoJoin.php b/app/Livewire/Actions/DeviceAutoJoin.php index 82d63ed..c16322c 100644 --- a/app/Livewire/Actions/DeviceAutoJoin.php +++ b/app/Livewire/Actions/DeviceAutoJoin.php @@ -10,14 +10,14 @@ class DeviceAutoJoin extends Component public bool $isFirstUser = false; - public function mount(): void + public function mount() { - $this->deviceAutojoin = (bool) (auth()->user()->assign_new_devices ?? false); + $this->deviceAutojoin = auth()->user()->assign_new_devices; $this->isFirstUser = auth()->user()->id === 1; } - public function updating($name, $value): void + public function updating($name, $value) { $this->validate([ 'deviceAutojoin' => 'boolean', @@ -30,7 +30,7 @@ class DeviceAutoJoin extends Component } } - public function render(): \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory + public function render() { return view('livewire.actions.device-auto-join'); } diff --git a/app/Livewire/Actions/Logout.php b/app/Livewire/Actions/Logout.php index c26fa72..45993bb 100644 --- a/app/Livewire/Actions/Logout.php +++ b/app/Livewire/Actions/Logout.php @@ -10,7 +10,7 @@ class Logout /** * Log the current user out of the application. */ - public function __invoke(): \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse + public function __invoke() { Auth::guard('web')->logout(); diff --git a/app/Livewire/DeviceDashboard.php b/app/Livewire/DeviceDashboard.php index a2a3692..78309cb 100644 --- a/app/Livewire/DeviceDashboard.php +++ b/app/Livewire/DeviceDashboard.php @@ -6,7 +6,7 @@ use Livewire\Component; class DeviceDashboard extends Component { - public function render(): \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory + public function render() { return view('livewire.device-dashboard', ['devices' => auth()->user()->devices()->paginate(10)]); } diff --git a/app/Models/Device.php b/app/Models/Device.php index 3583f48..d786d2e 100644 --- a/app/Models/Device.php +++ b/app/Models/Device.php @@ -10,24 +10,12 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Facades\Storage; -/** - * @property-read DeviceModel|null $deviceModel - * @property-read DevicePalette|null $palette - */ class Device extends Model { use HasFactory; protected $guarded = ['id']; - /** - * Set the MAC address attribute, normalizing to uppercase. - */ - public function setMacAddressAttribute(?string $value): void - { - $this->attributes['mac_address'] = $value ? mb_strtoupper($value) : null; - } - protected $casts = [ 'battery_notification_sent' => 'boolean', 'proxy_cloud' => 'boolean', @@ -44,7 +32,7 @@ class Device extends Model 'pause_until' => 'datetime', ]; - public function getBatteryPercentAttribute(): int|float + public function getBatteryPercentAttribute() { $volts = $this->last_battery_voltage; @@ -92,7 +80,7 @@ class Device extends Model return round($voltage, 2); } - public function getWifiStrengthAttribute(): int + public function getWifiStrengthAttribute() { $rssi = $this->last_rssi_level; if ($rssi >= 0) { @@ -115,7 +103,11 @@ class Device extends Model return true; } - return $this->proxy_cloud_response && $this->proxy_cloud_response['update_firmware']; + if ($this->proxy_cloud_response && $this->proxy_cloud_response['update_firmware']) { + return true; + } + + return false; } public function getFirmwareUrlAttribute(): ?string @@ -191,40 +183,6 @@ class Device extends Model return $this->belongsTo(Firmware::class, 'update_firmware_id'); } - public function deviceModel(): BelongsTo - { - return $this->belongsTo(DeviceModel::class); - } - - public function palette(): BelongsTo - { - return $this->belongsTo(DevicePalette::class, 'palette_id'); - } - - /** - * Get the color depth string (e.g., "4bit") for the associated device model. - */ - public function colorDepth(): ?string - { - return $this->deviceModel?->color_depth; - } - - /** - * Get the scale level (e.g., large/xlarge/xxlarge) for the associated device model. - */ - public function scaleLevel(): ?string - { - return $this->deviceModel?->scale_level; - } - - /** - * Get the device variant name, defaulting to 'og' if not available. - */ - public function deviceVariant(): string - { - return $this->deviceModel->name ?? 'og'; - } - public function logs(): HasMany { return $this->hasMany(DeviceLog::class); @@ -241,7 +199,7 @@ class Device extends Model return false; } - $now = $now instanceof DateTimeInterface ? Carbon::instance($now) : now(); + $now = $now ? Carbon::instance($now) : now(); // Handle overnight ranges (e.g. 22:00 to 06:00) return $this->sleep_mode_from < $this->sleep_mode_to @@ -255,7 +213,7 @@ class Device extends Model return null; } - $now = $now instanceof DateTimeInterface ? Carbon::instance($now) : now(); + $now = $now ? Carbon::instance($now) : now(); $from = $this->sleep_mode_from; $to = $this->sleep_mode_to; @@ -263,20 +221,19 @@ class Device extends Model if ($from < $to) { // Normal range, same day return $now->between($from, $to) ? (int) $now->diffInSeconds($to, false) : null; + } else { + // Overnight range + if ($now->gte($from)) { + // After 'from', before midnight + return (int) $now->diffInSeconds($to->copy()->addDay(), false); + } elseif ($now->lt($to)) { + // After midnight, before 'to' + return (int) $now->diffInSeconds($to, false); + } else { + // Not in sleep window + return null; + } } - // Overnight range - if ($now->gte($from)) { - // After 'from', before midnight - return (int) $now->diffInSeconds($to->copy()->addDay(), false); - } - if ($now->lt($to)) { - // After midnight, before 'to' - return (int) $now->diffInSeconds($to, false); - } - - // Not in sleep window - return null; - } public function isPauseActive(): bool diff --git a/app/Models/DeviceModel.php b/app/Models/DeviceModel.php deleted file mode 100644 index 6132a76..0000000 --- a/app/Models/DeviceModel.php +++ /dev/null @@ -1,78 +0,0 @@ - 'integer', - 'height' => 'integer', - 'colors' => 'integer', - 'bit_depth' => 'integer', - 'scale_factor' => 'float', - 'rotation' => 'integer', - 'offset_x' => 'integer', - 'offset_y' => 'integer', - 'published_at' => 'datetime', - ]; - - public function getColorDepthAttribute(): ?string - { - if (! $this->bit_depth) { - return null; - } - - if ($this->bit_depth === 3) { - return '2bit'; - } - - // if higher than 4 return 4bit - if ($this->bit_depth > 4) { - return '4bit'; - } - - return $this->bit_depth.'bit'; - } - - /** - * Returns the scale level based on the device width. - */ - public function getScaleLevelAttribute(): ?string - { - if (! $this->width) { - return null; - } - - if ($this->width > 800 && $this->width <= 1000) { - return 'large'; - } - - if ($this->width > 1000 && $this->width <= 1400) { - return 'xlarge'; - } - - if ($this->width > 1400) { - return 'xxlarge'; - } - - return null; - } - - public function palette(): BelongsTo - { - return $this->belongsTo(DevicePalette::class, 'palette_id'); - } -} diff --git a/app/Models/DevicePalette.php b/app/Models/DevicePalette.php deleted file mode 100644 index 54b0876..0000000 --- a/app/Models/DevicePalette.php +++ /dev/null @@ -1,23 +0,0 @@ - 'integer', - 'colors' => 'array', - ]; -} diff --git a/app/Models/Playlist.php b/app/Models/Playlist.php index b4daf5e..d20798c 100644 --- a/app/Models/Playlist.php +++ b/app/Models/Playlist.php @@ -37,33 +37,26 @@ class Playlist extends Model return false; } - // Get user's timezone or fall back to app timezone - $timezone = $this->device->user->timezone ?? config('app.timezone'); - $now = now($timezone); - - // Check weekday (using timezone-aware time) - if ($this->weekdays !== null && ! in_array($now->dayOfWeek, $this->weekdays)) { - return false; + // Check weekday + if ($this->weekdays !== null) { + if (! in_array(now()->dayOfWeek, $this->weekdays)) { + return false; + } } if ($this->active_from !== null && $this->active_until !== null) { - // Create timezone-aware datetime objects for active_from and active_until - $activeFrom = $now->copy() - ->setTimeFrom($this->active_from) - ->timezone($timezone); - - $activeUntil = $now->copy() - ->setTimeFrom($this->active_until) - ->timezone($timezone); + $now = now(); // Handle time ranges that span across midnight - if ($activeFrom > $activeUntil) { + if ($this->active_from > $this->active_until) { // Time range spans midnight (e.g., 09:01 to 03:58) - if ($now >= $activeFrom || $now <= $activeUntil) { + if ($now >= $this->active_from || $now <= $this->active_until) { + return true; + } + } else { + if ($now >= $this->active_from && $now <= $this->active_until) { return true; } - } elseif ($now >= $activeFrom && $now <= $activeUntil) { - return true; } return false; diff --git a/app/Models/PlaylistItem.php b/app/Models/PlaylistItem.php index ad11f1d..2459257 100644 --- a/app/Models/PlaylistItem.php +++ b/app/Models/PlaylistItem.php @@ -135,13 +135,10 @@ class PlaylistItem extends Model /** * Render all plugins with appropriate layout */ - public function render(?Device $device = null): string + public function render(): string { if (! $this->isMashup()) { return view('trmnl-layouts.single', [ - 'colorDepth' => $device?->colorDepth(), - 'deviceVariant' => $device?->deviceVariant() ?? 'og', - 'scaleLevel' => $device?->scaleLevel(), 'slot' => $this->plugin instanceof Plugin ? $this->plugin->render('full', false) : throw new Exception('Invalid plugin instance'), @@ -153,7 +150,9 @@ class PlaylistItem extends Model $plugins = Plugin::whereIn('id', $pluginIds)->get(); // Sort the collection to match plugin_ids order - $plugins = $plugins->sortBy(fn ($plugin): int|string|false => array_search($plugin->id, $pluginIds))->values(); + $plugins = $plugins->sortBy(function ($plugin) use ($pluginIds) { + return array_search($plugin->id, $pluginIds); + })->values(); foreach ($plugins as $index => $plugin) { $size = $this->getLayoutSize($index); @@ -161,9 +160,6 @@ class PlaylistItem extends Model } return view('trmnl-layouts.mashup', [ - 'colorDepth' => $device?->colorDepth(), - 'deviceVariant' => $device?->deviceVariant() ?? 'og', - 'scaleLevel' => $device?->scaleLevel(), 'mashupLayout' => $this->getMashupLayoutType(), 'slot' => implode('', $pluginMarkups), ])->render(); diff --git a/app/Models/Plugin.php b/app/Models/Plugin.php index 31841bc..1d07251 100644 --- a/app/Models/Plugin.php +++ b/app/Models/Plugin.php @@ -2,32 +2,13 @@ namespace App\Models; -use App\Liquid\FileSystems\InlineTemplatesFileSystem; -use App\Liquid\Filters\Data; -use App\Liquid\Filters\Date; -use App\Liquid\Filters\Localization; -use App\Liquid\Filters\Numbers; -use App\Liquid\Filters\StandardFilters; -use App\Liquid\Filters\StringMarkup; -use App\Liquid\Filters\Uniqueness; -use App\Liquid\Tags\TemplateTag; -use App\Services\Plugin\Parsers\ResponseParserRegistry; -use App\Services\PluginImportService; -use Carbon\Carbon; -use Exception; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use Illuminate\Http\Client\Response; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Http; -use Illuminate\Support\Facades\Log; -use Illuminate\Support\Facades\Process; use Illuminate\Support\Str; -use InvalidArgumentException; -use Keepsuit\LaravelLiquid\LaravelLiquidExtension; use Keepsuit\Liquid\Exceptions\LiquidException; -use Keepsuit\Liquid\Extensions\StandardExtension; class Plugin extends Model { @@ -40,107 +21,21 @@ class Plugin extends Model 'data_payload_updated_at' => 'datetime', 'is_native' => 'boolean', 'markup_language' => 'string', - 'configuration' => 'json', - 'configuration_template' => 'json', - 'no_bleed' => 'boolean', - 'dark_mode' => 'boolean', - 'preferred_renderer' => 'string', - 'plugin_type' => 'string', - 'alias' => 'boolean', ]; protected static function boot() { parent::boot(); - static::creating(function ($model): void { + static::creating(function ($model) { if (empty($model->uuid)) { $model->uuid = Str::uuid(); } }); - - static::updating(function ($model): void { - // Reset image cache when markup changes - if ($model->isDirty('render_markup')) { - $model->current_image = null; - } - }); - - // Sanitize configuration template on save - static::saving(function ($model): void { - $model->sanitizeTemplate(); - }); - } - - public function user() - { - return $this->belongsTo(User::class); - } - - // sanitize configuration template descriptions and help texts (since they allow HTML rendering) - protected function sanitizeTemplate(): void - { - $template = $this->configuration_template; - - if (isset($template['custom_fields']) && is_array($template['custom_fields'])) { - foreach ($template['custom_fields'] as &$field) { - if (isset($field['description'])) { - $field['description'] = \Stevebauman\Purify\Facades\Purify::clean($field['description']); - } - if (isset($field['help_text'])) { - $field['help_text'] = \Stevebauman\Purify\Facades\Purify::clean($field['help_text']); - } - } - - $this->configuration_template = $template; - } - } - - public function hasMissingRequiredConfigurationFields(): bool - { - if (! isset($this->configuration_template['custom_fields']) || empty($this->configuration_template['custom_fields'])) { - return false; - } - - foreach ($this->configuration_template['custom_fields'] as $field) { - // Skip fields as they are informational only - if ($field['field_type'] === 'author_bio') { - continue; - } - - if ($field['field_type'] === 'copyable') { - continue; - } - - if ($field['field_type'] === 'copyable_webhook_url') { - continue; - } - - $fieldKey = $field['keyname'] ?? $field['key'] ?? $field['name']; - - // Check if field is required (not marked as optional) - $isRequired = ! isset($field['optional']) || $field['optional'] !== true; - - if ($isRequired) { - $currentValue = $this->configuration[$fieldKey] ?? null; - - // If the field has a default value and no current value is set, it's not missing - if ((in_array($currentValue, [null, '', []], true)) && ! isset($field['default'])) { - return true; // Found a required field that is not set and has no default - } - } - } - - return false; // All required fields are set } public function isDataStale(): bool { - // Image webhook plugins don't use data staleness - images are pushed directly - if ($this->plugin_type === 'image_webhook') { - return false; - } - if ($this->data_strategy === 'webhook') { // Treat as stale if any webhook event has occurred in the past hour return $this->data_payload_updated_at && $this->data_payload_updated_at->gt(now()->subHour()); @@ -154,260 +49,38 @@ class Plugin extends Model public function updateDataPayload(): void { - if ($this->data_strategy !== 'polling' || ! $this->polling_url) { - return; - } - $headers = ['User-Agent' => 'usetrmnl/byos_laravel', 'Accept' => 'application/json']; + if ($this->data_strategy === 'polling' && $this->polling_url) { - // resolve headers - if ($this->polling_header) { - $resolvedHeader = $this->resolveLiquidVariables($this->polling_header); - $headerLines = explode("\n", mb_trim($resolvedHeader)); - foreach ($headerLines as $line) { - $parts = explode(':', $line, 2); - if (count($parts) === 2) { - $headers[mb_trim($parts[0])] = mb_trim($parts[1]); + $headers = ['User-Agent' => 'usetrmnl/byos_laravel', 'Accept' => 'application/json']; + + if ($this->polling_header) { + $headerLines = explode("\n", trim($this->polling_header)); + foreach ($headerLines as $line) { + $parts = explode(':', $line, 2); + if (count($parts) === 2) { + $headers[trim($parts[0])] = trim($parts[1]); + } } } - } - // resolve and clean URLs - $resolvedPollingUrls = $this->resolveLiquidVariables($this->polling_url); - $urls = array_values(array_filter( // array_values ensures 0, 1, 2... - array_map(trim(...), explode("\n", $resolvedPollingUrls)), - filled(...) - )); - - $combinedResponse = []; - - // Loop through all URLs (Handles 1 or many) - foreach ($urls as $index => $url) { $httpRequest = Http::withHeaders($headers); if ($this->polling_verb === 'post' && $this->polling_body) { - $resolvedBody = $this->resolveLiquidVariables($this->polling_body); - $httpRequest = $httpRequest->withBody($resolvedBody); + $httpRequest = $httpRequest->withBody($this->polling_body); } - try { - $httpResponse = ($this->polling_verb === 'post') - ? $httpRequest->post($url) - : $httpRequest->get($url); - - $response = $this->parseResponse($httpResponse); - - // Nest if it's a sequential array - if (array_keys($response) === range(0, count($response) - 1)) { - $combinedResponse["IDX_{$index}"] = ['data' => $response]; - } else { - $combinedResponse["IDX_{$index}"] = $response; - } - } catch (Exception $e) { - Log::warning("Failed to fetch data from URL {$url}: ".$e->getMessage()); - $combinedResponse["IDX_{$index}"] = ['error' => 'Failed to fetch data']; + // Make the request based on the verb + if ($this->polling_verb === 'post') { + $response = $httpRequest->post($this->polling_url)->json(); + } else { + $response = $httpRequest->get($this->polling_url)->json(); } + + $this->update([ + 'data_payload' => $response, + 'data_payload_updated_at' => now(), + ]); } - - // unwrap IDX_0 if only one URL - $finalPayload = (count($urls) === 1) ? reset($combinedResponse) : $combinedResponse; - - $this->update([ - 'data_payload' => $finalPayload, - 'data_payload_updated_at' => now(), - ]); - } - - private function parseResponse(Response $httpResponse): array - { - $parsers = app(ResponseParserRegistry::class)->getParsers(); - - foreach ($parsers as $parser) { - $parserName = class_basename($parser); - - try { - $result = $parser->parse($httpResponse); - - if ($result !== null) { - return $result; - } - } catch (Exception $e) { - Log::warning("Failed to parse {$parserName} response: ".$e->getMessage()); - } - } - - return ['error' => 'Failed to parse response']; - } - - /** - * Apply Liquid template replacements (converts 'with' syntax to comma syntax) - */ - private function applyLiquidReplacements(string $template): string - { - - $replacements = []; - - // Apply basic replacements - $template = str_replace(array_keys($replacements), array_values($replacements), $template); - - // Convert Ruby/strftime date formats to PHP date formats - $template = $this->convertDateFormats($template); - - // Convert {% render "template" with %} syntax to {% render "template", %} syntax - $template = preg_replace( - '/{%\s*render\s+([^}]+?)\s+with\s+/i', - '{% render $1, ', - $template - ); - - // Convert for loops with filters to use temporary variables - // This handles: {% for item in collection | filter: "key", "value" %} - // Converts to: {% assign temp_filtered = collection | filter: "key", "value" %}{% for item in temp_filtered %} - $template = preg_replace_callback( - '/{%\s*for\s+(\w+)\s+in\s+([^|%}]+)\s*\|\s*([^%}]+)%}/', - function (array $matches): string { - $variableName = mb_trim($matches[1]); - $collection = mb_trim($matches[2]); - $filter = mb_trim($matches[3]); - $tempVarName = '_temp_'.uniqid(); - - return "{% assign {$tempVarName} = {$collection} | {$filter} %}{% for {$variableName} in {$tempVarName} %}"; - }, - (string) $template - ); - - return $template; - } - - /** - * Convert Ruby/strftime date formats to PHP date formats in Liquid templates - */ - private function convertDateFormats(string $template): string - { - // Handle date filter formats: date: "format" or date: 'format' - $template = preg_replace_callback( - '/date:\s*(["\'])([^"\']+)\1/', - function (array $matches): string { - $quote = $matches[1]; - $format = $matches[2]; - $convertedFormat = \App\Liquid\Utils\ExpressionUtils::strftimeToPhpFormat($format); - - return 'date: '.$quote.$convertedFormat.$quote; - }, - $template - ); - - // Handle l_date filter formats: l_date: "format" or l_date: 'format' - $template = preg_replace_callback( - '/l_date:\s*(["\'])([^"\']+)\1/', - function (array $matches): string { - $quote = $matches[1]; - $format = $matches[2]; - $convertedFormat = \App\Liquid\Utils\ExpressionUtils::strftimeToPhpFormat($format); - - return 'l_date: '.$quote.$convertedFormat.$quote; - }, - (string) $template - ); - - return $template; - } - - /** - * Check if a template contains a Liquid for loop pattern - * - * @param string $template The template string to check - * @return bool True if the template contains a for loop pattern - */ - private function containsLiquidForLoop(string $template): bool - { - return preg_match('/{%-?\s*for\s+/i', $template) === 1; - } - - /** - * Resolve Liquid variables in a template string using the Liquid template engine - * - * Uses the external trmnl-liquid renderer when: - * - preferred_renderer is 'trmnl-liquid' - * - External renderer is enabled in config - * - Template contains a Liquid for loop pattern - * - * Otherwise uses the internal PHP-based Liquid renderer. - * - * @param string $template The template string containing Liquid variables - * @return string The resolved template with variables replaced with their values - * - * @throws LiquidException - * @throws Exception - */ - public function resolveLiquidVariables(string $template): string - { - // Get configuration variables - make them available at root level - $variables = $this->configuration ?? []; - - // Check if external renderer should be used - $useExternalRenderer = $this->preferred_renderer === 'trmnl-liquid' - && config('services.trmnl.liquid_enabled') - && $this->containsLiquidForLoop($template); - - if ($useExternalRenderer) { - // Use external Ruby liquid renderer - return $this->renderWithExternalLiquidRenderer($template, $variables); - } - - // Use the Liquid template engine to resolve variables - $environment = App::make('liquid.environment'); - $environment->filterRegistry->register(StandardFilters::class); - $liquidTemplate = $environment->parseString($template); - $context = $environment->newRenderContext(data: $variables); - - return $liquidTemplate->render($context); - } - - /** - * Render template using external Ruby liquid renderer - * - * @param string $template The liquid template string - * @param array $context The render context data - * @return string The rendered HTML - * - * @throws Exception - */ - private function renderWithExternalLiquidRenderer(string $template, array $context): string - { - $liquidPath = config('services.trmnl.liquid_path'); - - if (empty($liquidPath)) { - throw new Exception('External liquid renderer path is not configured'); - } - - // HTML encode the template - $encodedTemplate = htmlspecialchars($template, ENT_QUOTES, 'UTF-8'); - - // Encode context as JSON - $jsonContext = json_encode($context, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); - - if ($jsonContext === false) { - throw new Exception('Failed to encode render context as JSON: '.json_last_error_msg()); - } - - // Validate argument sizes - app(PluginImportService::class)->validateExternalRendererArguments($encodedTemplate, $jsonContext, $liquidPath); - - // Execute the external renderer - $process = Process::run([ - $liquidPath, - '--template', - $encodedTemplate, - '--context', - $jsonContext, - ]); - - if (! $process->successful()) { - $errorOutput = $process->errorOutput() ?: $process->output(); - throw new Exception('External liquid renderer failed: '.$errorOutput); - } - - return $process->output(); } /** @@ -415,112 +88,24 @@ class Plugin extends Model * * @throws LiquidException */ - public function render(string $size = 'full', bool $standalone = true, ?Device $device = null): string + public function render(string $size = 'full', bool $standalone = true): string { - if ($this->plugin_type !== 'recipe') { - throw new InvalidArgumentException('Render method is only applicable for recipe plugins.'); - } - if ($this->render_markup) { $renderedContent = ''; if ($this->markup_language === 'liquid') { - // Get timezone from user or fall back to app timezone - $timezone = $this->user->timezone ?? config('app.timezone'); - - // Calculate UTC offset in seconds - $utcOffset = (string) Carbon::now($timezone)->getOffset(); - - // Build render context - $context = [ - 'size' => $size, - 'data' => $this->data_payload, - 'config' => $this->configuration ?? [], - ...(is_array($this->data_payload) ? $this->data_payload : []), - 'trmnl' => [ - 'system' => [ - 'timestamp_utc' => now()->utc()->timestamp, - ], - 'user' => [ - 'utc_offset' => $utcOffset, - 'name' => $this->user->name ?? 'Unknown User', - 'locale' => 'en', - 'time_zone_iana' => $timezone, - ], - 'plugin_settings' => [ - 'instance_name' => $this->name, - 'strategy' => $this->data_strategy, - 'dark_mode' => $this->dark_mode ? 'yes' : 'no', - 'no_screen_padding' => $this->no_bleed ? 'yes' : 'no', - 'polling_headers' => $this->polling_header, - 'polling_url' => $this->polling_url, - 'custom_fields_values' => [ - ...(is_array($this->configuration) ? $this->configuration : []), - ], - ], - ], - ]; - - // Check if external renderer should be used - if ($this->preferred_renderer === 'trmnl-liquid' && config('services.trmnl.liquid_enabled')) { - // Use external Ruby renderer - pass raw template without preprocessing - $renderedContent = $this->renderWithExternalLiquidRenderer($this->render_markup, $context); - } else { - // Use PHP keepsuit/liquid renderer - // Create a custom environment with inline templates support - $inlineFileSystem = new InlineTemplatesFileSystem(); - $environment = new \Keepsuit\Liquid\Environment( - fileSystem: $inlineFileSystem, - extensions: [new StandardExtension(), new LaravelLiquidExtension()] - ); - - // Register all custom filters - $environment->filterRegistry->register(Data::class); - $environment->filterRegistry->register(Date::class); - $environment->filterRegistry->register(Localization::class); - $environment->filterRegistry->register(Numbers::class); - $environment->filterRegistry->register(StringMarkup::class); - $environment->filterRegistry->register(Uniqueness::class); - - // Register the template tag for inline templates - $environment->tagRegistry->register(TemplateTag::class); - - // Apply Liquid replacements (including 'with' syntax conversion) - $processedMarkup = $this->applyLiquidReplacements($this->render_markup); - - $template = $environment->parseString($processedMarkup); - $liquidContext = $environment->newRenderContext(data: $context); - $renderedContent = $template->render($liquidContext); - } + $environment = App::make('liquid.environment'); + $template = $environment->parseString($this->render_markup); + $context = $environment->newRenderContext(data: ['size' => $size, 'data' => $this->data_payload]); + $renderedContent = $template->render($context); } else { - $renderedContent = Blade::render($this->render_markup, [ - 'size' => $size, - 'data' => $this->data_payload, - 'config' => $this->configuration ?? [], - ]); + $renderedContent = Blade::render($this->render_markup, ['size' => $size, 'data' => $this->data_payload]); } if ($standalone) { - if ($size === 'full') { - return view('trmnl-layouts.single', [ - 'colorDepth' => $device?->colorDepth(), - 'deviceVariant' => $device?->deviceVariant() ?? 'og', - 'noBleed' => $this->no_bleed, - 'darkMode' => $this->dark_mode, - 'scaleLevel' => $device?->scaleLevel(), - 'slot' => $renderedContent, - ])->render(); - } - - return view('trmnl-layouts.mashup', [ - 'mashupLayout' => $this->getPreviewMashupLayoutForSize($size), - 'colorDepth' => $device?->colorDepth(), - 'deviceVariant' => $device?->deviceVariant() ?? 'og', - 'darkMode' => $this->dark_mode, - 'scaleLevel' => $device?->scaleLevel(), + return view('trmnl-layouts.single', [ 'slot' => $renderedContent, ])->render(); - } return $renderedContent; @@ -528,115 +113,21 @@ class Plugin extends Model if ($this->render_markup_view) { if ($standalone) { - $renderedView = view($this->render_markup_view, [ - 'size' => $size, - 'data' => $this->data_payload, - 'config' => $this->configuration ?? [], - ])->render(); - - if ($size === 'full') { - return view('trmnl-layouts.single', [ - 'colorDepth' => $device?->colorDepth(), - 'deviceVariant' => $device?->deviceVariant() ?? 'og', - 'noBleed' => $this->no_bleed, - 'darkMode' => $this->dark_mode, - 'scaleLevel' => $device?->scaleLevel(), - 'slot' => $renderedView, - ])->render(); - } - - return view('trmnl-layouts.mashup', [ - 'mashupLayout' => $this->getPreviewMashupLayoutForSize($size), - 'colorDepth' => $device?->colorDepth(), - 'deviceVariant' => $device?->deviceVariant() ?? 'og', - 'darkMode' => $this->dark_mode, - 'scaleLevel' => $device?->scaleLevel(), - 'slot' => $renderedView, + return view('trmnl-layouts.single', [ + 'slot' => view($this->render_markup_view, [ + 'size' => $size, + 'data' => $this->data_payload, + ])->render(), ])->render(); } return view($this->render_markup_view, [ 'size' => $size, 'data' => $this->data_payload, - 'config' => $this->configuration ?? [], ])->render(); } return '

No render markup yet defined for this plugin.

'; } - - /** - * Get a configuration value by key - */ - public function getConfiguration(string $key, $default = null) - { - return $this->configuration[$key] ?? $default; - } - - public function getPreviewMashupLayoutForSize(string $size): string - { - return match ($size) { - 'half_vertical' => '1Lx1R', - 'quadrant' => '2x2', - default => '1Tx1B', - }; - } - - /** - * Duplicate the plugin, copying all attributes and handling render_markup_view - * - * @param int|null $userId Optional user ID for the duplicate. If not provided, uses the original plugin's user_id. - * @return Plugin The newly created duplicate plugin - */ - public function duplicate(?int $userId = null): self - { - // Get all attributes except id and uuid - // Use toArray() to get cast values (respects JSON casts) - $attributes = $this->toArray(); - unset($attributes['id'], $attributes['uuid']); - - // Handle render_markup_view - copy file content to render_markup - if ($this->render_markup_view) { - try { - $basePath = resource_path('views/'.str_replace('.', '/', $this->render_markup_view)); - $paths = [ - $basePath.'.blade.php', - $basePath.'.liquid', - ]; - - $fileContent = null; - $markupLanguage = null; - foreach ($paths as $path) { - if (file_exists($path)) { - $fileContent = file_get_contents($path); - // Determine markup language based on file extension - $markupLanguage = str_ends_with($path, '.liquid') ? 'liquid' : 'blade'; - break; - } - } - - if ($fileContent !== null) { - $attributes['render_markup'] = $fileContent; - $attributes['markup_language'] = $markupLanguage; - $attributes['render_markup_view'] = null; - } else { - // File doesn't exist, remove the view reference - $attributes['render_markup_view'] = null; - } - } catch (Exception) { - // If file reading fails, remove the view reference - $attributes['render_markup_view'] = null; - } - } - - // Append " (Copy)" to the name - $attributes['name'] = $this->name.' (Copy)'; - - // Set user_id - use provided userId or fall back to original plugin's user_id - $attributes['user_id'] = $userId ?? $this->user_id; - - // Create and return the new plugin - return self::create($attributes); - } } diff --git a/app/Models/User.php b/app/Models/User.php index 8d7aa7e..1f524a7 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -8,13 +8,12 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Illuminate\Support\Str; -use Laravel\Fortify\TwoFactorAuthenticatable; use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable // implements MustVerifyEmail { /** @use HasFactory<\Database\Factories\UserFactory> */ - use HasApiTokens, HasFactory, Notifiable, TwoFactorAuthenticatable; + use HasApiTokens, HasFactory, Notifiable; /** * The attributes that are mass assignable. @@ -27,8 +26,6 @@ class User extends Authenticatable // implements MustVerifyEmail 'password', 'assign_new_devices', 'assign_new_device_id', - 'oidc_sub', - 'timezone', ]; /** diff --git a/app/Notifications/BatteryLow.php b/app/Notifications/BatteryLow.php index 17fb1da..c76c87f 100644 --- a/app/Notifications/BatteryLow.php +++ b/app/Notifications/BatteryLow.php @@ -13,10 +13,15 @@ class BatteryLow extends Notification { use Queueable; + private Device $device; + /** * Create a new notification instance. */ - public function __construct(private Device $device) {} + public function __construct(Device $device) + { + $this->device = $device; + } /** * Get the notification's delivery channels. @@ -36,7 +41,7 @@ class BatteryLow extends Notification return (new MailMessage)->markdown('mail.battery-low', ['device' => $this->device]); } - public function toWebhook(object $notifiable): WebhookMessage + public function toWebhook(object $notifiable) { return WebhookMessage::create() ->data([ diff --git a/app/Notifications/Channels/WebhookChannel.php b/app/Notifications/Channels/WebhookChannel.php index 796cb24..d116200 100644 --- a/app/Notifications/Channels/WebhookChannel.php +++ b/app/Notifications/Channels/WebhookChannel.php @@ -11,7 +11,13 @@ use Illuminate\Support\Arr; class WebhookChannel extends Notification { - public function __construct(protected Client $client) {} + /** @var Client */ + protected $client; + + public function __construct(Client $client) + { + $this->client = $client; + } /** * Send the given notification. diff --git a/app/Notifications/Messages/WebhookMessage.php b/app/Notifications/Messages/WebhookMessage.php index 6dc58eb..920c16d 100644 --- a/app/Notifications/Messages/WebhookMessage.php +++ b/app/Notifications/Messages/WebhookMessage.php @@ -13,6 +13,13 @@ final class WebhookMessage extends Notification */ private $query; + /** + * The POST data of the Webhook request. + * + * @var mixed + */ + private $data; + /** * The headers to send with the request. * @@ -29,8 +36,9 @@ final class WebhookMessage extends Notification /** * @param mixed $data + * @return static */ - public static function create($data = ''): self + public static function create($data = '') { return new self($data); } @@ -38,12 +46,10 @@ final class WebhookMessage extends Notification /** * @param mixed $data */ - public function __construct( - /** - * The POST data of the Webhook request. - */ - private $data = '' - ) {} + public function __construct($data = '') + { + $this->data = $data; + } /** * Set the Webhook parameters to be URL encoded. @@ -51,7 +57,7 @@ final class WebhookMessage extends Notification * @param mixed $query * @return $this */ - public function query($query): self + public function query($query) { $this->query = $query; @@ -64,7 +70,7 @@ final class WebhookMessage extends Notification * @param mixed $data * @return $this */ - public function data($data): self + public function data($data) { $this->data = $data; @@ -78,7 +84,7 @@ final class WebhookMessage extends Notification * @param string $value * @return $this */ - public function header($name, $value): self + public function header($name, $value) { $this->headers[$name] = $value; @@ -91,7 +97,7 @@ final class WebhookMessage extends Notification * @param string $userAgent * @return $this */ - public function userAgent($userAgent): self + public function userAgent($userAgent) { $this->headers['User-Agent'] = $userAgent; @@ -103,14 +109,17 @@ final class WebhookMessage extends Notification * * @return $this */ - public function verify($value = true): self + public function verify($value = true) { $this->verify = $value; return $this; } - public function toArray(): array + /** + * @return array + */ + public function toArray() { return [ 'query' => $this->query, diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 48178e8..9e5761f 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,12 +2,8 @@ namespace App\Providers; -use App\Services\OidcProvider; -use App\Services\QrCodeService; -use Illuminate\Http\Request; -use Illuminate\Support\Facades\URL; use Illuminate\Support\ServiceProvider; -use Laravel\Socialite\Facades\Socialite; +use URL; class AppServiceProvider extends ServiceProvider { @@ -16,7 +12,7 @@ class AppServiceProvider extends ServiceProvider */ public function register(): void { - $this->app->bind('qr-code', fn () => new QrCodeService); + // } /** @@ -27,31 +23,5 @@ class AppServiceProvider extends ServiceProvider if (app()->isProduction() && config('app.force_https')) { URL::forceScheme('https'); } - - Request::macro('hasValidSignature', function ($absolute = true, array $ignoreQuery = []) { - $https = clone $this; - $https->server->set('HTTPS', 'on'); - - $http = clone $this; - $http->server->set('HTTPS', 'off'); - if (URL::hasValidSignature($https, $absolute, $ignoreQuery)) { - return true; - } - - return URL::hasValidSignature($http, $absolute, $ignoreQuery); - }); - - // Register OIDC provider with Socialite - Socialite::extend('oidc', function (\Illuminate\Contracts\Foundation\Application $app): OidcProvider { - $config = $app->make('config')->get('services.oidc', []); - - return new OidcProvider( - $app->make(Request::class), - $config['client_id'] ?? null, - $config['client_secret'] ?? null, - $config['redirect'] ?? null, - $config['scopes'] ?? ['openid', 'profile', 'email'] - ); - }); } } diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php deleted file mode 100644 index bf7a1b3..0000000 --- a/app/Providers/FortifyServiceProvider.php +++ /dev/null @@ -1,72 +0,0 @@ -configureActions(); - $this->configureViews(); - $this->configureRateLimiting(); - } - - /** - * Configure Fortify actions. - */ - private function configureActions(): void - { - Fortify::resetUserPasswordsUsing(ResetUserPassword::class); - Fortify::createUsersUsing(CreateNewUser::class); - } - - /** - * Configure Fortify views. - */ - private function configureViews(): void - { - Fortify::loginView(fn (): Factory|View => view('pages::auth.login')); - Fortify::verifyEmailView(fn (): Factory|View => view('pages::auth.verify-email')); - Fortify::twoFactorChallengeView(fn (): Factory|View => view('pages::auth.two-factor-challenge')); - Fortify::confirmPasswordView(fn (): Factory|View => view('pages::auth.confirm-password')); - Fortify::registerView(fn (): Factory|View => view('pages::auth.register')); - Fortify::resetPasswordView(fn (): Factory|View => view('pages::auth.reset-password')); - Fortify::requestPasswordResetLinkView(fn (): Factory|View => view('pages::auth.forgot-password')); - } - - /** - * Configure rate limiting. - */ - private function configureRateLimiting(): void - { - RateLimiter::for('two-factor', fn (Request $request) => Limit::perMinute(5)->by($request->session()->get('login.id'))); - - RateLimiter::for('login', function (Request $request) { - $throttleKey = Str::transliterate(Str::lower($request->input(Fortify::username())).'|'.$request->ip()); - - return Limit::perMinute(5)->by($throttleKey); - }); - } -} diff --git a/app/Providers/VoltServiceProvider.php b/app/Providers/VoltServiceProvider.php new file mode 100644 index 0000000..e61d984 --- /dev/null +++ b/app/Providers/VoltServiceProvider.php @@ -0,0 +1,28 @@ +find($deviceId); - $uuid = self::generateImageFromModel( - markup: $markup, - deviceModel: $device->deviceModel, - user: $device->user, - palette: $device->palette ?? $device->deviceModel?->palette, - device: $device - ); + $device = Device::find($deviceId); + $uuid = Uuid::uuid4()->toString(); + $pngPath = Storage::disk('public')->path('/images/generated/'.$uuid.'.png'); + $bmpPath = Storage::disk('public')->path('/images/generated/'.$uuid.'.bmp'); + + // Generate PNG + if (config('app.puppeteer_mode') === 'sidecar-aws') { + try { + $browsershot = BrowsershotLambda::html($markup) + ->windowSize(800, 480); + + if (config('app.puppeteer_wait_for_network_idle')) { + $browsershot->waitUntilNetworkIdle(); + } + + $browsershot->save($pngPath); + } catch (Exception $e) { + Log::error('Failed to generate PNG: '.$e->getMessage()); + throw new RuntimeException('Failed to generate PNG: '.$e->getMessage(), 0, $e); + } + } else { + try { + $browsershot = Browsershot::html($markup) + ->setOption('args', config('app.puppeteer_docker') ? ['--no-sandbox', '--disable-setuid-sandbox', '--disable-gpu'] : []) + ->windowSize(800, 480); + + if (config('app.puppeteer_wait_for_network_idle')) { + $browsershot->waitUntilNetworkIdle(); + } + $browsershot->save($pngPath); + } catch (Exception $e) { + Log::error('Failed to generate PNG: '.$e->getMessage()); + throw new RuntimeException('Failed to generate PNG: '.$e->getMessage(), 0, $e); + } + } + switch ($device->image_format) { + case ImageFormat::BMP3_1BIT_SRGB->value: + try { + self::convertToBmpImageMagick($pngPath, $bmpPath); + } catch (ImagickException $e) { + throw new RuntimeException('Failed to convert image to BMP: '.$e->getMessage(), 0, $e); + } + break; + case ImageFormat::PNG_8BIT_GRAYSCALE->value: + case ImageFormat::PNG_8BIT_256C->value: + try { + self::convertToPngImageMagick($pngPath, $device->width, $device->height, $device->rotate, quantize: $device->image_format === ImageFormat::PNG_8BIT_GRAYSCALE->value); + } catch (ImagickException $e) { + throw new RuntimeException('Failed to convert image to PNG: '.$e->getMessage(), 0, $e); + } + break; + case ImageFormat::AUTO->value: + default: + if (isset($device->last_firmware_version) + && version_compare($device->last_firmware_version, '1.5.2', '<')) { + try { + self::convertToBmpImageMagick($pngPath, $bmpPath); + } catch (ImagickException $e) { + throw new RuntimeException('Failed to convert image to BMP: '.$e->getMessage(), 0, $e); + } + } else { + try { + self::convertToPngImageMagick($pngPath, $device->width, $device->height, $device->rotate); + } catch (ImagickException $e) { + throw new RuntimeException('Failed to convert image to PNG: '.$e->getMessage(), 0, $e); + } + } + } $device->update(['current_screen_image' => $uuid]); Log::info("Device $device->id: updated with new image: $uuid"); @@ -41,274 +96,47 @@ class ImageGenerationService } /** - * Generate an image from markup using a DeviceModel - * - * @param string $markup The HTML markup to render - * @param DeviceModel|null $deviceModel The device model to use for image generation - * @param \App\Models\User|null $user Optional user for timezone settings - * @param \App\Models\DevicePalette|null $palette Optional palette, falls back to device model's palette - * @param Device|null $device Optional device for legacy devices without DeviceModel - * @return string The UUID of the generated image + * @throws ImagickException */ - public static function generateImageFromModel( - string $markup, - ?DeviceModel $deviceModel = null, - ?\App\Models\User $user = null, - ?\App\Models\DevicePalette $palette = null, - ?Device $device = null - ): string { - $uuid = Uuid::uuid4()->toString(); - - try { - // Get image generation settings from DeviceModel or Device (for legacy devices) - $imageSettings = $deviceModel instanceof DeviceModel - ? self::getImageSettingsFromModel($deviceModel) - : ($device instanceof Device ? self::getImageSettings($device) : self::getImageSettingsFromModel(null)); - - $fileExtension = $imageSettings['mime_type'] === 'image/bmp' ? 'bmp' : 'png'; - $outputPath = Storage::disk('public')->path('/images/generated/'.$uuid.'.'.$fileExtension); - - // Create custom Browsershot instance if using AWS Lambda - $browsershotInstance = null; - if (config('app.puppeteer_mode') === 'sidecar-aws') { - $browsershotInstance = new BrowsershotLambda(); - } - - $browserStage = new BrowserStage($browsershotInstance); - $browserStage->html($markup); - - // Set timezone from user or fall back to app timezone - $timezone = $user->timezone ?? config('app.timezone'); - $browserStage->timezone($timezone); - - if (config('app.puppeteer_window_size_strategy') === 'v2') { - $browserStage - ->width($imageSettings['width']) - ->height($imageSettings['height']); - } else { - // default behaviour for Framework v1 - $browserStage->useDefaultDimensions(); - } - - if (config('app.puppeteer_wait_for_network_idle')) { - $browserStage->setBrowsershotOption('waitUntil', 'networkidle0'); - } - - if (config('app.puppeteer_docker')) { - $browserStage->setBrowsershotOption('args', ['--no-sandbox', '--disable-setuid-sandbox', '--disable-gpu']); - } - - // Get palette from parameter or fallback to device model's default palette - $colorPalette = null; - if ($palette && $palette->colors) { - $colorPalette = $palette->colors; - } elseif ($deviceModel?->palette && $deviceModel->palette->colors) { - $colorPalette = $deviceModel->palette->colors; - } - - $imageStage = new ImageStage(); - $imageStage->format($fileExtension) - ->width($imageSettings['width']) - ->height($imageSettings['height']) - ->colors($imageSettings['colors']) - ->bitDepth($imageSettings['bit_depth']) - ->rotation($imageSettings['rotation']) - ->offsetX($imageSettings['offset_x']) - ->offsetY($imageSettings['offset_y']) - ->outputPath($outputPath); - - // Apply color palette if available - if ($colorPalette) { - $imageStage->colormap($colorPalette); - } - - // Apply dithering if requested by markup - $shouldDither = self::markupContainsDitherImage($markup); - if ($shouldDither) { - $imageStage->dither(); - } - - (new TrmnlPipeline())->pipe($browserStage) - ->pipe($imageStage) - ->process(); - - if (! file_exists($outputPath)) { - throw new RuntimeException('Image file was not created: '.$outputPath); - } - - if (filesize($outputPath) === 0) { - throw new RuntimeException('Image file is empty: '.$outputPath); - } - - Log::info("Generated image: $uuid"); - - return $uuid; - - } catch (Exception $e) { - Log::error('Failed to generate image: '.$e->getMessage()); - throw new RuntimeException('Failed to generate image: '.$e->getMessage(), 0, $e); - } + private static function convertToBmpImageMagick(string $pngPath, string $bmpPath): void + { + $imagick = new Imagick($pngPath); + $imagick->setImageType(Imagick::IMGTYPE_GRAYSCALE); + $imagick->quantizeImage(2, Imagick::COLORSPACE_GRAY, 0, true, false); + $imagick->setImageDepth(1); + $imagick->stripImage(); + $imagick->setFormat('BMP3'); + $imagick->writeImage($bmpPath); + $imagick->clear(); } /** - * Get image generation settings from DeviceModel if available, otherwise use device settings + * @throws ImagickException */ - private static function getImageSettings(Device $device): array + private static function convertToPngImageMagick(string $pngPath, ?int $width, ?int $height, ?int $rotate, $quantize = true): void { - // If device has a DeviceModel, use its settings - if ($device->deviceModel) { - return self::getImageSettingsFromModel($device->deviceModel); + $imagick = new Imagick($pngPath); + if ($width !== 800 || $height !== 480) { + $imagick->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1, true); + } + if ($rotate !== null && $rotate !== 0) { + $imagick->rotateImage(new ImagickPixel('black'), $rotate); } - // Fallback to device settings - $imageFormat = $device->image_format ?? ImageFormat::AUTO->value; - $mimeType = self::getMimeTypeFromImageFormat($imageFormat); - $colors = self::getColorsFromImageFormat($imageFormat); - $bitDepth = self::getBitDepthFromImageFormat($imageFormat); + $imagick->setImageType(Imagick::IMGTYPE_GRAYSCALE); - return [ - 'width' => $device->width ?? 800, - 'height' => $device->height ?? 480, - 'colors' => $colors, - 'bit_depth' => $bitDepth, - 'scale_factor' => 1.0, - 'rotation' => $device->rotate ?? 0, - 'mime_type' => $mimeType, - 'offset_x' => 0, - 'offset_y' => 0, - 'image_format' => $imageFormat, - 'use_model_settings' => false, - ]; - } + // Sharpen the image to make blurry text more defined + $imagick->sharpenImage(0.7, 0.5); - /** - * Get image generation settings from a DeviceModel - */ - private static function getImageSettingsFromModel(?DeviceModel $deviceModel): array - { - if ($deviceModel instanceof DeviceModel) { - return [ - 'width' => $deviceModel->width, - 'height' => $deviceModel->height, - 'colors' => $deviceModel->colors, - 'bit_depth' => $deviceModel->bit_depth, - 'scale_factor' => $deviceModel->scale_factor, - 'rotation' => $deviceModel->rotation, - 'mime_type' => $deviceModel->mime_type, - 'offset_x' => $deviceModel->offset_x, - 'offset_y' => $deviceModel->offset_y, - 'image_format' => self::determineImageFormatFromModel($deviceModel), - 'use_model_settings' => true, - ]; + if ($quantize) { + $imagick->quantizeImage(2, Imagick::COLORSPACE_GRAY, 0, true, false); } + $imagick->setImageDepth(8); + $imagick->stripImage(); - // Default settings if no device model provided - return [ - 'width' => 800, - 'height' => 480, - 'colors' => 2, - 'bit_depth' => 1, - 'scale_factor' => 1.0, - 'rotation' => 0, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'image_format' => ImageFormat::AUTO->value, - 'use_model_settings' => false, - ]; - } - - /** - * Determine the appropriate ImageFormat based on DeviceModel settings - */ - private static function determineImageFormatFromModel(DeviceModel $model): string - { - // Map DeviceModel settings to ImageFormat - if ($model->mime_type === 'image/bmp' && $model->bit_depth === 1) { - return ImageFormat::BMP3_1BIT_SRGB->value; - } - if ($model->mime_type === 'image/png' && $model->bit_depth === 8 && $model->colors === 2) { - return ImageFormat::PNG_8BIT_GRAYSCALE->value; - } - if ($model->mime_type === 'image/png' && $model->bit_depth === 8 && $model->colors === 256) { - return ImageFormat::PNG_8BIT_256C->value; - } - if ($model->mime_type === 'image/png' && $model->bit_depth === 2 && $model->colors === 4) { - return ImageFormat::PNG_2BIT_4C->value; - } - - // Default to AUTO for unknown combinations - return ImageFormat::AUTO->value; - } - - /** - * Get MIME type from ImageFormat - */ - private static function getMimeTypeFromImageFormat(string $imageFormat): string - { - return match ($imageFormat) { - ImageFormat::BMP3_1BIT_SRGB->value => 'image/bmp', - ImageFormat::PNG_8BIT_GRAYSCALE->value, - ImageFormat::PNG_8BIT_256C->value, - ImageFormat::PNG_2BIT_4C->value => 'image/png', - ImageFormat::AUTO->value => 'image/png', // Default for AUTO - default => 'image/png', - }; - } - - /** - * Get colors from ImageFormat - */ - private static function getColorsFromImageFormat(string $imageFormat): int - { - return match ($imageFormat) { - ImageFormat::BMP3_1BIT_SRGB->value, - ImageFormat::PNG_8BIT_GRAYSCALE->value => 2, - ImageFormat::PNG_8BIT_256C->value => 256, - ImageFormat::PNG_2BIT_4C->value => 4, - ImageFormat::AUTO->value => 2, // Default for AUTO - default => 2, - }; - } - - /** - * Get bit depth from ImageFormat - */ - private static function getBitDepthFromImageFormat(string $imageFormat): int - { - return match ($imageFormat) { - ImageFormat::BMP3_1BIT_SRGB->value, - ImageFormat::PNG_8BIT_GRAYSCALE->value => 1, - ImageFormat::PNG_8BIT_256C->value => 8, - ImageFormat::PNG_2BIT_4C->value => 2, - ImageFormat::AUTO->value => 1, // Default for AUTO - default => 1, - }; - } - - /** - * Detect whether the provided HTML markup contains an tag with class "image-dither". - */ - private static function markupContainsDitherImage(string $markup): bool - { - if (mb_trim($markup) === '') { - return false; - } - - // Find (or with single quotes) and inspect class tokens - $imgWithClassPattern = '/]*\bclass\s*=\s*(["\'])(.*?)\1[^>]*>/i'; - if (! preg_match_all($imgWithClassPattern, $markup, $matches)) { - return false; - } - - foreach ($matches[2] as $classValue) { - // Look for class token 'image-dither' or 'image--dither' - if (preg_match('/(?:^|\s)image--?dither(?:\s|$)/', $classValue)) { - return true; - } - } - - return false; + $imagick->setFormat('png'); + $imagick->writeImage($pngPath); + $imagick->clear(); } public static function cleanupFolder(): void @@ -334,208 +162,17 @@ class ImageGenerationService public static function resetIfNotCacheable(?Plugin $plugin): void { if ($plugin?->id) { - // Image webhook plugins have finalized images that shouldn't be reset - if ($plugin->plugin_type === 'image_webhook') { - return; - } - // Check if any devices have custom dimensions or use non-standard DeviceModels - $hasCustomDimensions = Device::query() - ->where(function ($query): void { - $query->where('width', '!=', 800) - ->orWhere('height', '!=', 480) - ->orWhere('rotate', '!=', 0); - }) - ->orWhereHas('deviceModel', function ($query): void { - // Only allow caching if all device models have standard dimensions (800x480, rotation=0) - $query->where(function ($subQuery): void { - $subQuery->where('width', '!=', 800) - ->orWhere('height', '!=', 480) - ->orWhere('rotation', '!=', 0); - }); - }) - ->exists(); - - if ($hasCustomDimensions) { + if ( + Device::query() + ->where('width', '!=', 800) + ->orWhere('height', '!=', 480) + ->orWhere('rotate', '!=', 0) + ->exists() + ) { // TODO cache image per device $plugin->update(['current_image' => null]); - Log::debug('Skip cache as devices with custom dimensions or non-standard DeviceModels exist'); + Log::debug('Skip cache as devices with other dimensions exist'); } } } - - /** - * Get device-specific default image path for setup or sleep mode - */ - public static function getDeviceSpecificDefaultImage(Device $device, string $imageType): ?string - { - // Validate image type - if (! in_array($imageType, ['setup-logo', 'sleep', 'error'])) { - return null; - } - - // If device has a DeviceModel, try to find device-specific image - if ($device->deviceModel) { - $model = $device->deviceModel; - $extension = $model->mime_type === 'image/bmp' ? 'bmp' : 'png'; - $filename = "{$model->width}_{$model->height}_{$model->bit_depth}_{$model->rotation}.{$extension}"; - $deviceSpecificPath = "images/default-screens/{$imageType}_{$filename}"; - - if (Storage::disk('public')->exists($deviceSpecificPath)) { - return $deviceSpecificPath; - } - } - - // Fallback to original hardcoded images - $fallbackPath = "images/{$imageType}.bmp"; - if (Storage::disk('public')->exists($fallbackPath)) { - return $fallbackPath; - } - - // Try PNG fallback - $fallbackPathPng = "images/{$imageType}.png"; - if (Storage::disk('public')->exists($fallbackPathPng)) { - return $fallbackPathPng; - } - - return null; - } - - /** - * Generate a default screen image from Blade template - */ - public static function generateDefaultScreenImage(Device $device, string $imageType, ?string $pluginName = null): string - { - // Validate image type - if (! in_array($imageType, ['setup-logo', 'sleep', 'error'])) { - throw new InvalidArgumentException("Invalid image type: {$imageType}"); - } - - $uuid = Uuid::uuid4()->toString(); - - try { - // Load device with relationships - $device->load(['palette', 'deviceModel.palette', 'user']); - - // Get image generation settings from DeviceModel if available, otherwise use device settings - $imageSettings = self::getImageSettings($device); - - $fileExtension = $imageSettings['mime_type'] === 'image/bmp' ? 'bmp' : 'png'; - $outputPath = Storage::disk('public')->path('/images/generated/'.$uuid.'.'.$fileExtension); - - // Generate HTML from Blade template - $html = self::generateDefaultScreenHtml($device, $imageType, $pluginName); - - // Create custom Browsershot instance if using AWS Lambda - $browsershotInstance = null; - if (config('app.puppeteer_mode') === 'sidecar-aws') { - $browsershotInstance = new BrowsershotLambda(); - } - - $browserStage = new BrowserStage($browsershotInstance); - $browserStage->html($html); - - // Set timezone from user or fall back to app timezone - $timezone = $device->user->timezone ?? config('app.timezone'); - $browserStage->timezone($timezone); - - if (config('app.puppeteer_window_size_strategy') === 'v2') { - $browserStage - ->width($imageSettings['width']) - ->height($imageSettings['height']); - } else { - $browserStage->useDefaultDimensions(); - } - - if (config('app.puppeteer_wait_for_network_idle')) { - $browserStage->setBrowsershotOption('waitUntil', 'networkidle0'); - } - - if (config('app.puppeteer_docker')) { - $browserStage->setBrowsershotOption('args', ['--no-sandbox', '--disable-setuid-sandbox', '--disable-gpu']); - } - - // Get palette from device or fallback to device model's default palette - $palette = $device->palette ?? $device->deviceModel?->palette; - $colorPalette = null; - - if ($palette && $palette->colors) { - $colorPalette = $palette->colors; - } - - $imageStage = new ImageStage(); - $imageStage->format($fileExtension) - ->width($imageSettings['width']) - ->height($imageSettings['height']) - ->colors($imageSettings['colors']) - ->bitDepth($imageSettings['bit_depth']) - ->rotation($imageSettings['rotation']) - ->offsetX($imageSettings['offset_x']) - ->offsetY($imageSettings['offset_y']) - ->outputPath($outputPath); - - // Apply color palette if available - if ($colorPalette) { - $imageStage->colormap($colorPalette); - } - - (new TrmnlPipeline())->pipe($browserStage) - ->pipe($imageStage) - ->process(); - - if (! file_exists($outputPath)) { - throw new RuntimeException('Image file was not created: '.$outputPath); - } - - if (filesize($outputPath) === 0) { - throw new RuntimeException('Image file is empty: '.$outputPath); - } - - Log::info("Device $device->id: generated default screen image: $uuid for type: $imageType"); - - return $uuid; - - } catch (Exception $e) { - Log::error('Failed to generate default screen image: '.$e->getMessage()); - throw new RuntimeException('Failed to generate default screen image: '.$e->getMessage(), 0, $e); - } - } - - /** - * Generate HTML from Blade template for default screens - */ - private static function generateDefaultScreenHtml(Device $device, string $imageType, ?string $pluginName = null): string - { - // Map image type to template name - $templateName = match ($imageType) { - 'setup-logo' => 'default-screens.setup', - 'sleep' => 'default-screens.sleep', - 'error' => 'default-screens.error', - default => throw new InvalidArgumentException("Invalid image type: {$imageType}") - }; - - // Determine device properties from DeviceModel or device settings - $deviceVariant = $device->deviceVariant(); - $deviceOrientation = $device->rotate > 0 ? 'portrait' : 'landscape'; - $colorDepth = $device->colorDepth() ?? '1bit'; - $scaleLevel = $device->scaleLevel(); - $darkMode = $imageType === 'sleep'; // Sleep mode uses dark mode, setup uses light mode - - // Build view data - $viewData = [ - 'noBleed' => false, - 'darkMode' => $darkMode, - 'deviceVariant' => $deviceVariant, - 'deviceOrientation' => $deviceOrientation, - 'colorDepth' => $colorDepth, - 'scaleLevel' => $scaleLevel, - ]; - - // Add plugin name for error screens - if ($imageType === 'error' && $pluginName !== null) { - $viewData['pluginName'] = $pluginName; - } - - // Render the Blade template - return view($templateName, $viewData)->render(); - } } diff --git a/app/Services/OidcProvider.php b/app/Services/OidcProvider.php deleted file mode 100644 index 8ea2e44..0000000 --- a/app/Services/OidcProvider.php +++ /dev/null @@ -1,158 +0,0 @@ -baseUrl = str_replace('/.well-known/openid-configuration', '', $endpoint); - } else { - $this->baseUrl = mb_rtrim($endpoint, '/'); - } - - $this->scopes = $scopes ?: ['openid', 'profile', 'email']; - $this->loadOidcConfiguration(); - } - - /** - * Load OIDC configuration from the well-known endpoint. - */ - protected function loadOidcConfiguration() - { - try { - $url = $this->baseUrl.'/.well-known/openid-configuration'; - $client = app(Client::class); - $response = $client->get($url); - $this->oidcConfig = json_decode($response->getBody()->getContents(), true); - - if (! $this->oidcConfig) { - throw new Exception('OIDC configuration is empty or invalid JSON'); - } - - if (! isset($this->oidcConfig['authorization_endpoint'])) { - throw new Exception('authorization_endpoint not found in OIDC configuration'); - } - - } catch (Exception $e) { - throw new Exception('Failed to load OIDC configuration: '.$e->getMessage(), $e->getCode(), $e); - } - } - - /** - * Get the authentication URL for the provider. - */ - protected function getAuthUrl($state) - { - if (! $this->oidcConfig || ! isset($this->oidcConfig['authorization_endpoint'])) { - throw new Exception('OIDC configuration not loaded or authorization_endpoint not found.'); - } - - return $this->buildAuthUrlFromBase($this->oidcConfig['authorization_endpoint'], $state); - } - - /** - * Get the token URL for the provider. - */ - protected function getTokenUrl() - { - if (! $this->oidcConfig || ! isset($this->oidcConfig['token_endpoint'])) { - throw new Exception('OIDC configuration not loaded or token_endpoint not found.'); - } - - return $this->oidcConfig['token_endpoint']; - } - - /** - * Get the raw user for the given access token. - */ - protected function getUserByToken($token) - { - if (! $this->oidcConfig || ! isset($this->oidcConfig['userinfo_endpoint'])) { - throw new Exception('OIDC configuration not loaded or userinfo_endpoint not found.'); - } - - $response = $this->getHttpClient()->get($this->oidcConfig['userinfo_endpoint'], [ - 'headers' => [ - 'Authorization' => 'Bearer '.$token, - ], - ]); - - return json_decode($response->getBody(), true); - } - - /** - * Map the raw user array to a Socialite User instance. - */ - public function mapUserToObject(array $user) - { - return (new User)->setRaw($user)->map([ - 'id' => $user['sub'], - 'nickname' => $user['preferred_username'] ?? null, - 'name' => $user['name'] ?? null, - 'email' => $user['email'] ?? null, - 'avatar' => $user['picture'] ?? null, - ]); - } - - /** - * Get the access token response for the given code. - */ - public function getAccessTokenResponse($code) - { - $response = $this->getHttpClient()->post($this->getTokenUrl(), [ - 'headers' => ['Accept' => 'application/json'], - 'form_params' => $this->getTokenFields($code), - ]); - - return json_decode($response->getBody(), true); - } - - /** - * Get the POST fields for the token request. - */ - protected function getTokenFields($code) - { - return array_merge(parent::getTokenFields($code), [ - 'grant_type' => 'authorization_code', - ]); - } -} diff --git a/app/Services/Plugin/Parsers/IcalResponseParser.php b/app/Services/Plugin/Parsers/IcalResponseParser.php deleted file mode 100644 index c8f2b58..0000000 --- a/app/Services/Plugin/Parsers/IcalResponseParser.php +++ /dev/null @@ -1,111 +0,0 @@ -header('Content-Type'); - $body = $response->body(); - - if (! $this->isIcalResponse($contentType, $body)) { - return null; - } - - try { - $this->parser->parseString($body); - - $events = $this->parser->getEvents()->sorted()->getArrayCopy(); - $windowStart = now()->subDays(7); - $windowEnd = now()->addDays(30); - - $filteredEvents = array_values(array_filter($events, function (array $event) use ($windowStart, $windowEnd): bool { - $startDate = $this->asCarbon($event['DTSTART'] ?? null); - - if (! $startDate instanceof Carbon) { - return false; - } - - return $startDate->between($windowStart, $windowEnd, true); - })); - - $normalizedEvents = array_map($this->normalizeIcalEvent(...), $filteredEvents); - - return ['ical' => $normalizedEvents]; - } catch (Exception $exception) { - Log::warning('Failed to parse iCal response: '.$exception->getMessage()); - - return ['error' => 'Failed to parse iCal response']; - } - } - - private function isIcalResponse(?string $contentType, string $body): bool - { - $normalizedContentType = $contentType ? mb_strtolower($contentType) : ''; - - if ($normalizedContentType && str_contains($normalizedContentType, 'text/calendar')) { - return true; - } - - return str_contains($body, 'BEGIN:VCALENDAR'); - } - - private function asCarbon(DateTimeInterface|string|null $value): ?Carbon - { - if ($value instanceof Carbon) { - return $value; - } - - if ($value instanceof DateTimeInterface) { - return Carbon::instance($value); - } - - if (is_string($value) && $value !== '') { - try { - return Carbon::parse($value); - } catch (Exception $exception) { - Log::warning('Failed to parse date value: '.$exception->getMessage()); - - return null; - } - } - - return null; - } - - private function normalizeIcalEvent(array $event): array - { - $normalized = []; - - foreach ($event as $key => $value) { - $normalized[$key] = $this->normalizeIcalValue($value); - } - - return $normalized; - } - - private function normalizeIcalValue(mixed $value): mixed - { - if ($value instanceof DateTimeInterface) { - return Carbon::instance($value)->toAtomString(); - } - - if (is_array($value)) { - return array_map($this->normalizeIcalValue(...), $value); - } - - return $value; - } -} diff --git a/app/Services/Plugin/Parsers/JsonOrTextResponseParser.php b/app/Services/Plugin/Parsers/JsonOrTextResponseParser.php deleted file mode 100644 index 44ea0cb..0000000 --- a/app/Services/Plugin/Parsers/JsonOrTextResponseParser.php +++ /dev/null @@ -1,26 +0,0 @@ -json(); - if ($json !== null) { - return $json; - } - - return ['data' => $response->body()]; - } catch (Exception $e) { - Log::warning('Failed to parse JSON response: '.$e->getMessage()); - - return ['error' => 'Failed to parse JSON response']; - } - } -} diff --git a/app/Services/Plugin/Parsers/ResponseParser.php b/app/Services/Plugin/Parsers/ResponseParser.php deleted file mode 100644 index b8f9c05..0000000 --- a/app/Services/Plugin/Parsers/ResponseParser.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ - private readonly array $parsers; - - /** - * @param array $parsers - */ - public function __construct(array $parsers = []) - { - $this->parsers = $parsers ?: [ - new XmlResponseParser(), - new IcalResponseParser(), - new JsonOrTextResponseParser(), - ]; - } - - /** - * @return array - */ - public function getParsers(): array - { - return $this->parsers; - } -} diff --git a/app/Services/Plugin/Parsers/XmlResponseParser.php b/app/Services/Plugin/Parsers/XmlResponseParser.php deleted file mode 100644 index b82ba80..0000000 --- a/app/Services/Plugin/Parsers/XmlResponseParser.php +++ /dev/null @@ -1,46 +0,0 @@ -header('Content-Type'); - - if (! $contentType || ! str_contains(mb_strtolower($contentType), 'xml')) { - return null; - } - - try { - $xml = simplexml_load_string($response->body()); - if ($xml === false) { - throw new Exception('Invalid XML content'); - } - - return ['rss' => $this->xmlToArray($xml)]; - } catch (Exception $exception) { - Log::warning('Failed to parse XML response: '.$exception->getMessage()); - - return ['error' => 'Failed to parse XML response']; - } - } - - private function xmlToArray(SimpleXMLElement $xml): array - { - $array = (array) $xml; - - foreach ($array as $key => $value) { - if ($value instanceof SimpleXMLElement) { - $array[$key] = $this->xmlToArray($value); - } - } - - return $array; - } -} diff --git a/app/Services/PluginExportService.php b/app/Services/PluginExportService.php deleted file mode 100644 index 241764d..0000000 --- a/app/Services/PluginExportService.php +++ /dev/null @@ -1,172 +0,0 @@ -generateSettingsYaml($plugin); - $settingsYaml = Yaml::dump($settings, 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); - File::put($tempDir.'/settings.yml', $settingsYaml); - // Generate full template content - $fullTemplate = $this->generateFullTemplate($plugin); - $extension = $plugin->markup_language === 'liquid' ? 'liquid' : 'blade.php'; - File::put($tempDir.'/full.'.$extension, $fullTemplate); - // Generate shared.liquid if needed (for liquid templates) - if ($plugin->markup_language === 'liquid') { - $sharedTemplate = $this->generateSharedTemplate(); - /** @phpstan-ignore-next-line */ - if ($sharedTemplate) { - File::put($tempDir.'/shared.liquid', $sharedTemplate); - } - } - // Create ZIP file - $zipPath = $tempDir.'/plugin_'.$plugin->trmnlp_id.'.zip'; - $zip = new ZipArchive(); - if ($zip->open($zipPath, ZipArchive::CREATE) !== true) { - throw new Exception('Could not create ZIP file.'); - } - // Add files directly to ZIP root - $this->addDirectoryToZip($zip, $tempDir, ''); - $zip->close(); - - // Return the ZIP file as a download response - return response()->download($zipPath, 'plugin_'.$plugin->trmnlp_id.'.zip'); - } - - /** - * Generate the settings.yml content for the plugin - */ - private function generateSettingsYaml(Plugin $plugin): array - { - $settings = []; - - // Add fields in the specific order requested - $settings['name'] = $plugin->name; - $settings['no_screen_padding'] = 'no'; // Default value - $settings['dark_mode'] = 'no'; // Default value - $settings['strategy'] = $plugin->data_strategy; - - // Add static data if available - if ($plugin->data_payload) { - $settings['static_data'] = json_encode($plugin->data_payload, JSON_PRETTY_PRINT); - } - - // Add polling configuration if applicable - if ($plugin->data_strategy === 'polling') { - if ($plugin->polling_verb) { - $settings['polling_verb'] = $plugin->polling_verb; - } - if ($plugin->polling_url) { - $settings['polling_url'] = $plugin->polling_url; - } - if ($plugin->polling_header) { - // Convert header format from "key: value" to "key=value" - $settings['polling_headers'] = str_replace(':', '=', $plugin->polling_header); - } - if ($plugin->polling_body) { - $settings['polling_body'] = $plugin->polling_body; - } - } - - $settings['refresh_interval'] = $plugin->data_stale_minutes; - $settings['id'] = $plugin->trmnlp_id; - - // Add custom fields from configuration template - if (isset($plugin->configuration_template['custom_fields'])) { - $settings['custom_fields'] = $plugin->configuration_template['custom_fields']; - } - - return $settings; - } - - /** - * Generate the full template content - */ - private function generateFullTemplate(Plugin $plugin): string - { - $markup = $plugin->render_markup; - - // Remove the wrapper div if it exists (it will be added during import) - $markup = preg_replace('/^
\s*/', '', $markup); - $markup = preg_replace('/\s*<\/div>\s*$/', '', $markup); - - return mb_trim($markup); - } - - /** - * Generate the shared template content (for liquid templates) - */ - private function generateSharedTemplate(): null - { - // For now, we don't have a way to store shared templates separately - // TODO - add support for shared templates - return null; - } - - /** - * Add a directory and its contents to a ZIP file - */ - private function addDirectoryToZip(ZipArchive $zip, string $dirPath, string $zipPath): void - { - $files = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($dirPath), - RecursiveIteratorIterator::LEAVES_ONLY - ); - - foreach ($files as $file) { - if (! $file->isDir()) { - $filePath = $file->getRealPath(); - $fileName = basename((string) $filePath); - - // For root directory, just use the filename - $relativePath = $zipPath === '' ? $fileName : $zipPath.'/'.mb_substr((string) $filePath, mb_strlen($dirPath) + 1); - - $zip->addFile($filePath, $relativePath); - } - } - } -} diff --git a/app/Services/PluginImportService.php b/app/Services/PluginImportService.php deleted file mode 100644 index 51a9aee..0000000 --- a/app/Services/PluginImportService.php +++ /dev/null @@ -1,598 +0,0 @@ -getRealPath(); - - // Extract the ZIP file using ZipArchive - $zip = new ZipArchive(); - if ($zip->open($zipFullPath) !== true) { - throw new Exception('Could not open the ZIP file.'); - } - - $zip->extractTo($tempDir); - $zip->close(); - - // Find the required files (settings.yml and full.liquid/full.blade.php/shared.liquid/shared.blade.php) - $filePaths = $this->findRequiredFiles($tempDir, $zipEntryPath); - - // Validate that we found the required files - if (! $filePaths['settingsYamlPath']) { - throw new Exception('Invalid ZIP structure. Required file settings.yml is missing.'); - } - - // Validate that we have at least one template file - if (! $filePaths['fullLiquidPath'] && ! $filePaths['sharedLiquidPath'] && ! $filePaths['sharedBladePath']) { - throw new Exception('Invalid ZIP structure. At least one of the following files is required: full.liquid, full.blade.php, shared.liquid, or shared.blade.php.'); - } - - // Parse settings.yml - $settingsYaml = File::get($filePaths['settingsYamlPath']); - $settings = Yaml::parse($settingsYaml); - $this->validateYAML($settings); - - // Determine which template file to use and read its content - $templatePath = null; - $markupLanguage = 'blade'; - - if ($filePaths['fullLiquidPath']) { - $templatePath = $filePaths['fullLiquidPath']; - $fullLiquid = File::get($templatePath); - - // Prepend shared.liquid or shared.blade.php content if available - if ($filePaths['sharedLiquidPath'] && File::exists($filePaths['sharedLiquidPath'])) { - $sharedLiquid = File::get($filePaths['sharedLiquidPath']); - $fullLiquid = $sharedLiquid."\n".$fullLiquid; - } elseif ($filePaths['sharedBladePath'] && File::exists($filePaths['sharedBladePath'])) { - $sharedBlade = File::get($filePaths['sharedBladePath']); - $fullLiquid = $sharedBlade."\n".$fullLiquid; - } - - // Check if the file ends with .liquid to set markup language - if (pathinfo((string) $templatePath, PATHINFO_EXTENSION) === 'liquid') { - $markupLanguage = 'liquid'; - $fullLiquid = '
'."\n".$fullLiquid."\n".'
'; - } - } elseif ($filePaths['sharedLiquidPath']) { - $templatePath = $filePaths['sharedLiquidPath']; - $fullLiquid = File::get($templatePath); - $markupLanguage = 'liquid'; - $fullLiquid = '
'."\n".$fullLiquid."\n".'
'; - } elseif ($filePaths['sharedBladePath']) { - $templatePath = $filePaths['sharedBladePath']; - $fullLiquid = File::get($templatePath); - $markupLanguage = 'blade'; - } - - // Ensure custom_fields is properly formatted - if (! isset($settings['custom_fields']) || ! is_array($settings['custom_fields'])) { - $settings['custom_fields'] = []; - } - - // Normalize options in custom_fields (convert non-named values to named values) - $settings['custom_fields'] = $this->normalizeCustomFieldsOptions($settings['custom_fields']); - - // Create configuration template with the custom fields - $configurationTemplate = [ - 'custom_fields' => $settings['custom_fields'], - ]; - - $plugin_updated = isset($settings['id']) - && Plugin::where('user_id', $user->id)->where('trmnlp_id', $settings['id'])->exists(); - // Create a new plugin - $plugin = Plugin::updateOrCreate( - [ - 'user_id' => $user->id, 'trmnlp_id' => $settings['id'] ?? Uuid::v7(), - ], - [ - 'user_id' => $user->id, - 'name' => $settings['name'] ?? 'Imported Plugin', - 'trmnlp_id' => $settings['id'] ?? Uuid::v7(), - 'data_stale_minutes' => $settings['refresh_interval'] ?? 15, - 'data_strategy' => $settings['strategy'] ?? 'static', - 'polling_url' => $settings['polling_url'] ?? null, - 'polling_verb' => $settings['polling_verb'] ?? 'get', - 'polling_header' => isset($settings['polling_headers']) - ? str_replace('=', ':', $settings['polling_headers']) - : null, - 'polling_body' => $settings['polling_body'] ?? null, - 'markup_language' => $markupLanguage, - 'render_markup' => $fullLiquid ?? null, - 'configuration_template' => $configurationTemplate, - 'data_payload' => json_decode($settings['static_data'] ?? '{}', true), - ]); - - if (! $plugin_updated) { - // Extract default values from custom_fields and populate configuration - $configuration = []; - foreach ($settings['custom_fields'] as $field) { - if (isset($field['keyname']) && isset($field['default'])) { - $configuration[$field['keyname']] = $field['default']; - } - } - // set only if plugin is new - $plugin->update([ - 'configuration' => $configuration, - ]); - } - $plugin['trmnlp_yaml'] = $settingsYaml; - - return $plugin; - - } finally { - // Clean up temporary directory - Storage::deleteDirectory($tempDirName); - } - } - - /** - * Import a plugin from a ZIP URL - * - * @param string $zipUrl The URL to the ZIP file - * @param User $user The user importing the plugin - * @param string|null $zipEntryPath Optional path to specific plugin in monorepo - * @param string|null $preferredRenderer Optional preferred renderer (e.g., 'trmnl-liquid') - * @param string|null $iconUrl Optional icon URL to set on the plugin - * @param bool $allowDuplicate If true, generate a new UUID for trmnlp_id if a plugin with the same trmnlp_id already exists - * @return Plugin The created plugin instance - * - * @throws Exception If the ZIP file is invalid or required files are missing - */ - public function importFromUrl(string $zipUrl, User $user, ?string $zipEntryPath = null, $preferredRenderer = null, ?string $iconUrl = null, bool $allowDuplicate = false): Plugin - { - // Download the ZIP file - $response = Http::timeout(60)->get($zipUrl); - - if (! $response->successful()) { - throw new Exception('Could not download the ZIP file from the provided URL.'); - } - - // Create a temporary file - $tempDirName = 'temp/'.uniqid('plugin_import_', true); - Storage::makeDirectory($tempDirName); - $tempDir = Storage::path($tempDirName); - $zipPath = $tempDir.'/plugin.zip'; - - // Save the downloaded content to a temporary file - File::put($zipPath, $response->body()); - - try { - // Extract the ZIP file using ZipArchive - $zip = new ZipArchive(); - if ($zip->open($zipPath) !== true) { - throw new Exception('Could not open the downloaded ZIP file.'); - } - - $zip->extractTo($tempDir); - $zip->close(); - - // Find the required files (settings.yml and full.liquid/full.blade.php/shared.liquid/shared.blade.php) - $filePaths = $this->findRequiredFiles($tempDir, $zipEntryPath); - - // Validate that we found the required files - if (! $filePaths['settingsYamlPath']) { - throw new Exception('Invalid ZIP structure. Required file settings.yml is missing.'); - } - - // Validate that we have at least one template file - if (! $filePaths['fullLiquidPath'] && ! $filePaths['sharedLiquidPath'] && ! $filePaths['sharedBladePath']) { - throw new Exception('Invalid ZIP structure. At least one of the following files is required: full.liquid, full.blade.php, shared.liquid, or shared.blade.php.'); - } - - // Parse settings.yml - $settingsYaml = File::get($filePaths['settingsYamlPath']); - $settings = Yaml::parse($settingsYaml); - $this->validateYAML($settings); - - // Determine which template file to use and read its content - $templatePath = null; - $markupLanguage = 'blade'; - - if ($filePaths['fullLiquidPath']) { - $templatePath = $filePaths['fullLiquidPath']; - $fullLiquid = File::get($templatePath); - - // Prepend shared.liquid or shared.blade.php content if available - if ($filePaths['sharedLiquidPath'] && File::exists($filePaths['sharedLiquidPath'])) { - $sharedLiquid = File::get($filePaths['sharedLiquidPath']); - $fullLiquid = $sharedLiquid."\n".$fullLiquid; - } elseif ($filePaths['sharedBladePath'] && File::exists($filePaths['sharedBladePath'])) { - $sharedBlade = File::get($filePaths['sharedBladePath']); - $fullLiquid = $sharedBlade."\n".$fullLiquid; - } - - // Check if the file ends with .liquid to set markup language - if (pathinfo((string) $templatePath, PATHINFO_EXTENSION) === 'liquid') { - $markupLanguage = 'liquid'; - $fullLiquid = '
'."\n".$fullLiquid."\n".'
'; - } - } elseif ($filePaths['sharedLiquidPath']) { - $templatePath = $filePaths['sharedLiquidPath']; - $fullLiquid = File::get($templatePath); - $markupLanguage = 'liquid'; - $fullLiquid = '
'."\n".$fullLiquid."\n".'
'; - } elseif ($filePaths['sharedBladePath']) { - $templatePath = $filePaths['sharedBladePath']; - $fullLiquid = File::get($templatePath); - $markupLanguage = 'blade'; - } - - // Ensure custom_fields is properly formatted - if (! isset($settings['custom_fields']) || ! is_array($settings['custom_fields'])) { - $settings['custom_fields'] = []; - } - - // Normalize options in custom_fields (convert non-named values to named values) - $settings['custom_fields'] = $this->normalizeCustomFieldsOptions($settings['custom_fields']); - - // Create configuration template with the custom fields - $configurationTemplate = [ - 'custom_fields' => $settings['custom_fields'], - ]; - - // Determine the trmnlp_id to use - $trmnlpId = $settings['id'] ?? Uuid::v7(); - - // If allowDuplicate is true and a plugin with this trmnlp_id already exists, generate a new UUID - if ($allowDuplicate && isset($settings['id']) && Plugin::where('user_id', $user->id)->where('trmnlp_id', $settings['id'])->exists()) { - $trmnlpId = Uuid::v7(); - } - - $plugin_updated = ! $allowDuplicate && isset($settings['id']) - && Plugin::where('user_id', $user->id)->where('trmnlp_id', $settings['id'])->exists(); - - // Create a new plugin - $plugin = Plugin::updateOrCreate( - [ - 'user_id' => $user->id, 'trmnlp_id' => $trmnlpId, - ], - [ - 'user_id' => $user->id, - 'name' => $settings['name'] ?? 'Imported Plugin', - 'trmnlp_id' => $trmnlpId, - 'data_stale_minutes' => $settings['refresh_interval'] ?? 15, - 'data_strategy' => $settings['strategy'] ?? 'static', - 'polling_url' => $settings['polling_url'] ?? null, - 'polling_verb' => $settings['polling_verb'] ?? 'get', - 'polling_header' => isset($settings['polling_headers']) - ? str_replace('=', ':', $settings['polling_headers']) - : null, - 'polling_body' => $settings['polling_body'] ?? null, - 'markup_language' => $markupLanguage, - 'render_markup' => $fullLiquid ?? null, - 'configuration_template' => $configurationTemplate, - 'data_payload' => json_decode($settings['static_data'] ?? '{}', true), - 'preferred_renderer' => $preferredRenderer, - 'icon_url' => $iconUrl, - ]); - - if (! $plugin_updated) { - // Extract default values from custom_fields and populate configuration - $configuration = []; - foreach ($settings['custom_fields'] as $field) { - if (isset($field['keyname']) && isset($field['default'])) { - $configuration[$field['keyname']] = $field['default']; - } - } - // set only if plugin is new - $plugin->update([ - 'configuration' => $configuration, - ]); - } - $plugin['trmnlp_yaml'] = $settingsYaml; - - return $plugin; - - } finally { - // Clean up temporary directory - Storage::deleteDirectory($tempDirName); - } - } - - private function findRequiredFiles(string $tempDir, ?string $zipEntryPath = null): array - { - $settingsYamlPath = null; - $fullLiquidPath = null; - $sharedLiquidPath = null; - $sharedBladePath = null; - - // If zipEntryPath is specified, look for files in that specific directory first - if ($zipEntryPath) { - $targetDir = $tempDir.'/'.$zipEntryPath; - if (File::exists($targetDir)) { - // Check if files are directly in the target directory - if (File::exists($targetDir.'/settings.yml')) { - $settingsYamlPath = $targetDir.'/settings.yml'; - - if (File::exists($targetDir.'/full.liquid')) { - $fullLiquidPath = $targetDir.'/full.liquid'; - } elseif (File::exists($targetDir.'/full.blade.php')) { - $fullLiquidPath = $targetDir.'/full.blade.php'; - } - - if (File::exists($targetDir.'/shared.liquid')) { - $sharedLiquidPath = $targetDir.'/shared.liquid'; - } elseif (File::exists($targetDir.'/shared.blade.php')) { - $sharedBladePath = $targetDir.'/shared.blade.php'; - } - } - - // Check if files are in src subdirectory of target directory - if (! $settingsYamlPath && File::exists($targetDir.'/src/settings.yml')) { - $settingsYamlPath = $targetDir.'/src/settings.yml'; - - if (File::exists($targetDir.'/src/full.liquid')) { - $fullLiquidPath = $targetDir.'/src/full.liquid'; - } elseif (File::exists($targetDir.'/src/full.blade.php')) { - $fullLiquidPath = $targetDir.'/src/full.blade.php'; - } - - if (File::exists($targetDir.'/src/shared.liquid')) { - $sharedLiquidPath = $targetDir.'/src/shared.liquid'; - } elseif (File::exists($targetDir.'/src/shared.blade.php')) { - $sharedBladePath = $targetDir.'/src/shared.blade.php'; - } - } - - // If we found the required files in the target directory, return them - if ($settingsYamlPath && ($fullLiquidPath || $sharedLiquidPath || $sharedBladePath)) { - return [ - 'settingsYamlPath' => $settingsYamlPath, - 'fullLiquidPath' => $fullLiquidPath, - 'sharedLiquidPath' => $sharedLiquidPath, - 'sharedBladePath' => $sharedBladePath, - ]; - } - } - } - - // First, check if files are directly in the src folder - if (File::exists($tempDir.'/src/settings.yml')) { - $settingsYamlPath = $tempDir.'/src/settings.yml'; - - // Check for full.liquid or full.blade.php - if (File::exists($tempDir.'/src/full.liquid')) { - $fullLiquidPath = $tempDir.'/src/full.liquid'; - } elseif (File::exists($tempDir.'/src/full.blade.php')) { - $fullLiquidPath = $tempDir.'/src/full.blade.php'; - } - - // Check for shared.liquid or shared.blade.php in the same directory - if (File::exists($tempDir.'/src/shared.liquid')) { - $sharedLiquidPath = $tempDir.'/src/shared.liquid'; - } elseif (File::exists($tempDir.'/src/shared.blade.php')) { - $sharedBladePath = $tempDir.'/src/shared.blade.php'; - } - } else { - // Search for the files in the extracted directory structure - $directories = new RecursiveDirectoryIterator($tempDir, RecursiveDirectoryIterator::SKIP_DOTS); - $files = new RecursiveIteratorIterator($directories); - - foreach ($files as $file) { - $filename = $file->getFilename(); - $filepath = $file->getPathname(); - - if ($filename === 'settings.yml') { - $settingsYamlPath = $filepath; - } elseif ($filename === 'full.liquid' || $filename === 'full.blade.php') { - $fullLiquidPath = $filepath; - } elseif ($filename === 'shared.liquid') { - $sharedLiquidPath = $filepath; - } elseif ($filename === 'shared.blade.php') { - $sharedBladePath = $filepath; - } - } - - // Check if shared.liquid or shared.blade.php exists in the same directory as full.liquid - if ($settingsYamlPath && $fullLiquidPath && ! $sharedLiquidPath && ! $sharedBladePath) { - $fullLiquidDir = dirname((string) $fullLiquidPath); - if (File::exists($fullLiquidDir.'/shared.liquid')) { - $sharedLiquidPath = $fullLiquidDir.'/shared.liquid'; - } elseif (File::exists($fullLiquidDir.'/shared.blade.php')) { - $sharedBladePath = $fullLiquidDir.'/shared.blade.php'; - } - } - - // If we found the files but they're not in the src folder, - // check if they're in the root of the ZIP or in a subfolder - if ($settingsYamlPath && ($fullLiquidPath || $sharedLiquidPath || $sharedBladePath)) { - // If the files are in the root of the ZIP, create a src folder and move them there - $srcDir = dirname((string) $settingsYamlPath); - - // If the parent directory is not named 'src', create a src directory - if (basename($srcDir) !== 'src') { - $newSrcDir = $tempDir.'/src'; - File::makeDirectory($newSrcDir, 0755, true); - - // Copy the files to the src directory - File::copy($settingsYamlPath, $newSrcDir.'/settings.yml'); - - // Copy full.liquid or full.blade.php if it exists - if ($fullLiquidPath) { - $extension = pathinfo((string) $fullLiquidPath, PATHINFO_EXTENSION); - File::copy($fullLiquidPath, $newSrcDir.'/full.'.$extension); - $fullLiquidPath = $newSrcDir.'/full.'.$extension; - } - - // Copy shared.liquid or shared.blade.php if it exists - if ($sharedLiquidPath) { - File::copy($sharedLiquidPath, $newSrcDir.'/shared.liquid'); - $sharedLiquidPath = $newSrcDir.'/shared.liquid'; - } elseif ($sharedBladePath) { - File::copy($sharedBladePath, $newSrcDir.'/shared.blade.php'); - $sharedBladePath = $newSrcDir.'/shared.blade.php'; - } - - // Update the paths - $settingsYamlPath = $newSrcDir.'/settings.yml'; - } - } - } - - return [ - 'settingsYamlPath' => $settingsYamlPath, - 'fullLiquidPath' => $fullLiquidPath, - 'sharedLiquidPath' => $sharedLiquidPath, - 'sharedBladePath' => $sharedBladePath, - ]; - } - - /** - * Normalize options in custom_fields by converting non-named values to named values - * This ensures that options like ["true", "false"] become [["true" => "true"], ["false" => "false"]] - * - * @param array $customFields The custom_fields array from settings - * @return array The normalized custom_fields array - */ - private function normalizeCustomFieldsOptions(array $customFields): array - { - foreach ($customFields as &$field) { - // Only process select fields with options - if (isset($field['field_type']) && $field['field_type'] === 'select' && isset($field['options']) && is_array($field['options'])) { - $normalizedOptions = []; - foreach ($field['options'] as $option) { - // If option is already a named value (array with key-value pair), keep it as is - if (is_array($option)) { - $normalizedOptions[] = $option; - } else { - // Convert non-named value to named value - // Convert boolean to string, use lowercase for label - $value = is_bool($option) ? ($option ? 'true' : 'false') : (string) $option; - $normalizedOptions[] = [$value => $value]; - } - } - $field['options'] = $normalizedOptions; - - // Normalize default value to match normalized option values - if (isset($field['default'])) { - $default = $field['default']; - // If default is boolean, convert to string to match normalized options - if (is_bool($default)) { - $field['default'] = $default ? 'true' : 'false'; - } else { - // Convert to string to ensure consistency - $field['default'] = (string) $default; - } - } - } - } - - return $customFields; - } - - /** - * Validate that template and context are within command-line argument limits - * - * @param string $template The liquid template string - * @param string $jsonContext The JSON-encoded context - * @param string $liquidPath The path to the liquid renderer executable - * - * @throws Exception If the template or context exceeds argument limits - */ - public function validateExternalRendererArguments(string $template, string $jsonContext, string $liquidPath): void - { - // MAX_ARG_STRLEN on Linux is typically 131072 (128KB) for individual arguments - // ARG_MAX is the total size of all arguments (typically 2MB on modern systems) - $maxIndividualArgLength = 131072; // 128KB - MAX_ARG_STRLEN limit - $maxTotalArgLength = $this->getMaxArgumentLength(); - - // Check individual argument sizes (template and context are the largest) - if (mb_strlen($template) > $maxIndividualArgLength || mb_strlen($jsonContext) > $maxIndividualArgLength) { - throw new Exception('Context too large for external liquid renderer. Reduce the size of the Payload or Template.'); - } - - // Calculate total size of all arguments (path + flags + template + context) - // Add overhead for path, flags, and separators (conservative estimate: ~200 bytes) - $totalArgSize = mb_strlen($liquidPath) + mb_strlen('--template') + mb_strlen($template) - + mb_strlen('--context') + mb_strlen($jsonContext) + 200; - - if ($totalArgSize > $maxTotalArgLength) { - throw new Exception('Context too large for external liquid renderer. Reduce the size of the Payload or Template.'); - } - } - - /** - * Get the maximum argument length for command-line arguments - * - * @return int Maximum argument length in bytes - */ - private function getMaxArgumentLength(): int - { - // Try to get ARG_MAX from system using getconf - $argMax = null; - if (function_exists('shell_exec')) { - $result = @shell_exec('getconf ARG_MAX 2>/dev/null'); - if ($result !== null && is_numeric(mb_trim($result))) { - $argMax = (int) mb_trim($result); - } - } - - // Use conservative fallback if ARG_MAX cannot be determined - // ARG_MAX on macOS is typically 262144 (256KB), on Linux it's usually 2097152 (2MB) - // We use 200KB as a conservative limit that works on both systems - // Note: ARG_MAX includes environment variables, so we leave headroom - return $argMax !== null ? min($argMax, 204800) : 204800; - } -} diff --git a/app/Services/QrCodeService.php b/app/Services/QrCodeService.php deleted file mode 100644 index 812415b..0000000 --- a/app/Services/QrCodeService.php +++ /dev/null @@ -1,147 +0,0 @@ -format = $format; - - return $this; - } - - /** - * Set the size of the QR code - * - * @param int $size The size in pixels - * @return $this - */ - public function size(int $size): self - { - $this->size = $size; - - return $this; - } - - /** - * Set the error correction level - * - * @param string $level Error correction level: 'l', 'm', 'q', 'h' - * @return $this - */ - public function errorCorrection(string $level): self - { - $this->errorCorrection = $level; - - return $this; - } - - /** - * Generate the QR code - * - * @param string $text The text to encode - * @return string The generated QR code (SVG string) - */ - public function generate(string $text): string - { - // Ensure format is set (default to SVG) - $format = $this->format ?? 'svg'; - - if ($format !== 'svg') { - throw new InvalidArgumentException("Format '{$format}' is not supported. Only 'svg' is currently supported."); - } - - // Calculate size and margin - // If size is not set, calculate from module size (default module size is 11) - if ($this->size === null) { - $moduleSize = 11; - $this->size = 29 * $moduleSize; - } - - // Calculate margin: 4 modules on each side - // Module size = size / 29, so margin = (size / 29) * 4 - $moduleSize = $this->size / 29; - $margin = (int) ($moduleSize * 4); - - // Map error correction level - $errorCorrectionLevel = ErrorCorrectionLevel::valueOf('M'); // default - if ($this->errorCorrection !== null) { - $errorCorrectionLevel = match (mb_strtoupper($this->errorCorrection)) { - 'L' => ErrorCorrectionLevel::valueOf('L'), - 'M' => ErrorCorrectionLevel::valueOf('M'), - 'Q' => ErrorCorrectionLevel::valueOf('Q'), - 'H' => ErrorCorrectionLevel::valueOf('H'), - default => ErrorCorrectionLevel::valueOf('M'), - }; - } - - // Create renderer style with size and margin - $rendererStyle = new RendererStyle($this->size, $margin); - - // Create SVG renderer - $renderer = new ImageRenderer( - $rendererStyle, - new SvgImageBackEnd() - ); - - // Create writer - $writer = new Writer($renderer); - - // Generate SVG - $svg = $writer->writeString($text, 'ISO-8859-1', $errorCorrectionLevel); - - // Add class="qr-code" to the SVG element - $svg = $this->addQrCodeClass($svg); - - return $svg; - } - - /** - * Add the 'qr-code' class to the SVG element - * - * @param string $svg The SVG string - * @return string The SVG string with the class added - */ - protected function addQrCodeClass(string $svg): string - { - // Match - if (preg_match('/]*)>/', $svg, $matches)) { - $attributes = $matches[1]; - // Check if class already exists - if (mb_strpos($attributes, 'class=') === false) { - $svg = preg_replace('/]*)>/', '', $svg, 1); - } else { - // If class exists, add qr-code to it - $svg = preg_replace('/(]*class=["\'])([^"\']*)(["\'][^>]*>)/', '$1$2 qr-code$3', $svg, 1); - } - } else { - // Fallback: simple replacement if no attributes - $svg = preg_replace('//', '', $svg, 1); - } - - return $svg; - } -} diff --git a/bootstrap/providers.php b/bootstrap/providers.php index 0ad9c57..90915e8 100644 --- a/bootstrap/providers.php +++ b/bootstrap/providers.php @@ -2,5 +2,6 @@ return [ App\Providers\AppServiceProvider::class, - App\Providers\FortifyServiceProvider::class, + App\Providers\FolioServiceProvider::class, + App\Providers\VoltServiceProvider::class, ]; diff --git a/composer.json b/composer.json index a4951a0..be63349 100644 --- a/composer.json +++ b/composer.json @@ -4,46 +4,37 @@ "type": "project", "description": "TRMNL Server Implementation (BYOS) for Laravel", "keywords": [ - "trmnl", - "trmnl-server", - "trmnl-byos", - "laravel" + "laravel", + "framework", + "trmnl" ], "license": "MIT", "require": { "php": "^8.2", "ext-imagick": "*", - "ext-simplexml": "*", - "ext-zip": "*", - "bnussbau/laravel-trmnl-blade": "2.1.*", - "bnussbau/trmnl-pipeline-php": "^0.6.0", + "bnussbau/laravel-trmnl-blade": "1.1.*", + "intervention/image": "^3.11", "keepsuit/laravel-liquid": "^0.5.2", - "laravel/fortify": "^1.30", "laravel/framework": "^12.1", "laravel/sanctum": "^4.0", - "laravel/socialite": "^5.23", "laravel/tinker": "^2.10.1", "livewire/flux": "^2.0", - "livewire/livewire": "^4.0", - "om/icalparser": "^3.2", + "livewire/volt": "^1.7", "spatie/browsershot": "^5.0", - "stevebauman/purify": "^6.3", - "symfony/yaml": "^7.3", "wnx/sidecar-browsershot": "^2.6" }, "require-dev": { "fakerphp/faker": "^1.23", "larastan/larastan": "^3.0", - "laravel/boost": "^1.0", "laravel/pail": "^1.2.2", "laravel/pint": "^1.18", "laravel/sail": "^1.41", "mockery/mockery": "^1.6", "nunomaduro/collision": "^8.6", - "pestphp/pest": "^4.0", - "pestphp/pest-plugin-drift": "^4.0", - "pestphp/pest-plugin-laravel": "^4.0", - "rector/rector": "^2.1" + "pestphp/pest": "^3.7", + "pestphp/pest-plugin-drift": "^3.0", + "pestphp/pest-plugin-laravel": "^3.1", + "spatie/pest-expectations": "^1.10" }, "autoload": { "psr-4": { @@ -79,10 +70,7 @@ ], "test": "vendor/bin/pest", "test-coverage": "vendor/bin/pest --coverage", - "format": "vendor/bin/pint", - "analyse": "vendor/bin/phpstan analyse", - "analyze": "vendor/bin/phpstan analyse", - "rector": "vendor/bin/rector process" + "format": "vendor/bin/pint" }, "extra": { "laravel": { diff --git a/composer.lock b/composer.lock index 52a9ed0..da7185a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "cd2e6e87598cd99111e73d9ce8e0a9b8", + "content-hash": "29d4db93339349a577b09a89a73769f5", "packages": [ { "name": "aws/aws-crt-php", @@ -62,16 +62,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.369.14", + "version": "3.349.3", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "b40eb1177d2e621c18cd797ca6cc9efb5a0e99d9" + "reference": "b2d4718786398f47626add9c29840fc416175ef2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/b40eb1177d2e621c18cd797ca6cc9efb5a0e99d9", - "reference": "b40eb1177d2e621c18cd797ca6cc9efb5a0e99d9", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/b2d4718786398f47626add9c29840fc416175ef2", + "reference": "b2d4718786398f47626add9c29840fc416175ef2", "shasum": "" }, "require": { @@ -84,8 +84,7 @@ "guzzlehttp/psr7": "^2.4.5", "mtdowling/jmespath.php": "^2.8.0", "php": ">=8.1", - "psr/http-message": "^1.0 || ^2.0", - "symfony/filesystem": "^v5.4.45 || ^v6.4.3 || ^v7.1.0 || ^v8.0.0" + "psr/http-message": "^2.0" }, "require-dev": { "andrewsville/php-token-reflection": "^1.4", @@ -96,11 +95,13 @@ "doctrine/cache": "~1.4", "ext-dom": "*", "ext-openssl": "*", + "ext-pcntl": "*", "ext-sockets": "*", - "phpunit/phpunit": "^9.6", + "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", "psr/cache": "^2.0 || ^3.0", "psr/simple-cache": "^2.0 || ^3.0", "sebastian/comparator": "^1.2.3 || ^4.0 || ^5.0", + "symfony/filesystem": "^v6.4.0 || ^v7.1.0", "yoast/phpunit-polyfills": "^2.0" }, "suggest": { @@ -108,7 +109,6 @@ "doctrine/cache": "To use the DoctrineCacheAdapter", "ext-curl": "To send requests using cURL", "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", - "ext-pcntl": "To use client-side monitoring", "ext-sockets": "To use client-side monitoring" }, "type": "library", @@ -153,77 +153,22 @@ "support": { "forum": "https://github.com/aws/aws-sdk-php/discussions", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.369.14" + "source": "https://github.com/aws/aws-sdk-php/tree/3.349.3" }, - "time": "2026-01-15T19:10:54+00:00" - }, - { - "name": "bacon/bacon-qr-code", - "version": "v3.0.3", - "source": { - "type": "git", - "url": "https://github.com/Bacon/BaconQrCode.git", - "reference": "36a1cb2b81493fa5b82e50bf8068bf84d1542563" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/36a1cb2b81493fa5b82e50bf8068bf84d1542563", - "reference": "36a1cb2b81493fa5b82e50bf8068bf84d1542563", - "shasum": "" - }, - "require": { - "dasprid/enum": "^1.0.3", - "ext-iconv": "*", - "php": "^8.1" - }, - "require-dev": { - "phly/keep-a-changelog": "^2.12", - "phpunit/phpunit": "^10.5.11 || ^11.0.4", - "spatie/phpunit-snapshot-assertions": "^5.1.5", - "spatie/pixelmatch-php": "^1.2.0", - "squizlabs/php_codesniffer": "^3.9" - }, - "suggest": { - "ext-imagick": "to generate QR code images" - }, - "type": "library", - "autoload": { - "psr-4": { - "BaconQrCode\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Ben Scholzen 'DASPRiD'", - "email": "mail@dasprids.de", - "homepage": "https://dasprids.de/", - "role": "Developer" - } - ], - "description": "BaconQrCode is a QR code generator for PHP.", - "homepage": "https://github.com/Bacon/BaconQrCode", - "support": { - "issues": "https://github.com/Bacon/BaconQrCode/issues", - "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.3" - }, - "time": "2025-11-19T17:15:36+00:00" + "time": "2025-07-09T18:10:17+00:00" }, { "name": "bnussbau/laravel-trmnl-blade", - "version": "2.1.0", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/bnussbau/laravel-trmnl-blade.git", - "reference": "1e1cabfead00118d7a80c86ac6108aece2989bc7" + "reference": "a27dbce9203223591b3bbad46188ca3bf6c0af02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bnussbau/laravel-trmnl-blade/zipball/1e1cabfead00118d7a80c86ac6108aece2989bc7", - "reference": "1e1cabfead00118d7a80c86ac6108aece2989bc7", + "url": "https://api.github.com/repos/bnussbau/laravel-trmnl-blade/zipball/a27dbce9203223591b3bbad46188ca3bf6c0af02", + "reference": "a27dbce9203223591b3bbad46188ca3bf6c0af02", "shasum": "" }, "require": { @@ -278,7 +223,7 @@ ], "support": { "issues": "https://github.com/bnussbau/laravel-trmnl-blade/issues", - "source": "https://github.com/bnussbau/laravel-trmnl-blade/tree/2.1.0" + "source": "https://github.com/bnussbau/laravel-trmnl-blade/tree/1.1.1" }, "funding": [ { @@ -294,100 +239,29 @@ "type": "github" } ], - "time": "2026-01-02T20:38:51+00:00" - }, - { - "name": "bnussbau/trmnl-pipeline-php", - "version": "0.6.0", - "source": { - "type": "git", - "url": "https://github.com/bnussbau/trmnl-pipeline-php.git", - "reference": "228505afa8a39a5033916e9ae5ccbf1733092c1f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/bnussbau/trmnl-pipeline-php/zipball/228505afa8a39a5033916e9ae5ccbf1733092c1f", - "reference": "228505afa8a39a5033916e9ae5ccbf1733092c1f", - "shasum": "" - }, - "require": { - "ext-imagick": "*", - "league/pipeline": "^1.0", - "php": "^8.2", - "spatie/browsershot": "^5.0" - }, - "require-dev": { - "laravel/pint": "^1.0", - "pestphp/pest": "^4.0", - "phpstan/phpstan": "^1.10", - "rector/rector": "^1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Bnussbau\\TrmnlPipeline\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "bnussbau", - "email": "bnussbau@users.noreply.github.com", - "role": "Developer" - } - ], - "description": "Convert HTML content into optimized images for a range of e-ink devices.", - "homepage": "https://github.com/bnussbau/trmnl-pipeline-php", - "keywords": [ - "TRMNL", - "bnussbau", - "e-ink", - "trmnl-pipeline-php" - ], - "support": { - "issues": "https://github.com/bnussbau/trmnl-pipeline-php/issues", - "source": "https://github.com/bnussbau/trmnl-pipeline-php/tree/0.6.0" - }, - "funding": [ - { - "url": "https://www.buymeacoffee.com/bnussbau", - "type": "buy_me_a_coffee" - }, - { - "url": "https://usetrmnl.com/?ref=laravel-trmnl", - "type": "custom" - }, - { - "url": "https://github.com/bnussbau", - "type": "github" - } - ], - "time": "2025-12-02T15:18:51+00:00" + "time": "2025-07-14T18:37:41+00:00" }, { "name": "brick/math", - "version": "0.14.1", + "version": "0.13.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "f05858549e5f9d7bb45875a75583240a38a281d0" + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0", - "reference": "f05858549e5f9d7bb45875a75583240a38a281d0", + "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", "shasum": "" }, "require": { - "php": "^8.2" + "php": "^8.1" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpstan/phpstan": "2.1.22", - "phpunit/phpunit": "^11.5" + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "6.8.8" }, "type": "library", "autoload": { @@ -417,7 +291,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.14.1" + "source": "https://github.com/brick/math/tree/0.13.1" }, "funding": [ { @@ -425,7 +299,7 @@ "type": "github" } ], - "time": "2025-11-24T14:40:29+00:00" + "time": "2025-03-29T13:50:30+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -496,56 +370,6 @@ ], "time": "2024-02-09T16:56:22+00:00" }, - { - "name": "dasprid/enum", - "version": "1.0.7", - "source": { - "type": "git", - "url": "https://github.com/DASPRiD/Enum.git", - "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/b5874fa9ed0043116c72162ec7f4fb50e02e7cce", - "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce", - "shasum": "" - }, - "require": { - "php": ">=7.1 <9.0" - }, - "require-dev": { - "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11", - "squizlabs/php_codesniffer": "*" - }, - "type": "library", - "autoload": { - "psr-4": { - "DASPRiD\\Enum\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Ben Scholzen 'DASPRiD'", - "email": "mail@dasprids.de", - "homepage": "https://dasprids.de/", - "role": "Developer" - } - ], - "description": "PHP 7.1 enum implementation", - "keywords": [ - "enum", - "map" - ], - "support": { - "issues": "https://github.com/DASPRiD/Enum/issues", - "source": "https://github.com/DASPRiD/Enum/tree/1.0.7" - }, - "time": "2025-09-16T12:23:56+00:00" - }, { "name": "dflydev/dot-access-data", "version": "v3.0.3", @@ -623,32 +447,33 @@ }, { "name": "doctrine/inflector", - "version": "2.1.0", + "version": "2.0.10", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", - "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^12.0 || ^13.0", - "phpstan/phpstan": "^1.12 || ^2.0", - "phpstan/phpstan-phpunit": "^1.4 || ^2.0", - "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", - "phpunit/phpunit": "^8.5 || ^12.2" + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Inflector\\": "src" + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" } }, "notification-url": "https://packagist.org/downloads/", @@ -693,7 +518,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.1.0" + "source": "https://github.com/doctrine/inflector/tree/2.0.10" }, "funding": [ { @@ -709,7 +534,7 @@ "type": "tidelift" } ], - "time": "2025-08-10T19:31:58+00:00" + "time": "2024-02-18T20:23:39+00:00" }, { "name": "doctrine/lexer", @@ -790,28 +615,29 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v3.6.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013" + "reference": "8c784d071debd117328803d86b2097615b457500" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/d61a8a9604ec1f8c3d150d09db6ce98b32675013", - "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", + "reference": "8c784d071debd117328803d86b2097615b457500", "shasum": "" }, "require": { - "php": "^8.2|^8.3|^8.4|^8.5" + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" }, "replace": { "mtdowling/cron-expression": "^1.0" }, "require-dev": { - "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^1.12.32|^2.1.31", - "phpunit/phpunit": "^8.5.48|^9.0" + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" }, "type": "library", "extra": { @@ -842,7 +668,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.6.0" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" }, "funding": [ { @@ -850,7 +676,7 @@ "type": "github" } ], - "time": "2025-10-31T18:51:33+00:00" + "time": "2024-10-09T13:47:03+00:00" }, { "name": "egulias/email-validator", @@ -919,157 +745,33 @@ ], "time": "2025-03-06T22:45:56+00:00" }, - { - "name": "ezyang/htmlpurifier", - "version": "v4.19.0", - "source": { - "type": "git", - "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "b287d2a16aceffbf6e0295559b39662612b77fcf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/b287d2a16aceffbf6e0295559b39662612b77fcf", - "reference": "b287d2a16aceffbf6e0295559b39662612b77fcf", - "shasum": "" - }, - "require": { - "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" - }, - "require-dev": { - "cerdic/css-tidy": "^1.7 || ^2.0", - "simpletest/simpletest": "dev-master" - }, - "suggest": { - "cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.", - "ext-bcmath": "Used for unit conversion and imagecrash protection", - "ext-iconv": "Converts text to and from non-UTF-8 encodings", - "ext-tidy": "Used for pretty-printing HTML" - }, - "type": "library", - "autoload": { - "files": [ - "library/HTMLPurifier.composer.php" - ], - "psr-0": { - "HTMLPurifier": "library/" - }, - "exclude-from-classmap": [ - "/library/HTMLPurifier/Language/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-2.1-or-later" - ], - "authors": [ - { - "name": "Edward Z. Yang", - "email": "admin@htmlpurifier.org", - "homepage": "http://ezyang.com" - } - ], - "description": "Standards compliant HTML filter written in PHP", - "homepage": "http://htmlpurifier.org/", - "keywords": [ - "html" - ], - "support": { - "issues": "https://github.com/ezyang/htmlpurifier/issues", - "source": "https://github.com/ezyang/htmlpurifier/tree/v4.19.0" - }, - "time": "2025-10-17T16:34:55+00:00" - }, - { - "name": "firebase/php-jwt", - "version": "v7.0.2", - "source": { - "type": "git", - "url": "https://github.com/firebase/php-jwt.git", - "reference": "5645b43af647b6947daac1d0f659dd1fbe8d3b65" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/5645b43af647b6947daac1d0f659dd1fbe8d3b65", - "reference": "5645b43af647b6947daac1d0f659dd1fbe8d3b65", - "shasum": "" - }, - "require": { - "php": "^8.0" - }, - "require-dev": { - "guzzlehttp/guzzle": "^7.4", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5", - "psr/cache": "^2.0||^3.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0" - }, - "suggest": { - "ext-sodium": "Support EdDSA (Ed25519) signatures", - "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" - }, - "type": "library", - "autoload": { - "psr-4": { - "Firebase\\JWT\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Neuman Vong", - "email": "neuman+pear@twilio.com", - "role": "Developer" - }, - { - "name": "Anant Narayanan", - "email": "anant@php.net", - "role": "Developer" - } - ], - "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", - "homepage": "https://github.com/firebase/php-jwt", - "keywords": [ - "jwt", - "php" - ], - "support": { - "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v7.0.2" - }, - "time": "2025-12-16T22:17:28+00:00" - }, { "name": "fruitcake/php-cors", - "version": "v1.4.0", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/fruitcake/php-cors.git", - "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379" + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", - "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", "shasum": "" }, "require": { - "php": "^8.1", - "symfony/http-foundation": "^5.4|^6.4|^7.3|^8" + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6|^7" }, "require-dev": { - "phpstan/phpstan": "^2", + "phpstan/phpstan": "^1.4", "phpunit/phpunit": "^9", - "squizlabs/php_codesniffer": "^4" + "squizlabs/php_codesniffer": "^3.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -1100,7 +802,7 @@ ], "support": { "issues": "https://github.com/fruitcake/php-cors/issues", - "source": "https://github.com/fruitcake/php-cors/tree/v1.4.0" + "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" }, "funding": [ { @@ -1112,28 +814,28 @@ "type": "github" } ], - "time": "2025-12-03T09:33:47+00:00" + "time": "2023-10-12T05:21:21+00:00" }, { "name": "graham-campbell/result-type", - "version": "v1.1.4", + "version": "v1.1.3", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b" + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/e01f4a821471308ba86aa202fed6698b6b695e3b", - "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.5" + "phpoption/phpoption": "^1.9.3" }, "require-dev": { - "phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7" + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "autoload": { @@ -1162,7 +864,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.4" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" }, "funding": [ { @@ -1174,26 +876,26 @@ "type": "tidelift" } ], - "time": "2025-12-27T19:43:20+00:00" + "time": "2024-07-20T21:45:45+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.10.0", + "version": "7.9.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", - "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^2.3", - "guzzlehttp/psr7": "^2.8", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -1284,7 +986,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.10.0" + "source": "https://github.com/guzzle/guzzle/tree/7.9.3" }, "funding": [ { @@ -1300,20 +1002,20 @@ "type": "tidelift" } ], - "time": "2025-08-23T22:36:01+00:00" + "time": "2025-03-27T13:37:11+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.3.0", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "481557b130ef3790cf82b713667b43030dc9c957" + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", - "reference": "481557b130ef3790cf82b713667b43030dc9c957", + "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", "shasum": "" }, "require": { @@ -1321,7 +1023,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.44 || ^9.6.25" + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "type": "library", "extra": { @@ -1367,7 +1069,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.3.0" + "source": "https://github.com/guzzle/promises/tree/2.2.0" }, "funding": [ { @@ -1383,20 +1085,20 @@ "type": "tidelift" } ], - "time": "2025-08-22T14:34:08+00:00" + "time": "2025-03-27T13:27:01+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.8.0", + "version": "2.7.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "21dc724a0583619cd1652f673303492272778051" + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", - "reference": "21dc724a0583619cd1652f673303492272778051", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", "shasum": "" }, "require": { @@ -1412,7 +1114,7 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "0.9.0", - "phpunit/phpunit": "^8.5.44 || ^9.6.25" + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -1483,7 +1185,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.8.0" + "source": "https://github.com/guzzle/psr7/tree/2.7.1" }, "funding": [ { @@ -1499,20 +1201,20 @@ "type": "tidelift" } ], - "time": "2025-08-23T21:21:41+00:00" + "time": "2025-03-27T12:30:47+00:00" }, { "name": "guzzlehttp/uri-template", - "version": "v1.0.5", + "version": "v1.0.4", "source": { "type": "git", "url": "https://github.com/guzzle/uri-template.git", - "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1" + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/4f4bbd4e7172148801e76e3decc1e559bdee34e1", - "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/30e286560c137526eccd4ce21b2de477ab0676d2", + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2", "shasum": "" }, "require": { @@ -1521,7 +1223,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.44 || ^9.6.25", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", "uri-template/tests": "1.0.0" }, "type": "library", @@ -1569,7 +1271,7 @@ ], "support": { "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.5" + "source": "https://github.com/guzzle/uri-template/tree/v1.0.4" }, "funding": [ { @@ -1585,20 +1287,20 @@ "type": "tidelift" } ], - "time": "2025-08-22T14:27:06+00:00" + "time": "2025-02-03T10:55:03+00:00" }, { "name": "hammerstone/sidecar", - "version": "v0.7.1", + "version": "v0.7.0", "source": { "type": "git", "url": "https://github.com/aarondfrancis/sidecar.git", - "reference": "e30df1a441bd5a61d3da9342328926227c63610f" + "reference": "91a7001be31b16b51536aad42b14797653c3d862" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aarondfrancis/sidecar/zipball/e30df1a441bd5a61d3da9342328926227c63610f", - "reference": "e30df1a441bd5a61d3da9342328926227c63610f", + "url": "https://api.github.com/repos/aarondfrancis/sidecar/zipball/91a7001be31b16b51536aad42b14797653c3d862", + "reference": "91a7001be31b16b51536aad42b14797653c3d862", "shasum": "" }, "require": { @@ -1641,9 +1343,153 @@ "description": "A Laravel package to deploy Lambda functions alongside your main application.", "support": { "issues": "https://github.com/aarondfrancis/sidecar/issues", - "source": "https://github.com/aarondfrancis/sidecar/tree/v0.7.1" + "source": "https://github.com/aarondfrancis/sidecar/tree/v0.7.0" }, - "time": "2025-08-22T14:58:51+00:00" + "time": "2025-05-07T23:03:51+00:00" + }, + { + "name": "intervention/gif", + "version": "4.2.2", + "source": { + "type": "git", + "url": "https://github.com/Intervention/gif.git", + "reference": "5999eac6a39aa760fb803bc809e8909ee67b451a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Intervention/gif/zipball/5999eac6a39aa760fb803bc809e8909ee67b451a", + "reference": "5999eac6a39aa760fb803bc809e8909ee67b451a", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "slevomat/coding-standard": "~8.0", + "squizlabs/php_codesniffer": "^3.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Intervention\\Gif\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oliver Vogel", + "email": "oliver@intervention.io", + "homepage": "https://intervention.io/" + } + ], + "description": "Native PHP GIF Encoder/Decoder", + "homepage": "https://github.com/intervention/gif", + "keywords": [ + "animation", + "gd", + "gif", + "image" + ], + "support": { + "issues": "https://github.com/Intervention/gif/issues", + "source": "https://github.com/Intervention/gif/tree/4.2.2" + }, + "funding": [ + { + "url": "https://paypal.me/interventionio", + "type": "custom" + }, + { + "url": "https://github.com/Intervention", + "type": "github" + }, + { + "url": "https://ko-fi.com/interventionphp", + "type": "ko_fi" + } + ], + "time": "2025-03-29T07:46:21+00:00" + }, + { + "name": "intervention/image", + "version": "3.11.3", + "source": { + "type": "git", + "url": "https://github.com/Intervention/image.git", + "reference": "d0f097b8a3fa8fb758efc9440b513aa3833cda17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Intervention/image/zipball/d0f097b8a3fa8fb758efc9440b513aa3833cda17", + "reference": "d0f097b8a3fa8fb758efc9440b513aa3833cda17", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "intervention/gif": "^4.2", + "php": "^8.1" + }, + "require-dev": { + "mockery/mockery": "^1.6", + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "slevomat/coding-standard": "~8.0", + "squizlabs/php_codesniffer": "^3.8" + }, + "suggest": { + "ext-exif": "Recommended to be able to read EXIF data properly." + }, + "type": "library", + "autoload": { + "psr-4": { + "Intervention\\Image\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oliver Vogel", + "email": "oliver@intervention.io", + "homepage": "https://intervention.io/" + } + ], + "description": "PHP image manipulation", + "homepage": "https://image.intervention.io/", + "keywords": [ + "gd", + "image", + "imagick", + "resize", + "thumbnail", + "watermark" + ], + "support": { + "issues": "https://github.com/Intervention/image/issues", + "source": "https://github.com/Intervention/image/tree/3.11.3" + }, + "funding": [ + { + "url": "https://paypal.me/interventionio", + "type": "custom" + }, + { + "url": "https://github.com/Intervention", + "type": "github" + }, + { + "url": "https://ko-fi.com/interventionphp", + "type": "ko_fi" + } + ], + "time": "2025-05-22T17:26:23+00:00" }, { "name": "keepsuit/laravel-liquid", @@ -1722,16 +1568,16 @@ }, { "name": "keepsuit/liquid", - "version": "v0.9.1", + "version": "v0.9.0", "source": { "type": "git", "url": "https://github.com/keepsuit/php-liquid.git", - "reference": "844d88540524f99d9039916e0ef688b7f222ebc0" + "reference": "f5d81df3689acb79b04c7be3d13778e1f138185f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/keepsuit/php-liquid/zipball/844d88540524f99d9039916e0ef688b7f222ebc0", - "reference": "844d88540524f99d9039916e0ef688b7f222ebc0", + "url": "https://api.github.com/repos/keepsuit/php-liquid/zipball/f5d81df3689acb79b04c7be3d13778e1f138185f", + "reference": "f5d81df3689acb79b04c7be3d13778e1f138185f", "shasum": "" }, "require": { @@ -1740,17 +1586,17 @@ }, "require-dev": { "laravel/pint": "^1.2", - "pestphp/pest": "^2.36 || ^3.0 || ^4.0", - "pestphp/pest-plugin-arch": "^2.7 || ^3.0 || ^4.0", + "pestphp/pest": "^2.36 || ^3.0", + "pestphp/pest-plugin-arch": "^2.7 || ^3.0", "phpbench/phpbench": "dev-master", "phpstan/extension-installer": "^1.3", "phpstan/phpstan": "^2.0", "phpstan/phpstan-deprecation-rules": "^2.0", "spatie/invade": "^2.0", "spatie/ray": "^1.28", - "symfony/console": "^6.1 || ^7.0 || ^8.0", - "symfony/var-exporter": "^6.1 || ^7.0 || ^8.0", - "symfony/yaml": "^6.1 || ^7.0 || ^8.0" + "symfony/console": "^6.1 || ^7.0", + "symfony/var-exporter": "^6.1 || ^7.0", + "symfony/yaml": "^6.1 || ^7.0" }, "type": "library", "autoload": { @@ -1777,89 +1623,26 @@ ], "support": { "issues": "https://github.com/keepsuit/php-liquid/issues", - "source": "https://github.com/keepsuit/php-liquid/tree/v0.9.1" + "source": "https://github.com/keepsuit/php-liquid/tree/v0.9.0" }, - "time": "2025-12-01T12:01:51+00:00" - }, - { - "name": "laravel/fortify", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/laravel/fortify.git", - "reference": "e0666dabeec0b6428678af1d51f436dcfb24e3a9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/fortify/zipball/e0666dabeec0b6428678af1d51f436dcfb24e3a9", - "reference": "e0666dabeec0b6428678af1d51f436dcfb24e3a9", - "shasum": "" - }, - "require": { - "bacon/bacon-qr-code": "^3.0", - "ext-json": "*", - "illuminate/support": "^10.0|^11.0|^12.0", - "php": "^8.1", - "pragmarx/google2fa": "^9.0", - "symfony/console": "^6.0|^7.0" - }, - "require-dev": { - "orchestra/testbench": "^8.36|^9.15|^10.8", - "phpstan/phpstan": "^1.10" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Laravel\\Fortify\\FortifyServiceProvider" - ] - }, - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Laravel\\Fortify\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Backend controllers and scaffolding for Laravel authentication.", - "keywords": [ - "auth", - "laravel" - ], - "support": { - "issues": "https://github.com/laravel/fortify/issues", - "source": "https://github.com/laravel/fortify" - }, - "time": "2025-12-15T14:48:33+00:00" + "time": "2025-06-15T12:02:45+00:00" }, { "name": "laravel/framework", - "version": "v12.47.0", + "version": "v12.20.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "ab8114c2e78f32e64eb238fc4b495bea3f8b80ec" + "reference": "1b9a00f8caf5503c92aa436279172beae1a484ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/ab8114c2e78f32e64eb238fc4b495bea3f8b80ec", - "reference": "ab8114c2e78f32e64eb238fc4b495bea3f8b80ec", + "url": "https://api.github.com/repos/laravel/framework/zipball/1b9a00f8caf5503c92aa436279172beae1a484ff", + "reference": "1b9a00f8caf5503c92aa436279172beae1a484ff", "shasum": "" }, "require": { - "brick/math": "^0.11|^0.12|^0.13|^0.14", + "brick/math": "^0.11|^0.12|^0.13", "composer-runtime-api": "^2.2", "doctrine/inflector": "^2.0.5", "dragonmantank/cron-expression": "^3.4", @@ -1895,9 +1678,7 @@ "symfony/http-kernel": "^7.2.0", "symfony/mailer": "^7.2.0", "symfony/mime": "^7.2.0", - "symfony/polyfill-php83": "^1.33", - "symfony/polyfill-php84": "^1.33", - "symfony/polyfill-php85": "^1.33", + "symfony/polyfill-php83": "^1.31", "symfony/process": "^7.2.0", "symfony/routing": "^7.2.0", "symfony/uid": "^7.2.0", @@ -1933,7 +1714,6 @@ "illuminate/filesystem": "self.version", "illuminate/hashing": "self.version", "illuminate/http": "self.version", - "illuminate/json-schema": "self.version", "illuminate/log": "self.version", "illuminate/macroable": "self.version", "illuminate/mail": "self.version", @@ -1943,7 +1723,6 @@ "illuminate/process": "self.version", "illuminate/queue": "self.version", "illuminate/redis": "self.version", - "illuminate/reflection": "self.version", "illuminate/routing": "self.version", "illuminate/session": "self.version", "illuminate/support": "self.version", @@ -1967,14 +1746,13 @@ "league/flysystem-read-only": "^3.25.1", "league/flysystem-sftp-v3": "^3.25.1", "mockery/mockery": "^1.6.10", - "opis/json-schema": "^2.4.1", - "orchestra/testbench-core": "^10.8.1", + "orchestra/testbench-core": "^10.0.0", "pda/pheanstalk": "^5.0.6|^7.0.0", "php-http/discovery": "^1.15", "phpstan/phpstan": "^2.0", "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", "predis/predis": "^2.3|^3.0", - "resend/resend-php": "^0.10.0|^1.0", + "resend/resend-php": "^0.10.0", "symfony/cache": "^7.2.0", "symfony/http-client": "^7.2.0", "symfony/psr-http-message-bridge": "^7.2.0", @@ -1993,7 +1771,7 @@ "ext-pdo": "Required to use all database features.", "ext-posix": "Required to use all features of the queue worker.", "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).", - "fakerphp/faker": "Required to generate fake data using the fake() helper (^1.23).", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", "filp/whoops": "Required for friendly error pages in development (^2.14.3).", "laravel/tinker": "Required to use the tinker console command (^2.0).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", @@ -2008,7 +1786,7 @@ "predis/predis": "Required to use the predis connector (^2.3|^3.0).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", - "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0|^1.0).", + "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", "symfony/cache": "Required to PSR-6 cache bridge (^7.2).", "symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).", "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.2).", @@ -2030,7 +1808,6 @@ "src/Illuminate/Filesystem/functions.php", "src/Illuminate/Foundation/helpers.php", "src/Illuminate/Log/functions.php", - "src/Illuminate/Reflection/helpers.php", "src/Illuminate/Support/functions.php", "src/Illuminate/Support/helpers.php" ], @@ -2039,8 +1816,7 @@ "Illuminate\\Support\\": [ "src/Illuminate/Macroable/", "src/Illuminate/Collections/", - "src/Illuminate/Conditionable/", - "src/Illuminate/Reflection/" + "src/Illuminate/Conditionable/" ] } }, @@ -2064,20 +1840,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2026-01-13T15:29:06+00:00" + "time": "2025-07-08T15:02:21+00:00" }, { "name": "laravel/prompts", - "version": "v0.3.10", + "version": "v0.3.6", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "360ba095ef9f51017473505191fbd4ab73e1cab3" + "reference": "86a8b692e8661d0fb308cec64f3d176821323077" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/360ba095ef9f51017473505191fbd4ab73e1cab3", - "reference": "360ba095ef9f51017473505191fbd4ab73e1cab3", + "url": "https://api.github.com/repos/laravel/prompts/zipball/86a8b692e8661d0fb308cec64f3d176821323077", + "reference": "86a8b692e8661d0fb308cec64f3d176821323077", "shasum": "" }, "require": { @@ -2093,9 +1869,9 @@ "require-dev": { "illuminate/collections": "^10.0|^11.0|^12.0", "mockery/mockery": "^1.5", - "pestphp/pest": "^2.3|^3.4|^4.0", - "phpstan/phpstan": "^1.12.28", - "phpstan/phpstan-mockery": "^1.1.3" + "pestphp/pest": "^2.3|^3.4", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-mockery": "^1.1" }, "suggest": { "ext-pcntl": "Required for the spinner to be animated." @@ -2121,22 +1897,22 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.10" + "source": "https://github.com/laravel/prompts/tree/v0.3.6" }, - "time": "2026-01-13T20:29:29+00:00" + "time": "2025-07-07T14:17:42+00:00" }, { "name": "laravel/sanctum", - "version": "v4.2.3", + "version": "v4.1.2", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "47d26f1d310879ff757b971f5a6fc631d18663fd" + "reference": "e4c09e69aecd5a383e0c1b85a6bb501c997d7491" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/47d26f1d310879ff757b971f5a6fc631d18663fd", - "reference": "47d26f1d310879ff757b971f5a6fc631d18663fd", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/e4c09e69aecd5a383e0c1b85a6bb501c997d7491", + "reference": "e4c09e69aecd5a383e0c1b85a6bb501c997d7491", "shasum": "" }, "require": { @@ -2150,8 +1926,9 @@ }, "require-dev": { "mockery/mockery": "^1.6", - "orchestra/testbench": "^9.15|^10.8", - "phpstan/phpstan": "^1.10" + "orchestra/testbench": "^9.0|^10.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { @@ -2186,20 +1963,20 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2026-01-11T18:20:25+00:00" + "time": "2025-07-01T15:49:32+00:00" }, { "name": "laravel/serializable-closure", - "version": "v2.0.8", + "version": "v2.0.4", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b" + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/7581a4407012f5f53365e11bafc520fd7f36bc9b", - "reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841", "shasum": "" }, "require": { @@ -2208,7 +1985,7 @@ "require-dev": { "illuminate/support": "^10.0|^11.0|^12.0", "nesbot/carbon": "^2.67|^3.0", - "pestphp/pest": "^2.36|^3.0|^4.0", + "pestphp/pest": "^2.36|^3.0", "phpstan/phpstan": "^2.0", "symfony/var-dumper": "^6.2.0|^7.0.0" }, @@ -2247,92 +2024,20 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2026-01-08T16:22:46+00:00" - }, - { - "name": "laravel/socialite", - "version": "v5.24.2", - "source": { - "type": "git", - "url": "https://github.com/laravel/socialite.git", - "reference": "5cea2eebf11ca4bc6c2f20495c82a70a9b3d1613" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/5cea2eebf11ca4bc6c2f20495c82a70a9b3d1613", - "reference": "5cea2eebf11ca4bc6c2f20495c82a70a9b3d1613", - "shasum": "" - }, - "require": { - "ext-json": "*", - "firebase/php-jwt": "^6.4|^7.0", - "guzzlehttp/guzzle": "^6.0|^7.0", - "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/http": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", - "league/oauth1-client": "^1.11", - "php": "^7.2|^8.0", - "phpseclib/phpseclib": "^3.0" - }, - "require-dev": { - "mockery/mockery": "^1.0", - "orchestra/testbench": "^4.18|^5.20|^6.47|^7.55|^8.36|^9.15|^10.8", - "phpstan/phpstan": "^1.12.23", - "phpunit/phpunit": "^8.0|^9.3|^10.4|^11.5|^12.0" - }, - "type": "library", - "extra": { - "laravel": { - "aliases": { - "Socialite": "Laravel\\Socialite\\Facades\\Socialite" - }, - "providers": [ - "Laravel\\Socialite\\SocialiteServiceProvider" - ] - }, - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "Laravel\\Socialite\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.", - "homepage": "https://laravel.com", - "keywords": [ - "laravel", - "oauth" - ], - "support": { - "issues": "https://github.com/laravel/socialite/issues", - "source": "https://github.com/laravel/socialite" - }, - "time": "2026-01-10T16:07:28+00:00" + "time": "2025-03-19T13:51:03+00:00" }, { "name": "laravel/tinker", - "version": "v2.11.0", + "version": "v2.10.1", "source": { "type": "git", "url": "https://github.com/laravel/tinker.git", - "reference": "3d34b97c9a1747a81a3fde90482c092bd8b66468" + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/tinker/zipball/3d34b97c9a1747a81a3fde90482c092bd8b66468", - "reference": "3d34b97c9a1747a81a3fde90482c092bd8b66468", + "url": "https://api.github.com/repos/laravel/tinker/zipball/22177cc71807d38f2810c6204d8f7183d88a57d3", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3", "shasum": "" }, "require": { @@ -2341,7 +2046,7 @@ "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", "php": "^7.2.5|^8.0", "psy/psysh": "^0.11.1|^0.12.0", - "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0|^8.0" + "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0" }, "require-dev": { "mockery/mockery": "~1.3.3|^1.4.2", @@ -2383,22 +2088,22 @@ ], "support": { "issues": "https://github.com/laravel/tinker/issues", - "source": "https://github.com/laravel/tinker/tree/v2.11.0" + "source": "https://github.com/laravel/tinker/tree/v2.10.1" }, - "time": "2025-12-19T19:16:45+00:00" + "time": "2025-01-27T14:24:01+00:00" }, { "name": "league/commonmark", - "version": "2.8.0", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb" + "reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4efa10c1e56488e658d10adf7b7b7dcd19940bfb", - "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/6fbb36d44824ed4091adbcf4c7d4a3923cdb3405", + "reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405", "shasum": "" }, "require": { @@ -2427,7 +2132,7 @@ "symfony/process": "^5.4 | ^6.0 | ^7.0", "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", "unleashedtech/php-coding-standard": "^3.1.1", - "vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0" + "vimeo/psalm": "^4.24.0 || ^5.0.0" }, "suggest": { "symfony/yaml": "v2.3+ required if using the Front Matter extension" @@ -2435,7 +2140,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.9-dev" + "dev-main": "2.8-dev" } }, "autoload": { @@ -2492,7 +2197,7 @@ "type": "tidelift" } ], - "time": "2025-11-26T21:48:24+00:00" + "time": "2025-05-05T12:20:28+00:00" }, { "name": "league/config", @@ -2578,16 +2283,16 @@ }, { "name": "league/flysystem", - "version": "3.30.2", + "version": "3.30.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277" + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277", - "reference": "5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e", + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e", "shasum": "" }, "require": { @@ -2655,22 +2360,22 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.30.2" + "source": "https://github.com/thephpleague/flysystem/tree/3.30.0" }, - "time": "2025-11-10T17:13:11+00:00" + "time": "2025-06-25T13:29:59+00:00" }, { "name": "league/flysystem-local", - "version": "3.30.2", + "version": "3.30.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-local.git", - "reference": "ab4f9d0d672f601b102936aa728801dd1a11968d" + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/ab4f9d0d672f601b102936aa728801dd1a11968d", - "reference": "ab4f9d0d672f601b102936aa728801dd1a11968d", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/6691915f77c7fb69adfb87dcd550052dc184ee10", + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10", "shasum": "" }, "require": { @@ -2704,9 +2409,9 @@ "local" ], "support": { - "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.2" + "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.0" }, - "time": "2025-11-10T11:23:37+00:00" + "time": "2025-05-21T10:34:19+00:00" }, { "name": "league/mime-type-detection", @@ -2764,172 +2469,35 @@ ], "time": "2024-09-21T08:32:55+00:00" }, - { - "name": "league/oauth1-client", - "version": "v1.11.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/oauth1-client.git", - "reference": "f9c94b088837eb1aae1ad7c4f23eb65cc6993055" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/f9c94b088837eb1aae1ad7c4f23eb65cc6993055", - "reference": "f9c94b088837eb1aae1ad7c4f23eb65cc6993055", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-openssl": "*", - "guzzlehttp/guzzle": "^6.0|^7.0", - "guzzlehttp/psr7": "^1.7|^2.0", - "php": ">=7.1||>=8.0" - }, - "require-dev": { - "ext-simplexml": "*", - "friendsofphp/php-cs-fixer": "^2.17", - "mockery/mockery": "^1.3.3", - "phpstan/phpstan": "^0.12.42", - "phpunit/phpunit": "^7.5||9.5" - }, - "suggest": { - "ext-simplexml": "For decoding XML-based responses." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev", - "dev-develop": "2.0-dev" - } - }, - "autoload": { - "psr-4": { - "League\\OAuth1\\Client\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ben Corlett", - "email": "bencorlett@me.com", - "homepage": "http://www.webcomm.com.au", - "role": "Developer" - } - ], - "description": "OAuth 1.0 Client Library", - "keywords": [ - "Authentication", - "SSO", - "authorization", - "bitbucket", - "identity", - "idp", - "oauth", - "oauth1", - "single sign on", - "trello", - "tumblr", - "twitter" - ], - "support": { - "issues": "https://github.com/thephpleague/oauth1-client/issues", - "source": "https://github.com/thephpleague/oauth1-client/tree/v1.11.0" - }, - "time": "2024-12-10T19:59:05+00:00" - }, - { - "name": "league/pipeline", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/pipeline.git", - "reference": "9069ddfdbd5582f8a563e00cffdbeffb9a0acd01" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/pipeline/zipball/9069ddfdbd5582f8a563e00cffdbeffb9a0acd01", - "reference": "9069ddfdbd5582f8a563e00cffdbeffb9a0acd01", - "shasum": "" - }, - "require": { - "php": "^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.0 || ^10.0 || ^11.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "League\\Pipeline\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Frank de Jonge", - "email": "info@frenky.net", - "role": "Author" - }, - { - "name": "Woody Gilk", - "email": "woody.gilk@gmail.com", - "role": "Maintainer" - } - ], - "description": "A plug and play pipeline implementation.", - "keywords": [ - "composition", - "design pattern", - "pattern", - "pipeline", - "sequential" - ], - "support": { - "issues": "https://github.com/thephpleague/pipeline/issues", - "source": "https://github.com/thephpleague/pipeline/tree/1.1.0" - }, - "time": "2025-02-06T08:48:15+00:00" - }, { "name": "league/uri", - "version": "7.7.0", + "version": "7.5.1", "source": { "type": "git", "url": "https://github.com/thephpleague/uri.git", - "reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807" + "reference": "81fb5145d2644324614cc532b28efd0215bda430" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/8d587cddee53490f9b82bf203d3a9aa7ea4f9807", - "reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", + "reference": "81fb5145d2644324614cc532b28efd0215bda430", "shasum": "" }, "require": { - "league/uri-interfaces": "^7.7", - "php": "^8.1", - "psr/http-factory": "^1" + "league/uri-interfaces": "^7.5", + "php": "^8.1" }, "conflict": { "league/uri-schemes": "^1.0" }, "suggest": { "ext-bcmath": "to improve IPV4 host parsing", - "ext-dom": "to convert the URI into an HTML anchor tag", "ext-fileinfo": "to create Data URI from file contennts", "ext-gmp": "to improve IPV4 host parsing", "ext-intl": "to handle IDN host with the best performance", - "ext-uri": "to use the PHP native URI class", "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", "league/uri-components": "Needed to easily manipulate URI objects components", - "league/uri-polyfill": "Needed to backport the PHP URI extension for older versions of PHP", "php-64bit": "to improve IPV4 host parsing", - "rowbot/url": "to handle WHATWG URL", "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", @@ -2957,7 +2525,6 @@ "description": "URI manipulation library", "homepage": "https://uri.thephpleague.com", "keywords": [ - "URN", "data-uri", "file-uri", "ftp", @@ -2970,11 +2537,9 @@ "psr-7", "query-string", "querystring", - "rfc2141", "rfc3986", "rfc3987", "rfc6570", - "rfc8141", "uri", "uri-template", "url", @@ -2984,7 +2549,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri/tree/7.7.0" + "source": "https://github.com/thephpleague/uri/tree/7.5.1" }, "funding": [ { @@ -2992,25 +2557,26 @@ "type": "github" } ], - "time": "2025-12-07T16:02:06+00:00" + "time": "2024-12-08T08:40:02+00:00" }, { "name": "league/uri-interfaces", - "version": "7.7.0", + "version": "7.5.0", "source": { "type": "git", "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c" + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/62ccc1a0435e1c54e10ee6022df28d6c04c2946c", - "reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", "shasum": "" }, "require": { "ext-filter": "*", "php": "^8.1", + "psr/http-factory": "^1", "psr/http-message": "^1.1 || ^2.0" }, "suggest": { @@ -3018,7 +2584,6 @@ "ext-gmp": "to improve IPV4 host parsing", "ext-intl": "to handle IDN host with the best performance", "php-64bit": "to improve IPV4 host parsing", - "rowbot/url": "to handle WHATWG URL", "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", @@ -3043,7 +2608,7 @@ "homepage": "https://nyamsprod.com" } ], - "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI", + "description": "Common interfaces and classes for URI representation and interaction", "homepage": "https://uri.thephpleague.com", "keywords": [ "data-uri", @@ -3068,7 +2633,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri-interfaces/tree/7.7.0" + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" }, "funding": [ { @@ -3076,20 +2641,20 @@ "type": "github" } ], - "time": "2025-12-07T16:03:21+00:00" + "time": "2024-12-08T08:18:47+00:00" }, { "name": "livewire/flux", - "version": "v2.10.2", + "version": "v2.2.3", "source": { "type": "git", "url": "https://github.com/livewire/flux.git", - "reference": "e7a93989788429bb6c0a908a056d22ea3a6c7975" + "reference": "0fb4c0b78eac393ad3a19a387af193573c310371" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/flux/zipball/e7a93989788429bb6c0a908a056d22ea3a6c7975", - "reference": "e7a93989788429bb6c0a908a056d22ea3a6c7975", + "url": "https://api.github.com/repos/livewire/flux/zipball/0fb4c0b78eac393ad3a19a387af193573c310371", + "reference": "0fb4c0b78eac393ad3a19a387af193573c310371", "shasum": "" }, "require": { @@ -3097,13 +2662,10 @@ "illuminate/support": "^10.0|^11.0|^12.0", "illuminate/view": "^10.0|^11.0|^12.0", "laravel/prompts": "^0.1|^0.2|^0.3", - "livewire/livewire": "^3.7.3|^4.0", + "livewire/livewire": "^3.5.19", "php": "^8.1", "symfony/console": "^6.0|^7.0" }, - "conflict": { - "livewire/blaze": "<1.0.0" - }, "type": "library", "extra": { "laravel": { @@ -3140,22 +2702,22 @@ ], "support": { "issues": "https://github.com/livewire/flux/issues", - "source": "https://github.com/livewire/flux/tree/v2.10.2" + "source": "https://github.com/livewire/flux/tree/v2.2.3" }, - "time": "2025-12-19T02:11:45+00:00" + "time": "2025-07-11T00:25:51+00:00" }, { "name": "livewire/livewire", - "version": "v4.0.1", + "version": "v3.6.4", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "c7539589d5af82691bef17da17ce4e289269f8d9" + "reference": "ef04be759da41b14d2d129e670533180a44987dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/c7539589d5af82691bef17da17ce4e289269f8d9", - "reference": "c7539589d5af82691bef17da17ce4e289269f8d9", + "url": "https://api.github.com/repos/livewire/livewire/zipball/ef04be759da41b14d2d129e670533180a44987dc", + "reference": "ef04be759da41b14d2d129e670533180a44987dc", "shasum": "" }, "require": { @@ -3210,7 +2772,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v4.0.1" + "source": "https://github.com/livewire/livewire/tree/v3.6.4" }, "funding": [ { @@ -3218,35 +2780,107 @@ "type": "github" } ], - "time": "2026-01-14T18:40:41+00:00" + "time": "2025-07-17T05:12:15+00:00" }, { - "name": "maennchen/zipstream-php", - "version": "3.2.1", + "name": "livewire/volt", + "version": "v1.7.1", "source": { "type": "git", - "url": "https://github.com/maennchen/ZipStream-PHP.git", - "reference": "682f1098a8fddbaf43edac2306a691c7ad508ec5" + "url": "https://github.com/livewire/volt.git", + "reference": "ba3e609fd4c71f8b5783f024baf51715e48e93a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/682f1098a8fddbaf43edac2306a691c7ad508ec5", - "reference": "682f1098a8fddbaf43edac2306a691c7ad508ec5", + "url": "https://api.github.com/repos/livewire/volt/zipball/ba3e609fd4c71f8b5783f024baf51715e48e93a6", + "reference": "ba3e609fd4c71f8b5783f024baf51715e48e93a6", + "shasum": "" + }, + "require": { + "laravel/framework": "^10.38.2|^11.0|^12.0", + "livewire/livewire": "^3.6.1", + "php": "^8.1" + }, + "require-dev": { + "laravel/folio": "^1.1", + "mockery/mockery": "^1.6", + "orchestra/testbench": "^8.15.0|^9.0|^10.0", + "pestphp/pest": "^2.9.5|^3.0", + "phpstan/phpstan": "^1.10" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Livewire\\Volt\\VoltServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "files": [ + "functions.php" + ], + "psr-4": { + "Livewire\\Volt\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "An elegantly crafted functional API for Laravel Livewire.", + "homepage": "https://github.com/livewire/volt", + "keywords": [ + "laravel", + "livewire", + "volt" + ], + "support": { + "issues": "https://github.com/livewire/volt/issues", + "source": "https://github.com/livewire/volt" + }, + "time": "2025-04-08T15:13:36+00:00" + }, + { + "name": "maennchen/zipstream-php", + "version": "3.1.2", + "source": { + "type": "git", + "url": "https://github.com/maennchen/ZipStream-PHP.git", + "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f", + "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f", "shasum": "" }, "require": { "ext-mbstring": "*", "ext-zlib": "*", - "php-64bit": "^8.3" + "php-64bit": "^8.2" }, "require-dev": { "brianium/paratest": "^7.7", "ext-zip": "*", - "friendsofphp/php-cs-fixer": "^3.86", + "friendsofphp/php-cs-fixer": "^3.16", "guzzlehttp/guzzle": "^7.5", "mikey179/vfsstream": "^1.6", "php-coveralls/php-coveralls": "^2.5", - "phpunit/phpunit": "^12.0", + "phpunit/phpunit": "^11.0", "vimeo/psalm": "^6.0" }, "suggest": { @@ -3288,7 +2922,7 @@ ], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.2.1" + "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2" }, "funding": [ { @@ -3296,20 +2930,20 @@ "type": "github" } ], - "time": "2025-12-10T09:58:31+00:00" + "time": "2025-01-27T12:07:53+00:00" }, { "name": "monolog/monolog", - "version": "3.10.0", + "version": "3.9.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0" + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/b321dd6749f0bf7189444158a3ce785cc16d69b0", - "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", "shasum": "" }, "require": { @@ -3327,7 +2961,7 @@ "graylog2/gelf-php": "^1.4.2 || ^2.0", "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.2", - "mongodb/mongodb": "^1.8 || ^2.0", + "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", "php-console/php-console": "^3.1.8", "phpstan/phpstan": "^2", @@ -3387,7 +3021,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.10.0" + "source": "https://github.com/Seldaek/monolog/tree/3.9.0" }, "funding": [ { @@ -3399,7 +3033,7 @@ "type": "tidelift" } ], - "time": "2026-01-02T08:56:05+00:00" + "time": "2025-03-24T10:02:05+00:00" }, { "name": "mtdowling/jmespath.php", @@ -3469,16 +3103,16 @@ }, { "name": "nesbot/carbon", - "version": "3.11.0", + "version": "3.10.1", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "bdb375400dcd162624531666db4799b36b64e4a1" + "reference": "1fd1935b2d90aef2f093c5e35f7ae1257c448d00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/bdb375400dcd162624531666db4799b36b64e4a1", - "reference": "bdb375400dcd162624531666db4799b36b64e4a1", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/1fd1935b2d90aef2f093c5e35f7ae1257c448d00", + "reference": "1fd1935b2d90aef2f093c5e35f7ae1257c448d00", "shasum": "" }, "require": { @@ -3486,9 +3120,9 @@ "ext-json": "*", "php": "^8.1", "psr/clock": "^1.0", - "symfony/clock": "^6.3.12 || ^7.0 || ^8.0", + "symfony/clock": "^6.3.12 || ^7.0", "symfony/polyfill-mbstring": "^1.0", - "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0 || ^8.0" + "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0" }, "provide": { "psr/clock-implementation": "1.0" @@ -3496,13 +3130,13 @@ "require-dev": { "doctrine/dbal": "^3.6.3 || ^4.0", "doctrine/orm": "^2.15.2 || ^3.0", - "friendsofphp/php-cs-fixer": "^v3.87.1", + "friendsofphp/php-cs-fixer": "^3.75.0", "kylekatarnls/multi-tester": "^2.5.3", "phpmd/phpmd": "^2.15.0", "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^2.1.22", - "phpunit/phpunit": "^10.5.53", - "squizlabs/php_codesniffer": "^3.13.4" + "phpstan/phpstan": "^2.1.17", + "phpunit/phpunit": "^10.5.46", + "squizlabs/php_codesniffer": "^3.13.0" }, "bin": [ "bin/carbon" @@ -3570,29 +3204,29 @@ "type": "tidelift" } ], - "time": "2025-12-02T21:04:28+00:00" + "time": "2025-06-21T15:19:35+00:00" }, { "name": "nette/schema", - "version": "v1.3.3", + "version": "v1.3.2", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004" + "reference": "da801d52f0354f70a638673c4a0f04e16529431d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/2befc2f42d7c715fd9d95efc31b1081e5d765004", - "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004", + "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d", "shasum": "" }, "require": { "nette/utils": "^4.0", - "php": "8.1 - 8.5" + "php": "8.1 - 8.4" }, "require-dev": { "nette/tester": "^2.5.2", - "phpstan/phpstan-nette": "^2.0@stable", + "phpstan/phpstan-nette": "^1.0", "tracy/tracy": "^2.8" }, "type": "library", @@ -3602,9 +3236,6 @@ } }, "autoload": { - "psr-4": { - "Nette\\": "src" - }, "classmap": [ "src/" ] @@ -3633,35 +3264,35 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.3.3" + "source": "https://github.com/nette/schema/tree/v1.3.2" }, - "time": "2025-10-30T22:57:59+00:00" + "time": "2024-10-06T23:10:23+00:00" }, { "name": "nette/utils", - "version": "v4.1.1", + "version": "v4.0.7", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72" + "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/c99059c0315591f1a0db7ad6002000288ab8dc72", - "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72", + "url": "https://api.github.com/repos/nette/utils/zipball/e67c4061eb40b9c113b218214e42cb5a0dda28f2", + "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2", "shasum": "" }, "require": { - "php": "8.2 - 8.5" + "php": "8.0 - 8.4" }, "conflict": { "nette/finder": "<3", "nette/schema": "<1.2.2" }, "require-dev": { - "jetbrains/phpstorm-attributes": "^1.2", + "jetbrains/phpstorm-attributes": "dev-master", "nette/tester": "^2.5", - "phpstan/phpstan-nette": "^2.0@stable", + "phpstan/phpstan": "^1.0", "tracy/tracy": "^2.9" }, "suggest": { @@ -3675,13 +3306,10 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.0-dev" } }, "autoload": { - "psr-4": { - "Nette\\": "src" - }, "classmap": [ "src/" ] @@ -3722,22 +3350,22 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.1.1" + "source": "https://github.com/nette/utils/tree/v4.0.7" }, - "time": "2025-12-22T12:14:32+00:00" + "time": "2025-06-03T04:55:08+00:00" }, { "name": "nikic/php-parser", - "version": "v5.7.0", + "version": "v5.5.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", "shasum": "" }, "require": { @@ -3756,7 +3384,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.x-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -3780,37 +3408,37 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" }, - "time": "2025-12-06T11:56:16+00:00" + "time": "2025-05-31T08:24:38+00:00" }, { "name": "nunomaduro/termwind", - "version": "v2.3.3", + "version": "v2.3.1", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017" + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/6fb2a640ff502caace8e05fd7be3b503a7e1c017", - "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.3.6" + "symfony/console": "^7.2.6" }, "require-dev": { - "illuminate/console": "^11.46.1", - "laravel/pint": "^1.25.1", + "illuminate/console": "^11.44.7", + "laravel/pint": "^1.22.0", "mockery/mockery": "^1.6.12", - "pestphp/pest": "^2.36.0 || ^3.8.4 || ^4.1.3", - "phpstan/phpstan": "^1.12.32", + "pestphp/pest": "^2.36.0 || ^3.8.2", + "phpstan/phpstan": "^1.12.25", "phpstan/phpstan-strict-rules": "^1.6.2", - "symfony/var-dumper": "^7.3.5", + "symfony/var-dumper": "^7.2.6", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -3853,7 +3481,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.3.3" + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" }, "funding": [ { @@ -3869,190 +3497,20 @@ "type": "github" } ], - "time": "2025-11-20T02:34:59+00:00" - }, - { - "name": "om/icalparser", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/OzzyCzech/icalparser.git", - "reference": "bc7a82b12455ae9b62ce8e7f2d0273e86c931ecc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/OzzyCzech/icalparser/zipball/bc7a82b12455ae9b62ce8e7f2d0273e86c931ecc", - "reference": "bc7a82b12455ae9b62ce8e7f2d0273e86c931ecc", - "shasum": "" - }, - "require": { - "php": ">=8.1.0" - }, - "require-dev": { - "nette/tester": "^2.5.7" - }, - "suggest": { - "ext-dom": "for timezone tool" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Roman OΕΎana", - "email": "roman@ozana.cz" - } - ], - "description": "Simple iCal parser", - "keywords": [ - "calendar", - "ical", - "parser" - ], - "support": { - "issues": "https://github.com/OzzyCzech/icalparser/issues", - "source": "https://github.com/OzzyCzech/icalparser/tree/v3.2.1" - }, - "time": "2025-12-15T06:25:09+00:00" - }, - { - "name": "paragonie/constant_time_encoding", - "version": "v3.1.3", - "source": { - "type": "git", - "url": "https://github.com/paragonie/constant_time_encoding.git", - "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", - "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", - "shasum": "" - }, - "require": { - "php": "^8" - }, - "require-dev": { - "infection/infection": "^0", - "nikic/php-fuzzer": "^0", - "phpunit/phpunit": "^9|^10|^11", - "vimeo/psalm": "^4|^5|^6" - }, - "type": "library", - "autoload": { - "psr-4": { - "ParagonIE\\ConstantTime\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com", - "role": "Maintainer" - }, - { - "name": "Steve 'Sc00bz' Thomas", - "email": "steve@tobtu.com", - "homepage": "https://www.tobtu.com", - "role": "Original Developer" - } - ], - "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", - "keywords": [ - "base16", - "base32", - "base32_decode", - "base32_encode", - "base64", - "base64_decode", - "base64_encode", - "bin2hex", - "encoding", - "hex", - "hex2bin", - "rfc4648" - ], - "support": { - "email": "info@paragonie.com", - "issues": "https://github.com/paragonie/constant_time_encoding/issues", - "source": "https://github.com/paragonie/constant_time_encoding" - }, - "time": "2025-09-24T15:06:41+00:00" - }, - { - "name": "paragonie/random_compat", - "version": "v9.99.100", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", - "shasum": "" - }, - "require": { - "php": ">= 7" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*", - "vimeo/psalm": "^1" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" - ], - "support": { - "email": "info@paragonie.com", - "issues": "https://github.com/paragonie/random_compat/issues", - "source": "https://github.com/paragonie/random_compat" - }, - "time": "2020-10-15T08:29:30+00:00" + "time": "2025-05-08T08:14:37+00:00" }, { "name": "phpoption/phpoption", - "version": "1.9.5", + "version": "1.9.3", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "75365b91986c2405cf5e1e012c5595cd487a98be" + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be", - "reference": "75365b91986c2405cf5e1e012c5595cd487a98be", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", "shasum": "" }, "require": { @@ -4060,7 +3518,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34" + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "extra": { @@ -4102,7 +3560,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.5" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" }, "funding": [ { @@ -4114,169 +3572,7 @@ "type": "tidelift" } ], - "time": "2025-12-27T19:41:33+00:00" - }, - { - "name": "phpseclib/phpseclib", - "version": "3.0.48", - "source": { - "type": "git", - "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "64065a5679c50acb886e82c07aa139b0f757bb89" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/64065a5679c50acb886e82c07aa139b0f757bb89", - "reference": "64065a5679c50acb886e82c07aa139b0f757bb89", - "shasum": "" - }, - "require": { - "paragonie/constant_time_encoding": "^1|^2|^3", - "paragonie/random_compat": "^1.4|^2.0|^9.99.99", - "php": ">=5.6.1" - }, - "require-dev": { - "phpunit/phpunit": "*" - }, - "suggest": { - "ext-dom": "Install the DOM extension to load XML formatted public keys.", - "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", - "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", - "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", - "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." - }, - "type": "library", - "autoload": { - "files": [ - "phpseclib/bootstrap.php" - ], - "psr-4": { - "phpseclib3\\": "phpseclib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jim Wigginton", - "email": "terrafrost@php.net", - "role": "Lead Developer" - }, - { - "name": "Patrick Monnerat", - "email": "pm@datasphere.ch", - "role": "Developer" - }, - { - "name": "Andreas Fischer", - "email": "bantu@phpbb.com", - "role": "Developer" - }, - { - "name": "Hans-JΓΌrgen Petrich", - "email": "petrich@tronic-media.com", - "role": "Developer" - }, - { - "name": "Graham Campbell", - "email": "graham@alt-three.com", - "role": "Developer" - } - ], - "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", - "homepage": "http://phpseclib.sourceforge.net", - "keywords": [ - "BigInteger", - "aes", - "asn.1", - "asn1", - "blowfish", - "crypto", - "cryptography", - "encryption", - "rsa", - "security", - "sftp", - "signature", - "signing", - "ssh", - "twofish", - "x.509", - "x509" - ], - "support": { - "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.48" - }, - "funding": [ - { - "url": "https://github.com/terrafrost", - "type": "github" - }, - { - "url": "https://www.patreon.com/phpseclib", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", - "type": "tidelift" - } - ], - "time": "2025-12-15T11:51:42+00:00" - }, - { - "name": "pragmarx/google2fa", - "version": "v9.0.0", - "source": { - "type": "git", - "url": "https://github.com/antonioribeiro/google2fa.git", - "reference": "e6bc62dd6ae83acc475f57912e27466019a1f2cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/e6bc62dd6ae83acc475f57912e27466019a1f2cf", - "reference": "e6bc62dd6ae83acc475f57912e27466019a1f2cf", - "shasum": "" - }, - "require": { - "paragonie/constant_time_encoding": "^1.0|^2.0|^3.0", - "php": "^7.1|^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^7.5.15|^8.5|^9.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "PragmaRX\\Google2FA\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Antonio Carlos Ribeiro", - "email": "acr@antoniocarlosribeiro.com", - "role": "Creator & Designer" - } - ], - "description": "A One Time Password Authentication package, compatible with Google Authenticator.", - "keywords": [ - "2fa", - "Authentication", - "Two Factor Authentication", - "google2fa" - ], - "support": { - "issues": "https://github.com/antonioribeiro/google2fa/issues", - "source": "https://github.com/antonioribeiro/google2fa/tree/v9.0.0" - }, - "time": "2025-09-19T22:51:08+00:00" + "time": "2024-07-20T21:41:07+00:00" }, { "name": "psr/clock", @@ -4692,16 +3988,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.18", + "version": "v0.12.9", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "ddff0ac01beddc251786fe70367cd8bbdb258196" + "reference": "1b801844becfe648985372cb4b12ad6840245ace" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/ddff0ac01beddc251786fe70367cd8bbdb258196", - "reference": "ddff0ac01beddc251786fe70367cd8bbdb258196", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/1b801844becfe648985372cb4b12ad6840245ace", + "reference": "1b801844becfe648985372cb4b12ad6840245ace", "shasum": "" }, "require": { @@ -4709,19 +4005,18 @@ "ext-tokenizer": "*", "nikic/php-parser": "^5.0 || ^4.0", "php": "^8.0 || ^7.4", - "symfony/console": "^8.0 || ^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", - "symfony/var-dumper": "^8.0 || ^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" + "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" }, "conflict": { "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.2", - "composer/class-map-generator": "^1.6" + "bamarni/composer-bin-plugin": "^1.2" }, "suggest": { - "composer/class-map-generator": "Improved tab completion performance with better class discovery.", "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." }, "bin": [ @@ -4752,11 +4047,12 @@ "authors": [ { "name": "Justin Hileman", - "email": "justin@justinhileman.info" + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" } ], "description": "An interactive shell for modern PHP.", - "homepage": "https://psysh.org", + "homepage": "http://psysh.org", "keywords": [ "REPL", "console", @@ -4765,9 +4061,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.18" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.9" }, - "time": "2025-12-17T14:35:46+00:00" + "time": "2025-06-23T02:35:06+00:00" }, { "name": "ralouphie/getallheaders", @@ -4891,20 +4187,20 @@ }, { "name": "ramsey/uuid", - "version": "4.9.2", + "version": "4.9.0", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "8429c78ca35a09f27565311b98101e2826affde0" + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/8429c78ca35a09f27565311b98101e2826affde0", - "reference": "8429c78ca35a09f27565311b98101e2826affde0", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0", + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0", "shasum": "" }, "require": { - "brick/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14", + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" }, @@ -4963,22 +4259,22 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.9.2" + "source": "https://github.com/ramsey/uuid/tree/4.9.0" }, - "time": "2025-12-14T04:43:48+00:00" + "time": "2025-06-25T14:20:11+00:00" }, { "name": "spatie/browsershot", - "version": "5.2.0", + "version": "5.0.10", "source": { "type": "git", "url": "https://github.com/spatie/browsershot.git", - "reference": "9bc6b8d67175810d7a399b2588c3401efe2d02a8" + "reference": "9e5ae15487b3cdc3eb03318c1c8ac38971f60e58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/browsershot/zipball/9bc6b8d67175810d7a399b2588c3401efe2d02a8", - "reference": "9bc6b8d67175810d7a399b2588c3401efe2d02a8", + "url": "https://api.github.com/repos/spatie/browsershot/zipball/9e5ae15487b3cdc3eb03318c1c8ac38971f60e58", + "reference": "9e5ae15487b3cdc3eb03318c1c8ac38971f60e58", "shasum": "" }, "require": { @@ -4986,13 +4282,13 @@ "ext-json": "*", "php": "^8.2", "spatie/temporary-directory": "^2.0", - "symfony/process": "^6.0|^7.0|^8.0" + "symfony/process": "^6.0|^7.0" }, "require-dev": { - "pestphp/pest": "^3.0|^4.0", + "pestphp/pest": "^3.0", "spatie/image": "^3.6", "spatie/pdf-to-text": "^1.52", - "spatie/phpunit-snapshot-assertions": "^5.0" + "spatie/phpunit-snapshot-assertions": "^4.2.3|^5.0" }, "type": "library", "autoload": { @@ -5025,7 +4321,7 @@ "webpage" ], "support": { - "source": "https://github.com/spatie/browsershot/tree/5.2.0" + "source": "https://github.com/spatie/browsershot/tree/5.0.10" }, "funding": [ { @@ -5033,20 +4329,20 @@ "type": "github" } ], - "time": "2025-12-22T10:02:16+00:00" + "time": "2025-05-15T07:10:57+00:00" }, { "name": "spatie/laravel-package-tools", - "version": "1.92.7", + "version": "1.92.6", "source": { "type": "git", "url": "https://github.com/spatie/laravel-package-tools.git", - "reference": "f09a799850b1ed765103a4f0b4355006360c49a5" + "reference": "afa90e37741a953d33728e7106a1f24a13fdd808" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/f09a799850b1ed765103a4f0b4355006360c49a5", - "reference": "f09a799850b1ed765103a4f0b4355006360c49a5", + "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/afa90e37741a953d33728e7106a1f24a13fdd808", + "reference": "afa90e37741a953d33728e7106a1f24a13fdd808", "shasum": "" }, "require": { @@ -5086,7 +4382,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-package-tools/issues", - "source": "https://github.com/spatie/laravel-package-tools/tree/1.92.7" + "source": "https://github.com/spatie/laravel-package-tools/tree/1.92.6" }, "funding": [ { @@ -5094,20 +4390,20 @@ "type": "github" } ], - "time": "2025-07-17T15:46:43+00:00" + "time": "2025-07-14T08:02:47+00:00" }, { "name": "spatie/temporary-directory", - "version": "2.3.1", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/spatie/temporary-directory.git", - "reference": "662e481d6ec07ef29fd05010433428851a42cd07" + "reference": "580eddfe9a0a41a902cac6eeb8f066b42e65a32b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/662e481d6ec07ef29fd05010433428851a42cd07", - "reference": "662e481d6ec07ef29fd05010433428851a42cd07", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/580eddfe9a0a41a902cac6eeb8f066b42e65a32b", + "reference": "580eddfe9a0a41a902cac6eeb8f066b42e65a32b", "shasum": "" }, "require": { @@ -5143,7 +4439,7 @@ ], "support": { "issues": "https://github.com/spatie/temporary-directory/issues", - "source": "https://github.com/spatie/temporary-directory/tree/2.3.1" + "source": "https://github.com/spatie/temporary-directory/tree/2.3.0" }, "funding": [ { @@ -5155,91 +4451,26 @@ "type": "github" } ], - "time": "2026-01-12T07:42:22+00:00" - }, - { - "name": "stevebauman/purify", - "version": "v6.3.1", - "source": { - "type": "git", - "url": "https://github.com/stevebauman/purify.git", - "reference": "3acb5e77904f420ce8aad8fa1c7f394e82daa500" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/stevebauman/purify/zipball/3acb5e77904f420ce8aad8fa1c7f394e82daa500", - "reference": "3acb5e77904f420ce8aad8fa1c7f394e82daa500", - "shasum": "" - }, - "require": { - "ezyang/htmlpurifier": "^4.17", - "illuminate/contracts": "^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/support": "^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", - "php": ">=7.4" - }, - "require-dev": { - "orchestra/testbench": "^5.0|^6.0|^7.0|^8.0|^9.0|^10.0", - "phpunit/phpunit": "^8.0|^9.0|^10.0|^11.5.3" - }, - "type": "library", - "extra": { - "laravel": { - "aliases": { - "Purify": "Stevebauman\\Purify\\Facades\\Purify" - }, - "providers": [ - "Stevebauman\\Purify\\PurifyServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Stevebauman\\Purify\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Steve Bauman", - "email": "steven_bauman@outlook.com" - } - ], - "description": "An HTML Purifier / Sanitizer for Laravel", - "keywords": [ - "Purifier", - "clean", - "cleaner", - "html", - "laravel", - "purification", - "purify" - ], - "support": { - "issues": "https://github.com/stevebauman/purify/issues", - "source": "https://github.com/stevebauman/purify/tree/v6.3.1" - }, - "time": "2025-05-21T16:53:09+00:00" + "time": "2025-01-13T13:04:43+00:00" }, { "name": "symfony/clock", - "version": "v8.0.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "832119f9b8dbc6c8e6f65f30c5969eca1e88764f" + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/832119f9b8dbc6c8e6f65f30c5969eca1e88764f", - "reference": "832119f9b8dbc6c8e6f65f30c5969eca1e88764f", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", "shasum": "" }, "require": { - "php": ">=8.4", - "psr/clock": "^1.0" + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" }, "provide": { "psr/clock-implementation": "1.0" @@ -5278,7 +4509,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v8.0.0" + "source": "https://github.com/symfony/clock/tree/v7.3.0" }, "funding": [ { @@ -5289,29 +4520,25 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-11-12T15:46:48+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/console", - "version": "v7.4.3", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6" + "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/732a9ca6cd9dfd940c639062d5edbde2f6727fb6", - "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6", + "url": "https://api.github.com/repos/symfony/console/zipball/9e27aecde8f506ba0fd1d9989620c04a87697101", + "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101", "shasum": "" }, "require": { @@ -5319,7 +4546,7 @@ "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^7.2|^8.0" + "symfony/string": "^7.2" }, "conflict": { "symfony/dependency-injection": "<6.4", @@ -5333,16 +4560,16 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/event-dispatcher": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/lock": "^6.4|^7.0|^8.0", - "symfony/messenger": "^6.4|^7.0|^8.0", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/stopwatch": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5376,7 +4603,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.3" + "source": "https://github.com/symfony/console/tree/v7.3.1" }, "funding": [ { @@ -5387,33 +4614,29 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-12-23T14:50:43+00:00" + "time": "2025-06-27T19:55:54+00:00" }, { "name": "symfony/css-selector", - "version": "v8.0.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "6225bd458c53ecdee056214cb4a2ffaf58bd592b" + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/6225bd458c53ecdee056214cb4a2ffaf58bd592b", - "reference": "6225bd458c53ecdee056214cb4a2ffaf58bd592b", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=8.2" }, "type": "library", "autoload": { @@ -5445,7 +4668,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v8.0.0" + "source": "https://github.com/symfony/css-selector/tree/v7.3.0" }, "funding": [ { @@ -5456,16 +4679,12 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-10-30T14:17:19+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/deprecation-contracts", @@ -5536,33 +4755,32 @@ }, { "name": "symfony/error-handler", - "version": "v7.4.0", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2" + "reference": "35b55b166f6752d6aaf21aa042fc5ed280fce235" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/48be2b0653594eea32dcef130cca1c811dcf25c2", - "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/35b55b166f6752d6aaf21aa042fc5ed280fce235", + "reference": "35b55b166f6752d6aaf21aa042fc5ed280fce235", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/polyfill-php85": "^1.32", - "symfony/var-dumper": "^6.4|^7.0|^8.0" + "symfony/var-dumper": "^6.4|^7.0" }, "conflict": { "symfony/deprecation-contracts": "<2.5", "symfony/http-kernel": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/serializer": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", "symfony/webpack-encore-bundle": "^1.0|^2.0" }, "bin": [ @@ -5594,7 +4812,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.4.0" + "source": "https://github.com/symfony/error-handler/tree/v7.3.1" }, "funding": [ { @@ -5605,37 +4823,33 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-11-05T14:29:59+00:00" + "time": "2025-06-13T07:48:40+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v8.0.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "573f95783a2ec6e38752979db139f09fec033f03" + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/573f95783a2ec6e38752979db139f09fec033f03", - "reference": "573f95783a2ec6e38752979db139f09fec033f03", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d", "shasum": "" }, "require": { - "php": ">=8.4", + "php": ">=8.2", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/security-http": "<7.4", + "symfony/dependency-injection": "<6.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -5644,14 +4858,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^7.4|^8.0", - "symfony/dependency-injection": "^7.4|^8.0", - "symfony/error-handler": "^7.4|^8.0", - "symfony/expression-language": "^7.4|^8.0", - "symfony/framework-bundle": "^7.4|^8.0", - "symfony/http-foundation": "^7.4|^8.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^7.4|^8.0" + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5679,7 +4892,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0" }, "funding": [ { @@ -5690,16 +4903,12 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-10-30T14:17:19+00:00" + "time": "2025-04-22T09:11:45+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -5777,95 +4986,25 @@ ], "time": "2024-09-25T14:21:43+00:00" }, - { - "name": "symfony/filesystem", - "version": "v8.0.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "d937d400b980523dc9ee946bb69972b5e619058d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/d937d400b980523dc9ee946bb69972b5e619058d", - "reference": "d937d400b980523dc9ee946bb69972b5e619058d", - "shasum": "" - }, - "require": { - "php": ">=8.4", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" - }, - "require-dev": { - "symfony/process": "^7.4|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v8.0.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-12-01T09:13:36+00:00" - }, { "name": "symfony/finder", - "version": "v7.4.3", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "fffe05569336549b20a1be64250b40516d6e8d06" + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/fffe05569336549b20a1be64250b40516d6e8d06", - "reference": "fffe05569336549b20a1be64250b40516d6e8d06", + "url": "https://api.github.com/repos/symfony/finder/zipball/ec2344cf77a48253bbca6939aa3d2477773ea63d", + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0|^8.0" + "symfony/filesystem": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5893,7 +5032,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.3" + "source": "https://github.com/symfony/finder/tree/v7.3.0" }, "funding": [ { @@ -5904,35 +5043,32 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-12-23T14:50:43+00:00" + "time": "2024-12-30T19:00:26+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.4.3", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52" + "reference": "23dd60256610c86a3414575b70c596e5deff6ed9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a70c745d4cea48dbd609f4075e5f5cbce453bd52", - "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/23dd60256610c86a3414575b70c596e5deff6ed9", + "reference": "23dd60256610c86a3414575b70c596e5deff6ed9", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "^1.1" + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" }, "conflict": { "doctrine/dbal": "<3.6", @@ -5941,13 +5077,13 @@ "require-dev": { "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4.12|^7.1.5|^8.0", - "symfony/clock": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/mime": "^6.4|^7.0|^8.0", - "symfony/rate-limiter": "^6.4|^7.0|^8.0" + "symfony/cache": "^6.4.12|^7.1.5", + "symfony/clock": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5975,7 +5111,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.4.3" + "source": "https://github.com/symfony/http-foundation/tree/v7.3.1" }, "funding": [ { @@ -5986,38 +5122,34 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-12-23T14:23:49+00:00" + "time": "2025-06-23T15:07:14+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.4.3", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "885211d4bed3f857b8c964011923528a55702aa5" + "reference": "1644879a66e4aa29c36fe33dfa6c54b450ce1831" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/885211d4bed3f857b8c964011923528a55702aa5", - "reference": "885211d4bed3f857b8c964011923528a55702aa5", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/1644879a66e4aa29c36fe33dfa6c54b450ce1831", + "reference": "1644879a66e4aa29c36fe33dfa6c54b450ce1831", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0|^8.0", - "symfony/event-dispatcher": "^7.3|^8.0", - "symfony/http-foundation": "^7.4|^8.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^7.3", + "symfony/http-foundation": "^7.3", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -6027,7 +5159,6 @@ "symfony/console": "<6.4", "symfony/dependency-injection": "<6.4", "symfony/doctrine-bridge": "<6.4", - "symfony/flex": "<2.10", "symfony/form": "<6.4", "symfony/http-client": "<6.4", "symfony/http-client-contracts": "<2.5", @@ -6045,27 +5176,27 @@ }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^6.4|^7.0|^8.0", - "symfony/clock": "^6.4|^7.0|^8.0", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/css-selector": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/dom-crawler": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/property-access": "^7.1|^8.0", - "symfony/routing": "^6.4|^7.0|^8.0", - "symfony/serializer": "^7.1|^8.0", - "symfony/stopwatch": "^6.4|^7.0|^8.0", - "symfony/translation": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^7.1", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^7.1", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^6.4|^7.0|^8.0", - "symfony/validator": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0", - "symfony/var-exporter": "^6.4|^7.0|^8.0", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", "twig/twig": "^3.12" }, "type": "library", @@ -6094,7 +5225,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.4.3" + "source": "https://github.com/symfony/http-kernel/tree/v7.3.1" }, "funding": [ { @@ -6105,29 +5236,25 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-12-31T08:43:57+00:00" + "time": "2025-06-28T08:24:55+00:00" }, { "name": "symfony/mailer", - "version": "v7.4.3", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "e472d35e230108231ccb7f51eb6b2100cac02ee4" + "reference": "b5db5105b290bdbea5ab27b89c69effcf1cb3368" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/e472d35e230108231ccb7f51eb6b2100cac02ee4", - "reference": "e472d35e230108231ccb7f51eb6b2100cac02ee4", + "url": "https://api.github.com/repos/symfony/mailer/zipball/b5db5105b290bdbea5ab27b89c69effcf1cb3368", + "reference": "b5db5105b290bdbea5ab27b89c69effcf1cb3368", "shasum": "" }, "require": { @@ -6135,8 +5262,8 @@ "php": ">=8.2", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^6.4|^7.0|^8.0", - "symfony/mime": "^7.2|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/mime": "^7.2", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -6147,10 +5274,10 @@ "symfony/twig-bridge": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/http-client": "^6.4|^7.0|^8.0", - "symfony/messenger": "^6.4|^7.0|^8.0", - "symfony/twig-bridge": "^6.4|^7.0|^8.0" + "symfony/console": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -6178,7 +5305,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.4.3" + "source": "https://github.com/symfony/mailer/tree/v7.3.1" }, "funding": [ { @@ -6189,34 +5316,29 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-12-16T08:02:06+00:00" + "time": "2025-06-27T19:55:54+00:00" }, { "name": "symfony/mime", - "version": "v7.4.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a" + "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/bdb02729471be5d047a3ac4a69068748f1a6be7a", - "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a", + "url": "https://api.github.com/repos/symfony/mime/zipball/0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9", + "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -6231,11 +5353,11 @@ "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/property-access": "^6.4|^7.0|^8.0", - "symfony/property-info": "^6.4|^7.0|^8.0", - "symfony/serializer": "^6.4.3|^7.0.3|^8.0" + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" }, "type": "library", "autoload": { @@ -6267,7 +5389,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.4.0" + "source": "https://github.com/symfony/mime/tree/v7.3.0" }, "funding": [ { @@ -6278,20 +5400,16 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-11-16T10:14:42+00:00" + "time": "2025-02-19T08:51:26+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.33.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -6350,7 +5468,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" }, "funding": [ { @@ -6361,10 +5479,6 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -6374,16 +5488,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.33.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { @@ -6432,7 +5546,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" }, "funding": [ { @@ -6443,20 +5557,16 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-27T09:58:17+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.33.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", @@ -6519,7 +5629,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" }, "funding": [ { @@ -6530,10 +5640,6 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -6543,7 +5649,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.33.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -6604,7 +5710,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" }, "funding": [ { @@ -6615,10 +5721,6 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -6628,7 +5730,7 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", @@ -6689,7 +5791,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" }, "funding": [ { @@ -6700,10 +5802,6 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -6713,7 +5811,7 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.33.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", @@ -6773,7 +5871,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" }, "funding": [ { @@ -6784,10 +5882,6 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -6797,16 +5891,16 @@ }, { "name": "symfony/polyfill-php83", - "version": "v1.33.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", "shasum": "" }, "require": { @@ -6853,7 +5947,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" }, "funding": [ { @@ -6864,180 +5958,16 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-07-08T02:45:35+00:00" - }, - { - "name": "symfony/polyfill-php84", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php84.git", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php84\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-06-24T13:30:11+00:00" - }, - { - "name": "symfony/polyfill-php85", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php85.git", - "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", - "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php85\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-06-23T16:12:55+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.33.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", @@ -7096,7 +6026,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.32.0" }, "funding": [ { @@ -7107,10 +6037,6 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -7120,16 +6046,16 @@ }, { "name": "symfony/process", - "version": "v7.4.3", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "2f8e1a6cdf590ca63715da4d3a7a3327404a523f" + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/2f8e1a6cdf590ca63715da4d3a7a3327404a523f", - "reference": "2f8e1a6cdf590ca63715da4d3a7a3327404a523f", + "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", "shasum": "" }, "require": { @@ -7161,7 +6087,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.4.3" + "source": "https://github.com/symfony/process/tree/v7.3.0" }, "funding": [ { @@ -7172,29 +6098,25 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-12-19T10:00:43+00:00" + "time": "2025-04-17T09:11:12+00:00" }, { "name": "symfony/routing", - "version": "v7.4.3", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090" + "reference": "8e213820c5fea844ecea29203d2a308019007c15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090", - "reference": "5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090", + "url": "https://api.github.com/repos/symfony/routing/zipball/8e213820c5fea844ecea29203d2a308019007c15", + "reference": "8e213820c5fea844ecea29203d2a308019007c15", "shasum": "" }, "require": { @@ -7208,11 +6130,11 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/yaml": "^6.4|^7.0|^8.0" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -7246,7 +6168,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.4.3" + "source": "https://github.com/symfony/routing/tree/v7.3.0" }, "funding": [ { @@ -7257,29 +6179,25 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-12-19T10:00:43+00:00" + "time": "2025-05-24T20:43:28+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.6.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", "shasum": "" }, "require": { @@ -7333,7 +6251,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -7344,47 +6262,44 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-07-15T11:30:57+00:00" + "time": "2025-04-25T09:37:31+00:00" }, { "name": "symfony/string", - "version": "v8.0.1", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "ba65a969ac918ce0cc3edfac6cdde847eba231dc" + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ba65a969ac918ce0cc3edfac6cdde847eba231dc", - "reference": "ba65a969ac918ce0cc3edfac6cdde847eba231dc", + "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125", "shasum": "" }, "require": { - "php": ">=8.4", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-intl-grapheme": "^1.33", - "symfony/polyfill-intl-normalizer": "^1.0", - "symfony/polyfill-mbstring": "^1.0" + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/emoji": "^7.4|^8.0", - "symfony/http-client": "^7.4|^8.0", - "symfony/intl": "^7.4|^8.0", + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^7.4|^8.0" + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -7423,7 +6338,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v8.0.1" + "source": "https://github.com/symfony/string/tree/v7.3.0" }, "funding": [ { @@ -7434,40 +6349,43 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-12-01T09:13:36+00:00" + "time": "2025-04-20T20:19:01+00:00" }, { "name": "symfony/translation", - "version": "v8.0.3", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "60a8f11f0e15c48f2cc47c4da53873bb5b62135d" + "reference": "241d5ac4910d256660238a7ecf250deba4c73063" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/60a8f11f0e15c48f2cc47c4da53873bb5b62135d", - "reference": "60a8f11f0e15c48f2cc47c4da53873bb5b62135d", + "url": "https://api.github.com/repos/symfony/translation/zipball/241d5ac4910d256660238a7ecf250deba4c73063", + "reference": "241d5ac4910d256660238a7ecf250deba4c73063", "shasum": "" }, "require": { - "php": ">=8.4", - "symfony/polyfill-mbstring": "^1.0", - "symfony/translation-contracts": "^3.6.1" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" }, "conflict": { "nikic/php-parser": "<5.0", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", "symfony/http-client-contracts": "<2.5", - "symfony/service-contracts": "<2.5" + "symfony/http-kernel": "<6.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<6.4", + "symfony/yaml": "<6.4" }, "provide": { "symfony/translation-implementation": "2.3|3.0" @@ -7475,17 +6393,17 @@ "require-dev": { "nikic/php-parser": "^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^7.4|^8.0", - "symfony/console": "^7.4|^8.0", - "symfony/dependency-injection": "^7.4|^8.0", - "symfony/finder": "^7.4|^8.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^7.4|^8.0", - "symfony/intl": "^7.4|^8.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^7.4|^8.0", + "symfony/routing": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^7.4|^8.0" + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -7516,7 +6434,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v8.0.3" + "source": "https://github.com/symfony/translation/tree/v7.3.1" }, "funding": [ { @@ -7527,29 +6445,25 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-12-21T10:59:45+00:00" + "time": "2025-06-27T19:55:54+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.6.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "65a8bc82080447fae78373aa10f8d13b38338977" + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/65a8bc82080447fae78373aa10f8d13b38338977", - "reference": "65a8bc82080447fae78373aa10f8d13b38338977", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", "shasum": "" }, "require": { @@ -7598,7 +6512,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.6.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" }, "funding": [ { @@ -7609,29 +6523,25 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-07-15T13:41:35+00:00" + "time": "2024-09-27T08:32:26+00:00" }, { "name": "symfony/uid", - "version": "v7.4.0", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "2498e9f81b7baa206f44de583f2f48350b90142c" + "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/2498e9f81b7baa206f44de583f2f48350b90142c", - "reference": "2498e9f81b7baa206f44de583f2f48350b90142c", + "url": "https://api.github.com/repos/symfony/uid/zipball/a69f69f3159b852651a6bf45a9fdd149520525bb", + "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb", "shasum": "" }, "require": { @@ -7639,7 +6549,7 @@ "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0" + "symfony/console": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -7676,7 +6586,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.4.0" + "source": "https://github.com/symfony/uid/tree/v7.3.1" }, "funding": [ { @@ -7687,29 +6597,25 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-09-25T11:02:55+00:00" + "time": "2025-06-27T19:55:54+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.4.3", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "7e99bebcb3f90d8721890f2963463280848cba92" + "reference": "6e209fbe5f5a7b6043baba46fe5735a4b85d0d42" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7e99bebcb3f90d8721890f2963463280848cba92", - "reference": "7e99bebcb3f90d8721890f2963463280848cba92", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6e209fbe5f5a7b6043baba46fe5735a4b85d0d42", + "reference": "6e209fbe5f5a7b6043baba46fe5735a4b85d0d42", "shasum": "" }, "require": { @@ -7721,10 +6627,11 @@ "symfony/console": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/uid": "^6.4|^7.0|^8.0", + "ext-iconv": "*", + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", "twig/twig": "^3.12" }, "bin": [ @@ -7763,7 +6670,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.4.3" + "source": "https://github.com/symfony/var-dumper/tree/v7.3.1" }, "funding": [ { @@ -7774,29 +6681,25 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-12-18T07:04:31+00:00" + "time": "2025-06-27T19:55:54+00:00" }, { "name": "symfony/var-exporter", - "version": "v7.4.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "03a60f169c79a28513a78c967316fbc8bf17816f" + "reference": "c9a1168891b5aaadfd6332ef44393330b3498c4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/03a60f169c79a28513a78c967316fbc8bf17816f", - "reference": "03a60f169c79a28513a78c967316fbc8bf17816f", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/c9a1168891b5aaadfd6332ef44393330b3498c4c", + "reference": "c9a1168891b5aaadfd6332ef44393330b3498c4c", "shasum": "" }, "require": { @@ -7804,9 +6707,9 @@ "symfony/deprecation-contracts": "^2.5|^3" }, "require-dev": { - "symfony/property-access": "^6.4|^7.0|^8.0", - "symfony/serializer": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0" + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -7844,7 +6747,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.4.0" + "source": "https://github.com/symfony/var-exporter/tree/v7.3.0" }, "funding": [ { @@ -7855,112 +6758,32 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-09-11T10:15:23+00:00" - }, - { - "name": "symfony/yaml", - "version": "v7.4.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "24dd4de28d2e3988b311751ac49e684d783e2345" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/24dd4de28d2e3988b311751ac49e684d783e2345", - "reference": "24dd4de28d2e3988b311751ac49e684d783e2345", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "symfony/console": "<6.4" - }, - "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0" - }, - "bin": [ - "Resources/bin/yaml-lint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Loads and dumps YAML files", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/yaml/tree/v7.4.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-12-04T18:11:45+00:00" + "time": "2025-05-15T09:04:05+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", - "version": "v2.4.0", + "version": "v2.3.0", "source": { "type": "git", "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", - "reference": "f0292ccf0ec75843d65027214426b6b163b48b41" + "reference": "0d72ac1c00084279c1816675284073c5a337c20d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/f0292ccf0ec75843d65027214426b6b163b48b41", - "reference": "f0292ccf0ec75843d65027214426b6b163b48b41", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/0d72ac1c00084279c1816675284073c5a337c20d", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "php": "^7.4 || ^8.0", - "symfony/css-selector": "^5.4 || ^6.0 || ^7.0 || ^8.0" + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0" }, "require-dev": { "phpstan/phpstan": "^2.0", @@ -7993,32 +6816,32 @@ "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", "support": { "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", - "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.4.0" + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.3.0" }, - "time": "2025-12-02T11:56:42+00:00" + "time": "2024-12-21T16:25:41+00:00" }, { "name": "vlucas/phpdotenv", - "version": "v5.6.3", + "version": "v5.6.2", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "955e7815d677a3eaa7075231212f2110983adecc" + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc", - "reference": "955e7815d677a3eaa7075231212f2110983adecc", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.1.4", + "graham-campbell/result-type": "^1.1.3", "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.5", - "symfony/polyfill-ctype": "^1.26", - "symfony/polyfill-mbstring": "^1.26", - "symfony/polyfill-php80": "^1.26" + "phpoption/phpoption": "^1.9.3", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", @@ -8067,7 +6890,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.3" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" }, "funding": [ { @@ -8079,7 +6902,7 @@ "type": "tidelift" } ], - "time": "2025-12-27T19:49:13+00:00" + "time": "2025-04-30T23:37:27+00:00" }, { "name": "voku/portable-ascii", @@ -8156,23 +6979,81 @@ "time": "2024-11-21T01:49:47+00:00" }, { - "name": "wnx/sidecar-browsershot", - "version": "v2.7.0", + "name": "webmozart/assert", + "version": "1.11.0", "source": { "type": "git", - "url": "https://github.com/stefanzweifel/sidecar-browsershot.git", - "reference": "e42a996c6fab4357919cd5e3f3fab33f019cdd80" + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stefanzweifel/sidecar-browsershot/zipball/e42a996c6fab4357919cd5e3f3fab33f019cdd80", - "reference": "e42a996c6fab4357919cd5e3f3fab33f019cdd80", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", "shasum": "" }, "require": { - "hammerstone/sidecar": "^0.7", - "illuminate/contracts": "^12.0", - "php": "^8.4", + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + }, + { + "name": "wnx/sidecar-browsershot", + "version": "v2.6.0", + "source": { + "type": "git", + "url": "https://github.com/stefanzweifel/sidecar-browsershot.git", + "reference": "20c5a56c34298f7edb7334890e919c0521a7f467" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/stefanzweifel/sidecar-browsershot/zipball/20c5a56c34298f7edb7334890e919c0521a7f467", + "reference": "20c5a56c34298f7edb7334890e919c0521a7f467", + "shasum": "" + }, + "require": { + "hammerstone/sidecar": "^0.4 || ^0.5 || ^0.6 || ^0.7", + "illuminate/contracts": "^10.0 || ^11.0 || ^12.0", + "php": "^8.2", "spatie/browsershot": "^4.0 || ^5.0", "spatie/laravel-package-tools": "^1.9.2" }, @@ -8181,15 +7062,15 @@ "laravel/pint": "^1.13", "league/flysystem-aws-s3-v3": "^1.0|^2.0|^3.0", "nunomaduro/collision": "^7.0|^8.0", - "orchestra/testbench": "^10.0", - "pestphp/pest": "^3.0|^4.0", - "pestphp/pest-plugin-laravel": "^3.0|^4.0", + "orchestra/testbench": "^8.0|^9.0|^10.0", + "pestphp/pest": "^2.0|^3.0", + "pestphp/pest-plugin-laravel": "^2.0|^3.0", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", - "phpstan/phpstan-phpunit": "^1.0|^2.0", - "phpunit/phpunit": "^11.0 | ^12.0", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^10 | ^11.0", "spatie/image": "^3.3", - "spatie/pixelmatch-php": "^1.0" + "spatie/pixelmatch-php": "dev-main" }, "type": "library", "extra": { @@ -8231,7 +7112,7 @@ ], "support": { "issues": "https://github.com/stefanzweifel/sidecar-browsershot/issues", - "source": "https://github.com/stefanzweifel/sidecar-browsershot/tree/v2.7.0" + "source": "https://github.com/stefanzweifel/sidecar-browsershot/tree/v2.6.0" }, "funding": [ { @@ -8239,22 +7120,22 @@ "type": "github" } ], - "time": "2025-11-22T08:49:08+00:00" + "time": "2025-05-08T06:40:32+00:00" } ], "packages-dev": [ { "name": "brianium/paratest", - "version": "v7.16.1", + "version": "v7.8.3", "source": { "type": "git", "url": "https://github.com/paratestphp/paratest.git", - "reference": "f0fdfd8e654e0d38bc2ba756a6cabe7be287390b" + "reference": "a585c346ddf1bec22e51e20b5387607905604a71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/f0fdfd8e654e0d38bc2ba756a6cabe7be287390b", - "reference": "f0fdfd8e654e0d38bc2ba756a6cabe7be287390b", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/a585c346ddf1bec22e51e20b5387607905604a71", + "reference": "a585c346ddf1bec22e51e20b5387607905604a71", "shasum": "" }, "require": { @@ -8262,27 +7143,27 @@ "ext-pcre": "*", "ext-reflection": "*", "ext-simplexml": "*", - "fidry/cpu-core-counter": "^1.3.0", - "jean85/pretty-package-versions": "^2.1.1", - "php": "~8.3.0 || ~8.4.0 || ~8.5.0", - "phpunit/php-code-coverage": "^12.5.2", - "phpunit/php-file-iterator": "^6", - "phpunit/php-timer": "^8", - "phpunit/phpunit": "^12.5.4", - "sebastian/environment": "^8.0.3", - "symfony/console": "^7.3.4 || ^8.0.0", - "symfony/process": "^7.3.4 || ^8.0.0" + "fidry/cpu-core-counter": "^1.2.0", + "jean85/pretty-package-versions": "^2.1.0", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0", + "phpunit/php-code-coverage": "^11.0.9 || ^12.0.4", + "phpunit/php-file-iterator": "^5.1.0 || ^6", + "phpunit/php-timer": "^7.0.1 || ^8", + "phpunit/phpunit": "^11.5.11 || ^12.0.6", + "sebastian/environment": "^7.2.0 || ^8", + "symfony/console": "^6.4.17 || ^7.2.1", + "symfony/process": "^6.4.19 || ^7.2.4" }, "require-dev": { - "doctrine/coding-standard": "^14.0.0", - "ext-pcntl": "*", + "doctrine/coding-standard": "^12.0.0", "ext-pcov": "*", "ext-posix": "*", - "phpstan/phpstan": "^2.1.33", - "phpstan/phpstan-deprecation-rules": "^2.0.3", - "phpstan/phpstan-phpunit": "^2.0.11", - "phpstan/phpstan-strict-rules": "^2.0.7", - "symfony/filesystem": "^7.3.2 || ^8.0.0" + "phpstan/phpstan": "^2.1.6", + "phpstan/phpstan-deprecation-rules": "^2.0.1", + "phpstan/phpstan-phpunit": "^2.0.4", + "phpstan/phpstan-strict-rules": "^2.0.3", + "squizlabs/php_codesniffer": "^3.11.3", + "symfony/filesystem": "^6.4.13 || ^7.2.0" }, "bin": [ "bin/paratest", @@ -8322,7 +7203,7 @@ ], "support": { "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v7.16.1" + "source": "https://github.com/paratestphp/paratest/tree/v7.8.3" }, "funding": [ { @@ -8334,7 +7215,7 @@ "type": "paypal" } ], - "time": "2026-01-08T07:23:06+00:00" + "time": "2025-03-05T08:29:11+00:00" }, { "name": "doctrine/deprecations", @@ -8449,16 +7330,16 @@ }, { "name": "fidry/cpu-core-counter", - "version": "1.3.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "db9508f7b1474469d9d3c53b86f817e344732678" + "reference": "8520451a140d3f46ac33042715115e290cf5785f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", - "reference": "db9508f7b1474469d9d3c53b86f817e344732678", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", + "reference": "8520451a140d3f46ac33042715115e290cf5785f", "shasum": "" }, "require": { @@ -8468,10 +7349,10 @@ "fidry/makefile": "^0.2.0", "fidry/php-cs-fixer-config": "^1.1.2", "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^2.0", - "phpstan/phpstan-deprecation-rules": "^2.0.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", + "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.2.2", + "phpstan/phpstan-strict-rules": "^1.4.4", "phpunit/phpunit": "^8.5.31 || ^9.5.26", "webmozarts/strict-phpunit": "^7.5" }, @@ -8498,7 +7379,7 @@ ], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" }, "funding": [ { @@ -8506,20 +7387,20 @@ "type": "github" } ], - "time": "2025-08-14T07:29:31+00:00" + "time": "2024-08-06T10:04:20+00:00" }, { "name": "filp/whoops", - "version": "2.18.4", + "version": "2.18.3", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d" + "reference": "59a123a3d459c5a23055802237cb317f609867e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/d2102955e48b9fd9ab24280a7ad12ed552752c4d", - "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d", + "url": "https://api.github.com/repos/filp/whoops/zipball/59a123a3d459c5a23055802237cb317f609867e5", + "reference": "59a123a3d459c5a23055802237cb317f609867e5", "shasum": "" }, "require": { @@ -8569,7 +7450,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.18.4" + "source": "https://github.com/filp/whoops/tree/2.18.3" }, "funding": [ { @@ -8577,7 +7458,7 @@ "type": "github" } ], - "time": "2025-08-08T12:00:00+00:00" + "time": "2025-06-16T00:02:10+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -8733,16 +7614,16 @@ }, { "name": "larastan/larastan", - "version": "v3.8.1", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/larastan/larastan.git", - "reference": "ff3725291bc4c7e6032b5a54776e3e5104c86db9" + "reference": "e8ccd73008487ba91da9877b373f8c447743f1ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/ff3725291bc4c7e6032b5a54776e3e5104c86db9", - "reference": "ff3725291bc4c7e6032b5a54776e3e5104c86db9", + "url": "https://api.github.com/repos/larastan/larastan/zipball/e8ccd73008487ba91da9877b373f8c447743f1ce", + "reference": "e8ccd73008487ba91da9877b373f8c447743f1ce", "shasum": "" }, "require": { @@ -8756,7 +7637,7 @@ "illuminate/pipeline": "^11.44.2 || ^12.4.1", "illuminate/support": "^11.44.2 || ^12.4.1", "php": "^8.2", - "phpstan/phpstan": "^2.1.32" + "phpstan/phpstan": "^2.1.11" }, "require-dev": { "doctrine/coding-standard": "^13", @@ -8769,8 +7650,7 @@ "phpunit/phpunit": "^10.5.35 || ^11.5.15" }, "suggest": { - "orchestra/testbench": "Using Larastan for analysing a package needs Testbench", - "phpmyadmin/sql-parser": "Install to enable Larastan's optional phpMyAdmin-based SQL parser automatically" + "orchestra/testbench": "Using Larastan for analysing a package needs Testbench" }, "type": "phpstan-extension", "extra": { @@ -8811,7 +7691,7 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v3.8.1" + "source": "https://github.com/larastan/larastan/tree/v3.5.0" }, "funding": [ { @@ -8819,159 +7699,20 @@ "type": "github" } ], - "time": "2025-12-11T16:37:35+00:00" - }, - { - "name": "laravel/boost", - "version": "v1.8.10", - "source": { - "type": "git", - "url": "https://github.com/laravel/boost.git", - "reference": "aad8b2a423b0a886c2ce7ee92abbfde69992ff32" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/boost/zipball/aad8b2a423b0a886c2ce7ee92abbfde69992ff32", - "reference": "aad8b2a423b0a886c2ce7ee92abbfde69992ff32", - "shasum": "" - }, - "require": { - "guzzlehttp/guzzle": "^7.9", - "illuminate/console": "^10.49.0|^11.45.3|^12.41.1", - "illuminate/contracts": "^10.49.0|^11.45.3|^12.41.1", - "illuminate/routing": "^10.49.0|^11.45.3|^12.41.1", - "illuminate/support": "^10.49.0|^11.45.3|^12.41.1", - "laravel/mcp": "^0.5.1", - "laravel/prompts": "0.1.25|^0.3.6", - "laravel/roster": "^0.2.9", - "php": "^8.1" - }, - "require-dev": { - "laravel/pint": "^1.20.0", - "mockery/mockery": "^1.6.12", - "orchestra/testbench": "^8.36.0|^9.15.0|^10.6", - "pestphp/pest": "^2.36.0|^3.8.4|^4.1.5", - "phpstan/phpstan": "^2.1.27", - "rector/rector": "^2.1" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Laravel\\Boost\\BoostServiceProvider" - ] - }, - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Laravel\\Boost\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Laravel Boost accelerates AI-assisted development by providing the essential context and structure that AI needs to generate high-quality, Laravel-specific code.", - "homepage": "https://github.com/laravel/boost", - "keywords": [ - "ai", - "dev", - "laravel" - ], - "support": { - "issues": "https://github.com/laravel/boost/issues", - "source": "https://github.com/laravel/boost" - }, - "time": "2026-01-14T14:51:16+00:00" - }, - { - "name": "laravel/mcp", - "version": "v0.5.2", - "source": { - "type": "git", - "url": "https://github.com/laravel/mcp.git", - "reference": "b9bdd8d6f8b547c8733fe6826b1819341597ba3c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/mcp/zipball/b9bdd8d6f8b547c8733fe6826b1819341597ba3c", - "reference": "b9bdd8d6f8b547c8733fe6826b1819341597ba3c", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-mbstring": "*", - "illuminate/console": "^10.49.0|^11.45.3|^12.41.1", - "illuminate/container": "^10.49.0|^11.45.3|^12.41.1", - "illuminate/contracts": "^10.49.0|^11.45.3|^12.41.1", - "illuminate/http": "^10.49.0|^11.45.3|^12.41.1", - "illuminate/json-schema": "^12.41.1", - "illuminate/routing": "^10.49.0|^11.45.3|^12.41.1", - "illuminate/support": "^10.49.0|^11.45.3|^12.41.1", - "illuminate/validation": "^10.49.0|^11.45.3|^12.41.1", - "php": "^8.1" - }, - "require-dev": { - "laravel/pint": "^1.20", - "orchestra/testbench": "^8.36|^9.15|^10.8", - "pestphp/pest": "^2.36.0|^3.8.4|^4.1.0", - "phpstan/phpstan": "^2.1.27", - "rector/rector": "^2.2.4" - }, - "type": "library", - "extra": { - "laravel": { - "aliases": { - "Mcp": "Laravel\\Mcp\\Server\\Facades\\Mcp" - }, - "providers": [ - "Laravel\\Mcp\\Server\\McpServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Laravel\\Mcp\\": "src/", - "Laravel\\Mcp\\Server\\": "src/Server/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Rapidly build MCP servers for your Laravel applications.", - "homepage": "https://github.com/laravel/mcp", - "keywords": [ - "laravel", - "mcp" - ], - "support": { - "issues": "https://github.com/laravel/mcp/issues", - "source": "https://github.com/laravel/mcp" - }, - "time": "2025-12-19T19:32:34+00:00" + "time": "2025-06-19T22:41:50+00:00" }, { "name": "laravel/pail", - "version": "v1.2.4", + "version": "v1.2.3", "source": { "type": "git", "url": "https://github.com/laravel/pail.git", - "reference": "49f92285ff5d6fc09816e976a004f8dec6a0ea30" + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pail/zipball/49f92285ff5d6fc09816e976a004f8dec6a0ea30", - "reference": "49f92285ff5d6fc09816e976a004f8dec6a0ea30", + "url": "https://api.github.com/repos/laravel/pail/zipball/8cc3d575c1f0e57eeb923f366a37528c50d2385a", + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a", "shasum": "" }, "require": { @@ -8988,9 +7729,9 @@ "require-dev": { "laravel/framework": "^10.24|^11.0|^12.0", "laravel/pint": "^1.13", - "orchestra/testbench-core": "^8.13|^9.17|^10.8", - "pestphp/pest": "^2.20|^3.0|^4.0", - "pestphp/pest-plugin-type-coverage": "^2.3|^3.0|^4.0", + "orchestra/testbench-core": "^8.13|^9.0|^10.0", + "pestphp/pest": "^2.20|^3.0", + "pestphp/pest-plugin-type-coverage": "^2.3|^3.0", "phpstan/phpstan": "^1.12.27", "symfony/var-dumper": "^6.3|^7.0" }, @@ -9037,20 +7778,20 @@ "issues": "https://github.com/laravel/pail/issues", "source": "https://github.com/laravel/pail" }, - "time": "2025-11-20T16:29:35+00:00" + "time": "2025-06-05T13:55:57+00:00" }, { "name": "laravel/pint", - "version": "v1.27.0", + "version": "v1.24.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "c67b4195b75491e4dfc6b00b1c78b68d86f54c90" + "reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/c67b4195b75491e4dfc6b00b1c78b68d86f54c90", - "reference": "c67b4195b75491e4dfc6b00b1c78b68d86f54c90", + "url": "https://api.github.com/repos/laravel/pint/zipball/0345f3b05f136801af8c339f9d16ef29e6b4df8a", + "reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a", "shasum": "" }, "require": { @@ -9061,19 +7802,22 @@ "php": "^8.2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.92.4", - "illuminate/view": "^12.44.0", - "larastan/larastan": "^3.8.1", - "laravel-zero/framework": "^12.0.4", + "friendsofphp/php-cs-fixer": "^3.82.2", + "illuminate/view": "^11.45.1", + "larastan/larastan": "^3.5.0", + "laravel-zero/framework": "^11.45.0", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^2.3.3", - "pestphp/pest": "^3.8.4" + "nunomaduro/termwind": "^2.3.1", + "pestphp/pest": "^2.36.0" }, "bin": [ "builds/pint" ], "type": "project", "autoload": { + "files": [ + "overrides/Runner/Parallel/ProcessFactory.php" + ], "psr-4": { "App\\": "app/", "Database\\Seeders\\": "database/seeders/", @@ -9093,7 +7837,6 @@ "description": "An opinionated code formatter for PHP.", "homepage": "https://laravel.com", "keywords": [ - "dev", "format", "formatter", "lint", @@ -9104,81 +7847,20 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2026-01-05T16:49:17+00:00" - }, - { - "name": "laravel/roster", - "version": "v0.2.9", - "source": { - "type": "git", - "url": "https://github.com/laravel/roster.git", - "reference": "82bbd0e2de614906811aebdf16b4305956816fa6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/roster/zipball/82bbd0e2de614906811aebdf16b4305956816fa6", - "reference": "82bbd0e2de614906811aebdf16b4305956816fa6", - "shasum": "" - }, - "require": { - "illuminate/console": "^10.0|^11.0|^12.0", - "illuminate/contracts": "^10.0|^11.0|^12.0", - "illuminate/routing": "^10.0|^11.0|^12.0", - "illuminate/support": "^10.0|^11.0|^12.0", - "php": "^8.1|^8.2", - "symfony/yaml": "^6.4|^7.2" - }, - "require-dev": { - "laravel/pint": "^1.14", - "mockery/mockery": "^1.6", - "orchestra/testbench": "^8.22.0|^9.0|^10.0", - "pestphp/pest": "^2.0|^3.0", - "phpstan/phpstan": "^2.0" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Laravel\\Roster\\RosterServiceProvider" - ] - }, - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Laravel\\Roster\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Detect packages & approaches in use within a Laravel project", - "homepage": "https://github.com/laravel/roster", - "keywords": [ - "dev", - "laravel" - ], - "support": { - "issues": "https://github.com/laravel/roster/issues", - "source": "https://github.com/laravel/roster" - }, - "time": "2025-10-20T09:56:46+00:00" + "time": "2025-07-10T18:09:32+00:00" }, { "name": "laravel/sail", - "version": "v1.52.0", + "version": "v1.43.1", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "64ac7d8abb2dbcf2b76e61289451bae79066b0b3" + "reference": "3e7d899232a8c5e3ea4fc6dee7525ad583887e72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/64ac7d8abb2dbcf2b76e61289451bae79066b0b3", - "reference": "64ac7d8abb2dbcf2b76e61289451bae79066b0b3", + "url": "https://api.github.com/repos/laravel/sail/zipball/3e7d899232a8c5e3ea4fc6dee7525ad583887e72", + "reference": "3e7d899232a8c5e3ea4fc6dee7525ad583887e72", "shasum": "" }, "require": { @@ -9191,7 +7873,7 @@ }, "require-dev": { "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", - "phpstan/phpstan": "^2.0" + "phpstan/phpstan": "^1.10" }, "bin": [ "bin/sail" @@ -9228,7 +7910,7 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2026-01-01T02:46:03+00:00" + "time": "2025-05-19T13:19:21+00:00" }, { "name": "mockery/mockery", @@ -9315,16 +7997,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.13.4", + "version": "1.13.3", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + "reference": "faed855a7b5f4d4637717c2b3863e277116beb36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/faed855a7b5f4d4637717c2b3863e277116beb36", + "reference": "faed855a7b5f4d4637717c2b3863e277116beb36", "shasum": "" }, "require": { @@ -9363,7 +8045,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.3" }, "funding": [ { @@ -9371,20 +8053,20 @@ "type": "tidelift" } ], - "time": "2025-08-01T08:46:24+00:00" + "time": "2025-07-05T12:25:42+00:00" }, { "name": "nunomaduro/collision", - "version": "v8.8.3", + "version": "v8.8.2", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4" + "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/1dc9e88d105699d0fee8bb18890f41b274f6b4c4", - "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", "shasum": "" }, "require": { @@ -9406,7 +8088,7 @@ "laravel/sanctum": "^4.1.1", "laravel/tinker": "^2.10.1", "orchestra/testbench-core": "^9.12.0 || ^10.4", - "pestphp/pest": "^3.8.2 || ^4.0.0", + "pestphp/pest": "^3.8.2", "sebastian/environment": "^7.2.1 || ^8.0" }, "type": "library", @@ -9470,45 +8152,42 @@ "type": "patreon" } ], - "time": "2025-11-20T02:55:25+00:00" + "time": "2025-06-25T02:12:12+00:00" }, { "name": "pestphp/pest", - "version": "v4.3.1", + "version": "v3.8.2", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "bc57a84e77afd4544ff9643a6858f68d05aeab96" + "reference": "c6244a8712968dbac88eb998e7ff3b5caa556b0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/bc57a84e77afd4544ff9643a6858f68d05aeab96", - "reference": "bc57a84e77afd4544ff9643a6858f68d05aeab96", + "url": "https://api.github.com/repos/pestphp/pest/zipball/c6244a8712968dbac88eb998e7ff3b5caa556b0d", + "reference": "c6244a8712968dbac88eb998e7ff3b5caa556b0d", "shasum": "" }, "require": { - "brianium/paratest": "^7.16.0", - "nunomaduro/collision": "^8.8.3", - "nunomaduro/termwind": "^2.3.3", - "pestphp/pest-plugin": "^4.0.0", - "pestphp/pest-plugin-arch": "^4.0.0", - "pestphp/pest-plugin-mutate": "^4.0.1", - "pestphp/pest-plugin-profanity": "^4.2.1", - "php": "^8.3.0", - "phpunit/phpunit": "^12.5.4", - "symfony/process": "^7.4.3|^8.0.0" + "brianium/paratest": "^7.8.3", + "nunomaduro/collision": "^8.8.0", + "nunomaduro/termwind": "^2.3.0", + "pestphp/pest-plugin": "^3.0.0", + "pestphp/pest-plugin-arch": "^3.1.0", + "pestphp/pest-plugin-mutate": "^3.0.5", + "php": "^8.2.0", + "phpunit/phpunit": "^11.5.15" }, "conflict": { - "filp/whoops": "<2.18.3", - "phpunit/phpunit": ">12.5.4", - "sebastian/exporter": "<7.0.0", + "filp/whoops": "<2.16.0", + "phpunit/phpunit": ">11.5.15", + "sebastian/exporter": "<6.0.0", "webmozart/assert": "<1.11.0" }, "require-dev": { - "pestphp/pest-dev-tools": "^4.0.0", - "pestphp/pest-plugin-browser": "^4.1.1", - "pestphp/pest-plugin-type-coverage": "^4.0.3", - "psy/psysh": "^0.12.18" + "pestphp/pest-dev-tools": "^3.4.0", + "pestphp/pest-plugin-type-coverage": "^3.5.0", + "symfony/process": "^7.2.5" }, "bin": [ "bin/pest" @@ -9534,7 +8213,6 @@ "Pest\\Plugins\\Snapshot", "Pest\\Plugins\\Verbose", "Pest\\Plugins\\Version", - "Pest\\Plugins\\Shard", "Pest\\Plugins\\Parallel" ] }, @@ -9574,7 +8252,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v4.3.1" + "source": "https://github.com/pestphp/pest/tree/v3.8.2" }, "funding": [ { @@ -9586,34 +8264,34 @@ "type": "github" } ], - "time": "2026-01-04T16:29:59+00:00" + "time": "2025-04-17T10:53:02+00:00" }, { "name": "pestphp/pest-plugin", - "version": "v4.0.0", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/pestphp/pest-plugin.git", - "reference": "9d4b93d7f73d3f9c3189bb22c220fef271cdf568" + "reference": "e79b26c65bc11c41093b10150c1341cc5cdbea83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/9d4b93d7f73d3f9c3189bb22c220fef271cdf568", - "reference": "9d4b93d7f73d3f9c3189bb22c220fef271cdf568", + "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/e79b26c65bc11c41093b10150c1341cc5cdbea83", + "reference": "e79b26c65bc11c41093b10150c1341cc5cdbea83", "shasum": "" }, "require": { "composer-plugin-api": "^2.0.0", "composer-runtime-api": "^2.2.2", - "php": "^8.3" + "php": "^8.2" }, "conflict": { - "pestphp/pest": "<4.0.0" + "pestphp/pest": "<3.0.0" }, "require-dev": { - "composer/composer": "^2.8.10", - "pestphp/pest": "^4.0.0", - "pestphp/pest-dev-tools": "^4.0.0" + "composer/composer": "^2.7.9", + "pestphp/pest": "^3.0.0", + "pestphp/pest-dev-tools": "^3.0.0" }, "type": "composer-plugin", "extra": { @@ -9640,7 +8318,7 @@ "unit" ], "support": { - "source": "https://github.com/pestphp/pest-plugin/tree/v4.0.0" + "source": "https://github.com/pestphp/pest-plugin/tree/v3.0.0" }, "funding": [ { @@ -9656,30 +8334,30 @@ "type": "patreon" } ], - "time": "2025-08-20T12:35:58+00:00" + "time": "2024-09-08T23:21:41+00:00" }, { "name": "pestphp/pest-plugin-arch", - "version": "v4.0.0", + "version": "v3.1.1", "source": { "type": "git", "url": "https://github.com/pestphp/pest-plugin-arch.git", - "reference": "25bb17e37920ccc35cbbcda3b00d596aadf3e58d" + "reference": "db7bd9cb1612b223e16618d85475c6f63b9c8daa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/25bb17e37920ccc35cbbcda3b00d596aadf3e58d", - "reference": "25bb17e37920ccc35cbbcda3b00d596aadf3e58d", + "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/db7bd9cb1612b223e16618d85475c6f63b9c8daa", + "reference": "db7bd9cb1612b223e16618d85475c6f63b9c8daa", "shasum": "" }, "require": { - "pestphp/pest-plugin": "^4.0.0", - "php": "^8.3", - "ta-tikoma/phpunit-architecture-test": "^0.8.5" + "pestphp/pest-plugin": "^3.0.0", + "php": "^8.2", + "ta-tikoma/phpunit-architecture-test": "^0.8.4" }, "require-dev": { - "pestphp/pest": "^4.0.0", - "pestphp/pest-dev-tools": "^4.0.0" + "pestphp/pest": "^3.8.1", + "pestphp/pest-dev-tools": "^3.4.0" }, "type": "library", "extra": { @@ -9714,7 +8392,7 @@ "unit" ], "support": { - "source": "https://github.com/pestphp/pest-plugin-arch/tree/v4.0.0" + "source": "https://github.com/pestphp/pest-plugin-arch/tree/v3.1.1" }, "funding": [ { @@ -9726,30 +8404,30 @@ "type": "github" } ], - "time": "2025-08-20T13:10:51+00:00" + "time": "2025-04-16T22:59:48+00:00" }, { "name": "pestphp/pest-plugin-drift", - "version": "v4.0.0", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/pestphp/pest-plugin-drift.git", - "reference": "f4972f2dc6e6e6f1b47db0a8472ca70ca42b622e" + "reference": "cd506d2b931eb1443b878229b472c59d6f2d8ee8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-drift/zipball/f4972f2dc6e6e6f1b47db0a8472ca70ca42b622e", - "reference": "f4972f2dc6e6e6f1b47db0a8472ca70ca42b622e", + "url": "https://api.github.com/repos/pestphp/pest-plugin-drift/zipball/cd506d2b931eb1443b878229b472c59d6f2d8ee8", + "reference": "cd506d2b931eb1443b878229b472c59d6f2d8ee8", "shasum": "" }, "require": { - "nikic/php-parser": "^5.6.1", - "pestphp/pest": "^4.0.0", - "php": "^8.3.0", - "symfony/finder": "^7.3.2" + "nikic/php-parser": "^5.1.0", + "pestphp/pest": "^3.0.0", + "php": "^8.2.0", + "symfony/finder": "^7.1.4" }, "require-dev": { - "pestphp/pest-dev-tools": "^4.0.0" + "pestphp/pest-dev-tools": "^3.0.0" }, "type": "library", "extra": { @@ -9779,7 +8457,7 @@ "unit" ], "support": { - "source": "https://github.com/pestphp/pest-plugin-drift/tree/v4.0.0" + "source": "https://github.com/pestphp/pest-plugin-drift/tree/v3.0.0" }, "funding": [ { @@ -9795,31 +8473,31 @@ "type": "github" } ], - "time": "2025-08-20T12:54:20+00:00" + "time": "2024-09-08T23:45:48+00:00" }, { "name": "pestphp/pest-plugin-laravel", - "version": "v4.0.0", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/pestphp/pest-plugin-laravel.git", - "reference": "e12a07046b826a40b1c8632fd7b80d6b8d7b628e" + "reference": "6801be82fd92b96e82dd72e563e5674b1ce365fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-laravel/zipball/e12a07046b826a40b1c8632fd7b80d6b8d7b628e", - "reference": "e12a07046b826a40b1c8632fd7b80d6b8d7b628e", + "url": "https://api.github.com/repos/pestphp/pest-plugin-laravel/zipball/6801be82fd92b96e82dd72e563e5674b1ce365fc", + "reference": "6801be82fd92b96e82dd72e563e5674b1ce365fc", "shasum": "" }, "require": { - "laravel/framework": "^11.45.2|^12.25.0", - "pestphp/pest": "^4.0.0", - "php": "^8.3.0" + "laravel/framework": "^11.39.1|^12.9.2", + "pestphp/pest": "^3.8.2", + "php": "^8.2.0" }, "require-dev": { - "laravel/dusk": "^8.3.3", - "orchestra/testbench": "^9.13.0|^10.5.0", - "pestphp/pest-dev-tools": "^4.0.0" + "laravel/dusk": "^8.2.13|dev-develop", + "orchestra/testbench": "^9.9.0|^10.2.1", + "pestphp/pest-dev-tools": "^3.4.0" }, "type": "library", "extra": { @@ -9857,7 +8535,7 @@ "unit" ], "support": { - "source": "https://github.com/pestphp/pest-plugin-laravel/tree/v4.0.0" + "source": "https://github.com/pestphp/pest-plugin-laravel/tree/v3.2.0" }, "funding": [ { @@ -9869,32 +8547,32 @@ "type": "github" } ], - "time": "2025-08-20T12:46:37+00:00" + "time": "2025-04-21T07:40:53+00:00" }, { "name": "pestphp/pest-plugin-mutate", - "version": "v4.0.1", + "version": "v3.0.5", "source": { "type": "git", "url": "https://github.com/pestphp/pest-plugin-mutate.git", - "reference": "d9b32b60b2385e1688a68cc227594738ec26d96c" + "reference": "e10dbdc98c9e2f3890095b4fe2144f63a5717e08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-mutate/zipball/d9b32b60b2385e1688a68cc227594738ec26d96c", - "reference": "d9b32b60b2385e1688a68cc227594738ec26d96c", + "url": "https://api.github.com/repos/pestphp/pest-plugin-mutate/zipball/e10dbdc98c9e2f3890095b4fe2144f63a5717e08", + "reference": "e10dbdc98c9e2f3890095b4fe2144f63a5717e08", "shasum": "" }, "require": { - "nikic/php-parser": "^5.6.1", - "pestphp/pest-plugin": "^4.0.0", - "php": "^8.3", + "nikic/php-parser": "^5.2.0", + "pestphp/pest-plugin": "^3.0.0", + "php": "^8.2", "psr/simple-cache": "^3.0.0" }, "require-dev": { - "pestphp/pest": "^4.0.0", - "pestphp/pest-dev-tools": "^4.0.0", - "pestphp/pest-plugin-type-coverage": "^4.0.0" + "pestphp/pest": "^3.0.8", + "pestphp/pest-dev-tools": "^3.0.0", + "pestphp/pest-plugin-type-coverage": "^3.0.0" }, "type": "library", "autoload": { @@ -9907,10 +8585,6 @@ "MIT" ], "authors": [ - { - "name": "Nuno Maduro", - "email": "enunomaduro@gmail.com" - }, { "name": "Sandro Gehri", "email": "sandrogehri@gmail.com" @@ -9929,7 +8603,7 @@ "unit" ], "support": { - "source": "https://github.com/pestphp/pest-plugin-mutate/tree/v4.0.1" + "source": "https://github.com/pestphp/pest-plugin-mutate/tree/v3.0.5" }, "funding": [ { @@ -9945,63 +8619,7 @@ "type": "github" } ], - "time": "2025-08-21T20:19:25+00:00" - }, - { - "name": "pestphp/pest-plugin-profanity", - "version": "v4.2.1", - "source": { - "type": "git", - "url": "https://github.com/pestphp/pest-plugin-profanity.git", - "reference": "343cfa6f3564b7e35df0ebb77b7fa97039f72b27" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-profanity/zipball/343cfa6f3564b7e35df0ebb77b7fa97039f72b27", - "reference": "343cfa6f3564b7e35df0ebb77b7fa97039f72b27", - "shasum": "" - }, - "require": { - "pestphp/pest-plugin": "^4.0.0", - "php": "^8.3" - }, - "require-dev": { - "faissaloux/pest-plugin-inside": "^1.9", - "pestphp/pest": "^4.0.0", - "pestphp/pest-dev-tools": "^4.0.0" - }, - "type": "library", - "extra": { - "pest": { - "plugins": [ - "Pest\\Profanity\\Plugin" - ] - } - }, - "autoload": { - "psr-4": { - "Pest\\Profanity\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "The Pest Profanity Plugin", - "keywords": [ - "framework", - "pest", - "php", - "plugin", - "profanity", - "test", - "testing", - "unit" - ], - "support": { - "source": "https://github.com/pestphp/pest-plugin-profanity/tree/v4.2.1" - }, - "time": "2025-12-08T00:13:17+00:00" + "time": "2024-09-22T07:54:40+00:00" }, { "name": "phar-io/manifest", @@ -10176,16 +8794,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.6.6", + "version": "5.6.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8" + "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/5cee1d3dfc2d2aa6599834520911d246f656bcb8", - "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/92dde6a5919e34835c506ac8c523ef095a95ed62", + "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62", "shasum": "" }, "require": { @@ -10195,7 +8813,7 @@ "phpdocumentor/reflection-common": "^2.2", "phpdocumentor/type-resolver": "^1.7", "phpstan/phpdoc-parser": "^1.7|^2.0", - "webmozart/assert": "^1.9.1 || ^2" + "webmozart/assert": "^1.9.1" }, "require-dev": { "mockery/mockery": "~1.3.5 || ~1.6.0", @@ -10234,22 +8852,22 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.6" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.2" }, - "time": "2025-12-22T21:13:58+00:00" + "time": "2025-04-13T19:20:35+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.12.0", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195" + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/92a98ada2b93d9b201a613cb5a33584dde25f195", - "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", "shasum": "" }, "require": { @@ -10292,22 +8910,22 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.12.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" }, - "time": "2025-11-21T15:09:14+00:00" + "time": "2024-11-09T15:12:26+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "2.3.1", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374" + "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/16dbf9937da8d4528ceb2145c9c7c0bd29e26374", - "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/b9e61a61e39e02dd90944e9115241c7f7e76bfd8", + "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8", "shasum": "" }, "require": { @@ -10339,17 +8957,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.1" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.2.0" }, - "time": "2026-01-12T11:33:04+00:00" + "time": "2025-07-13T07:04:09+00:00" }, { "name": "phpstan/phpstan", - "version": "2.1.33", + "version": "2.1.17", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053" + }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9e800e6bee7d5bd02784d4c6069b48032d16224f", - "reference": "9e800e6bee7d5bd02784d4c6069b48032d16224f", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053", + "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053", "shasum": "" }, "require": { @@ -10394,38 +9017,39 @@ "type": "github" } ], - "time": "2025-12-05T10:24:31+00:00" + "time": "2025-05-21T20:55:28+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "12.5.2", + "version": "11.0.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "4a9739b51cbcb355f6e95659612f92e282a7077b" + "reference": "1a800a7446add2d79cc6b3c01c45381810367d76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4a9739b51cbcb355f6e95659612f92e282a7077b", - "reference": "4a9739b51cbcb355f6e95659612f92e282a7077b", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1a800a7446add2d79cc6b3c01c45381810367d76", + "reference": "1a800a7446add2d79cc6b3c01c45381810367d76", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^5.7.0", - "php": ">=8.3", - "phpunit/php-file-iterator": "^6.0", - "phpunit/php-text-template": "^5.0", - "sebastian/complexity": "^5.0", - "sebastian/environment": "^8.0.3", - "sebastian/lines-of-code": "^4.0", - "sebastian/version": "^6.0", - "theseer/tokenizer": "^2.0.1" + "nikic/php-parser": "^5.4.0", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.0", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^12.5.1" + "phpunit/phpunit": "^11.5.2" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -10434,7 +9058,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "12.5.x-dev" + "dev-main": "11.0.x-dev" } }, "autoload": { @@ -10463,7 +9087,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.2" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/show" }, "funding": [ { @@ -10483,32 +9107,32 @@ "type": "tidelift" } ], - "time": "2025-12-24T07:03:04+00:00" + "time": "2025-06-18T08:56:18+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "6.0.0", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "961bc913d42fe24a257bfff826a5068079ac7782" + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/961bc913d42fe24a257bfff826a5068079ac7782", - "reference": "961bc913d42fe24a257bfff826a5068079ac7782", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", "shasum": "" }, "require": { - "php": ">=8.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -10536,7 +9160,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/6.0.0" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" }, "funding": [ { @@ -10544,28 +9168,28 @@ "type": "github" } ], - "time": "2025-02-07T04:58:37+00:00" + "time": "2024-08-27T05:02:59+00:00" }, { "name": "phpunit/php-invoker", - "version": "6.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406" + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/12b54e689b07a25a9b41e57736dfab6ec9ae5406", - "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", "shasum": "" }, "require": { - "php": ">=8.3" + "php": ">=8.2" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.0" }, "suggest": { "ext-pcntl": "*" @@ -10573,7 +9197,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -10600,7 +9224,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/6.0.0" + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" }, "funding": [ { @@ -10608,32 +9232,32 @@ "type": "github" } ], - "time": "2025-02-07T04:58:58+00:00" + "time": "2024-07-03T05:07:44+00:00" }, { "name": "phpunit/php-text-template", - "version": "5.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53" + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/e1367a453f0eda562eedb4f659e13aa900d66c53", - "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", "shasum": "" }, "require": { - "php": ">=8.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -10660,7 +9284,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/5.0.0" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" }, "funding": [ { @@ -10668,32 +9292,32 @@ "type": "github" } ], - "time": "2025-02-07T04:59:16+00:00" + "time": "2024-07-03T05:08:43+00:00" }, { "name": "phpunit/php-timer", - "version": "8.0.0", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc" + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", - "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", "shasum": "" }, "require": { - "php": ">=8.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "8.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -10720,7 +9344,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", "security": "https://github.com/sebastianbergmann/php-timer/security/policy", - "source": "https://github.com/sebastianbergmann/php-timer/tree/8.0.0" + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" }, "funding": [ { @@ -10728,20 +9352,20 @@ "type": "github" } ], - "time": "2025-02-07T04:59:38+00:00" + "time": "2024-07-03T05:09:35+00:00" }, { "name": "phpunit/phpunit", - "version": "12.5.4", + "version": "11.5.15", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "4ba0e923f9d3fc655de22f9547c01d15a41fc93a" + "reference": "4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4ba0e923f9d3fc655de22f9547c01d15a41fc93a", - "reference": "4ba0e923f9d3fc655de22f9547c01d15a41fc93a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c", + "reference": "4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c", "shasum": "" }, "require": { @@ -10751,33 +9375,37 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.4", + "myclabs/deep-copy": "^1.13.0", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", - "php": ">=8.3", - "phpunit/php-code-coverage": "^12.5.1", - "phpunit/php-file-iterator": "^6.0.0", - "phpunit/php-invoker": "^6.0.0", - "phpunit/php-text-template": "^5.0.0", - "phpunit/php-timer": "^8.0.0", - "sebastian/cli-parser": "^4.2.0", - "sebastian/comparator": "^7.1.3", - "sebastian/diff": "^7.0.0", - "sebastian/environment": "^8.0.3", - "sebastian/exporter": "^7.0.2", - "sebastian/global-state": "^8.0.2", - "sebastian/object-enumerator": "^7.0.0", - "sebastian/type": "^6.0.3", - "sebastian/version": "^6.0.0", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.9", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.3", + "sebastian/comparator": "^6.3.1", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.0", + "sebastian/exporter": "^6.3.0", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.2", + "sebastian/version": "^5.0.2", "staabm/side-effects-detector": "^1.0.5" }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, "bin": [ "phpunit" ], "type": "library", "extra": { "branch-alias": { - "dev-main": "12.5-dev" + "dev-main": "11.5-dev" } }, "autoload": { @@ -10809,7 +9437,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.4" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.15" }, "funding": [ { @@ -10820,105 +9448,37 @@ "url": "https://github.com/sebastianbergmann", "type": "github" }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, { "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", "type": "tidelift" } ], - "time": "2025-12-15T06:05:34+00:00" - }, - { - "name": "rector/rector", - "version": "2.3.1", - "source": { - "type": "git", - "url": "https://github.com/rectorphp/rector.git", - "reference": "9afc1bb43571b25629f353c61a9315b5ef31383a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/9afc1bb43571b25629f353c61a9315b5ef31383a", - "reference": "9afc1bb43571b25629f353c61a9315b5ef31383a", - "shasum": "" - }, - "require": { - "php": "^7.4|^8.0", - "phpstan/phpstan": "^2.1.33" - }, - "conflict": { - "rector/rector-doctrine": "*", - "rector/rector-downgrade-php": "*", - "rector/rector-phpunit": "*", - "rector/rector-symfony": "*" - }, - "suggest": { - "ext-dom": "To manipulate phpunit.xml via the custom-rule command" - }, - "bin": [ - "bin/rector" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Instant Upgrade and Automated Refactoring of any PHP code", - "homepage": "https://getrector.com/", - "keywords": [ - "automation", - "dev", - "migration", - "refactoring" - ], - "support": { - "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.3.1" - }, - "funding": [ - { - "url": "https://github.com/tomasvotruba", - "type": "github" - } - ], - "time": "2026-01-13T15:13:58+00:00" + "time": "2025-03-23T16:02:11+00:00" }, { "name": "sebastian/cli-parser", - "version": "4.2.0", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04" + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/90f41072d220e5c40df6e8635f5dafba2d9d4d04", - "reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", "shasum": "" }, "require": { - "php": ">=8.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.2-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -10942,51 +9502,152 @@ "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/4.2.0" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/cli-parser", - "type": "tidelift" } ], - "time": "2025-09-14T09:36:45+00:00" + "time": "2024-07-03T04:41:36+00:00" }, { - "name": "sebastian/comparator", - "version": "7.1.3", + "name": "sebastian/code-unit", + "version": "3.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "dc904b4bb3ab070865fa4068cd84f3da8b945148" + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/dc904b4bb3ab070865fa4068cd84f3da8b945148", - "reference": "dc904b4bb3ab070865fa4068cd84f3da8b945148", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-19T07:56:08+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:45:54+00:00" + }, + { + "name": "sebastian/comparator", + "version": "6.3.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/24b8fbc2c8e201bb1308e7b05148d6ab393b6959", + "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959", "shasum": "" }, "require": { "ext-dom": "*", "ext-mbstring": "*", - "php": ">=8.3", - "sebastian/diff": "^7.0", - "sebastian/exporter": "^7.0" + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^12.2" + "phpunit/phpunit": "^11.4" }, "suggest": { "ext-bcmath": "For comparing BcMath\\Number objects" @@ -10994,7 +9655,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "7.1-dev" + "dev-main": "6.3-dev" } }, "autoload": { @@ -11034,53 +9695,41 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.3" + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", - "type": "tidelift" } ], - "time": "2025-08-20T11:27:00+00:00" + "time": "2025-03-07T06:57:01+00:00" }, { "name": "sebastian/complexity", - "version": "5.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb" + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/bad4316aba5303d0221f43f8cee37eb58d384bbb", - "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", "shasum": "" }, "require": { "nikic/php-parser": "^5.0", - "php": ">=8.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -11104,7 +9753,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/5.0.0" + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" }, "funding": [ { @@ -11112,33 +9761,33 @@ "type": "github" } ], - "time": "2025-02-07T04:55:25+00:00" + "time": "2024-07-03T04:49:50+00:00" }, { "name": "sebastian/diff", - "version": "7.0.0", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7ab1ea946c012266ca32390913653d844ecd085f" + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f", - "reference": "7ab1ea946c012266ca32390913653d844ecd085f", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", "shasum": "" }, "require": { - "php": ">=8.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^12.0", - "symfony/process": "^7.2" + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "7.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -11171,7 +9820,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/7.0.0" + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" }, "funding": [ { @@ -11179,27 +9828,27 @@ "type": "github" } ], - "time": "2025-02-07T04:55:46+00:00" + "time": "2024-07-03T04:53:05+00:00" }, { "name": "sebastian/environment", - "version": "8.0.3", + "version": "7.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68" + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/24a711b5c916efc6d6e62aa65aa2ec98fef77f68", - "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4", "shasum": "" }, "require": { - "php": ">=8.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.3" }, "suggest": { "ext-posix": "*" @@ -11207,7 +9856,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "8.0-dev" + "dev-main": "7.2-dev" } }, "autoload": { @@ -11235,7 +9884,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/8.0.3" + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1" }, "funding": [ { @@ -11255,34 +9904,34 @@ "type": "tidelift" } ], - "time": "2025-08-12T14:11:56+00:00" + "time": "2025-05-21T11:55:47+00:00" }, { "name": "sebastian/exporter", - "version": "7.0.2", + "version": "6.3.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "016951ae10980765e4e7aee491eb288c64e505b7" + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/016951ae10980765e4e7aee491eb288c64e505b7", - "reference": "016951ae10980765e4e7aee491eb288c64e505b7", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", "shasum": "" }, "require": { "ext-mbstring": "*", - "php": ">=8.3", - "sebastian/recursion-context": "^7.0" + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "7.0-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -11325,55 +9974,43 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/7.0.2" + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", - "type": "tidelift" } ], - "time": "2025-09-24T06:16:11+00:00" + "time": "2024-12-05T09:17:50+00:00" }, { "name": "sebastian/global-state", - "version": "8.0.2", + "version": "7.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "ef1377171613d09edd25b7816f05be8313f9115d" + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/ef1377171613d09edd25b7816f05be8313f9115d", - "reference": "ef1377171613d09edd25b7816f05be8313f9115d", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", "shasum": "" }, "require": { - "php": ">=8.3", - "sebastian/object-reflector": "^5.0", - "sebastian/recursion-context": "^7.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "8.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -11399,53 +10036,41 @@ "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.2" + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", - "type": "tidelift" } ], - "time": "2025-08-29T11:29:25+00:00" + "time": "2024-07-03T04:57:36+00:00" }, { "name": "sebastian/lines-of-code", - "version": "4.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f" + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/97ffee3bcfb5805568d6af7f0f893678fc076d2f", - "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", "shasum": "" }, "require": { "nikic/php-parser": "^5.0", - "php": ">=8.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -11469,7 +10094,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/4.0.0" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" }, "funding": [ { @@ -11477,34 +10102,34 @@ "type": "github" } ], - "time": "2025-02-07T04:57:28+00:00" + "time": "2024-07-03T04:58:38+00:00" }, { "name": "sebastian/object-enumerator", - "version": "7.0.0", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894" + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1effe8e9b8e068e9ae228e542d5d11b5d16db894", - "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", "shasum": "" }, "require": { - "php": ">=8.3", - "sebastian/object-reflector": "^5.0", - "sebastian/recursion-context": "^7.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "7.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -11527,7 +10152,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/7.0.0" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" }, "funding": [ { @@ -11535,32 +10160,32 @@ "type": "github" } ], - "time": "2025-02-07T04:57:48+00:00" + "time": "2024-07-03T05:00:13+00:00" }, { "name": "sebastian/object-reflector", - "version": "5.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "4bfa827c969c98be1e527abd576533293c634f6a" + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/4bfa827c969c98be1e527abd576533293c634f6a", - "reference": "4bfa827c969c98be1e527abd576533293c634f6a", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", "shasum": "" }, "require": { - "php": ">=8.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -11583,7 +10208,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/5.0.0" + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" }, "funding": [ { @@ -11591,32 +10216,32 @@ "type": "github" } ], - "time": "2025-02-07T04:58:17+00:00" + "time": "2024-07-03T05:01:32+00:00" }, { "name": "sebastian/recursion-context", - "version": "7.0.1", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c" + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/0b01998a7d5b1f122911a66bebcb8d46f0c82d8c", - "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", "shasum": "" }, "require": { - "php": ">=8.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "7.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -11647,52 +10272,40 @@ "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/7.0.1" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", - "type": "tidelift" } ], - "time": "2025-08-13T04:44:59+00:00" + "time": "2024-07-03T05:10:34+00:00" }, { "name": "sebastian/type", - "version": "6.0.3", + "version": "5.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d" + "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/e549163b9760b8f71f191651d22acf32d56d6d4d", - "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", + "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", "shasum": "" }, "require": { - "php": ">=8.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -11716,49 +10329,37 @@ "support": { "issues": "https://github.com/sebastianbergmann/type/issues", "security": "https://github.com/sebastianbergmann/type/security/policy", - "source": "https://github.com/sebastianbergmann/type/tree/6.0.3" + "source": "https://github.com/sebastianbergmann/type/tree/5.1.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/type", - "type": "tidelift" } ], - "time": "2025-08-09T06:57:12+00:00" + "time": "2025-03-18T13:35:50+00:00" }, { "name": "sebastian/version", - "version": "6.0.0", + "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c" + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/3e6ccf7657d4f0a59200564b08cead899313b53c", - "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", "shasum": "" }, "require": { - "php": ">=8.3" + "php": ">=8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -11782,7 +10383,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/version/issues", "security": "https://github.com/sebastianbergmann/version/security/policy", - "source": "https://github.com/sebastianbergmann/version/tree/6.0.0" + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" }, "funding": [ { @@ -11790,7 +10391,72 @@ "type": "github" } ], - "time": "2025-02-07T05:00:38+00:00" + "time": "2024-10-09T05:16:32+00:00" + }, + { + "name": "spatie/pest-expectations", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/pest-expectations.git", + "reference": "6ec6e5184c70fe7113e4237d40ad4f8387ce1be2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/pest-expectations/zipball/6ec6e5184c70fe7113e4237d40ad4f8387ce1be2", + "reference": "6ec6e5184c70fe7113e4237d40ad4f8387ce1be2", + "shasum": "" + }, + "require": { + "illuminate/database": "^10.7|^11.0|^12.0", + "php": "^8.2" + }, + "require-dev": { + "illuminate/contracts": "^10.0|^11.0|^12.0", + "laravel/pint": "^1.2", + "orchestra/testbench": "^8.3|^9.0|^10.0", + "pestphp/pest": "^3.0", + "spatie/laravel-json-api-paginate": "^1.14", + "spatie/ray": "^1.28" + }, + "type": "library", + "autoload": { + "files": [ + "src/PestExpectations.php", + "src/Helpers.php" + ], + "psr-4": { + "Spatie\\PestExpectations\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "role": "Developer" + } + ], + "description": "A collection of handy custom Pest customisations", + "homepage": "https://github.com/spatie/pest-expectations", + "keywords": [ + "pest-expectations", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/pest-expectations/issues", + "source": "https://github.com/spatie/pest-expectations/tree/1.11.0" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-04-13T12:30:30+00:00" }, { "name": "staabm/side-effects-detector", @@ -11844,6 +10510,78 @@ ], "time": "2024-10-20T05:08:20+00:00" }, + { + "name": "symfony/yaml", + "version": "v7.3.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "0c3555045a46ab3cd4cc5a69d161225195230edb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/0c3555045a46ab3cd4cc5a69d161225195230edb", + "reference": "0c3555045a46ab3cd4cc5a69d161225195230edb", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v7.3.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-03T06:57:57+00:00" + }, { "name": "ta-tikoma/phpunit-architecture-test", "version": "0.8.5", @@ -11905,23 +10643,23 @@ }, { "name": "theseer/tokenizer", - "version": "2.0.1", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4" + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/7989e43bf381af0eac72e4f0ca5bcbfa81658be4", - "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { "ext-dom": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": "^8.1" + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { @@ -11943,7 +10681,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/2.0.1" + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" }, "funding": [ { @@ -11951,69 +10689,7 @@ "type": "github" } ], - "time": "2025-12-08T11:19:18+00:00" - }, - { - "name": "webmozart/assert", - "version": "2.1.2", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "ce6a2f100c404b2d32a1dd1270f9b59ad4f57649" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/ce6a2f100c404b2d32a1dd1270f9b59ad4f57649", - "reference": "ce6a2f100c404b2d32a1dd1270f9b59ad4f57649", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-date": "*", - "ext-filter": "*", - "php": "^8.2" - }, - "suggest": { - "ext-intl": "", - "ext-simplexml": "", - "ext-spl": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-feature/2-0": "2.0-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - }, - { - "name": "Woody Gilk", - "email": "woody.gilk@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/2.1.2" - }, - "time": "2026-01-13T14:02:24+00:00" + "time": "2024-03-03T12:36:25+00:00" } ], "aliases": [], @@ -12023,10 +10699,8 @@ "prefer-lowest": false, "platform": { "php": "^8.2", - "ext-imagick": "*", - "ext-simplexml": "*", - "ext-zip": "*" + "ext-imagick": "*" }, "platform-dev": {}, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.6.0" } diff --git a/config/app.php b/config/app.php index c7cb051..8282215 100644 --- a/config/app.php +++ b/config/app.php @@ -130,8 +130,7 @@ return [ 'force_https' => env('FORCE_HTTPS', false), 'puppeteer_docker' => env('PUPPETEER_DOCKER', false), 'puppeteer_mode' => env('PUPPETEER_MODE', 'local'), - 'puppeteer_wait_for_network_idle' => env('PUPPETEER_WAIT_FOR_NETWORK_IDLE', true), - 'puppeteer_window_size_strategy' => env('PUPPETEER_WINDOW_SIZE_STRATEGY', null), + 'puppeteer_wait_for_network_idle' => env('PUPPETEER_WAIT_FOR_NETWORK_IDLE', false), 'notifications' => [ 'battery_low' => [ @@ -152,5 +151,4 @@ return [ 'version' => env('APP_VERSION', null), - 'catalog_url' => env('CATALOG_URL', 'https://raw.githubusercontent.com/bnussbau/trmnl-recipe-catalog/refs/heads/main/catalog.yaml'), ]; diff --git a/config/auth.php b/config/auth.php index 7d1eb0d..0ba5d5d 100644 --- a/config/auth.php +++ b/config/auth.php @@ -104,7 +104,7 @@ return [ | Password Confirmation Timeout |-------------------------------------------------------------------------- | - | Here you may define the number of seconds before a password confirmation + | Here you may define the amount of seconds before a password confirmation | window expires and users are asked to re-enter their password via the | confirmation screen. By default, the timeout lasts for three hours. | diff --git a/config/cache.php b/config/cache.php index b32aead..925f7d2 100644 --- a/config/cache.php +++ b/config/cache.php @@ -27,8 +27,7 @@ return [ | same cache driver to group types of items stored in your caches. | | Supported drivers: "array", "database", "file", "memcached", - | "redis", "dynamodb", "octane", - | "failover", "null" + | "redis", "dynamodb", "octane", "null" | */ @@ -91,14 +90,6 @@ return [ 'driver' => 'octane', ], - 'failover' => [ - 'driver' => 'failover', - 'stores' => [ - 'database', - 'array', - ], - ], - ], /* @@ -112,6 +103,6 @@ return [ | */ - 'prefix' => env('CACHE_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-cache-'), + 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'), ]; diff --git a/config/database.php b/config/database.php index 4da9dc6..8910562 100644 --- a/config/database.php +++ b/config/database.php @@ -40,7 +40,6 @@ return [ 'busy_timeout' => null, 'journal_mode' => null, 'synchronous' => null, - 'transaction_mode' => 'DEFERRED', ], 'mysql' => [ @@ -59,7 +58,7 @@ return [ 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ - (PHP_VERSION_ID >= 80500 ? Pdo\Mysql::ATTR_SSL_CA : PDO::MYSQL_ATTR_SSL_CA) => env('MYSQL_ATTR_SSL_CA'), + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], @@ -79,7 +78,7 @@ return [ 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ - (PHP_VERSION_ID >= 80500 ? Pdo\Mysql::ATTR_SSL_CA : PDO::MYSQL_ATTR_SSL_CA) => env('MYSQL_ATTR_SSL_CA'), + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], @@ -95,7 +94,7 @@ return [ 'prefix' => '', 'prefix_indexes' => true, 'search_path' => 'public', - 'sslmode' => env('DB_SSLMODE', 'prefer'), + 'sslmode' => 'prefer', ], 'sqlsrv' => [ @@ -148,7 +147,7 @@ return [ 'options' => [ 'cluster' => env('REDIS_CLUSTER', 'redis'), - 'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-database-'), + 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), 'persistent' => env('REDIS_PERSISTENT', false), ], @@ -159,10 +158,6 @@ return [ 'password' => env('REDIS_PASSWORD'), 'port' => env('REDIS_PORT', '6379'), 'database' => env('REDIS_DB', '0'), - 'max_retries' => env('REDIS_MAX_RETRIES', 3), - 'backoff_algorithm' => env('REDIS_BACKOFF_ALGORITHM', 'decorrelated_jitter'), - 'backoff_base' => env('REDIS_BACKOFF_BASE', 100), - 'backoff_cap' => env('REDIS_BACKOFF_CAP', 1000), ], 'cache' => [ @@ -172,10 +167,6 @@ return [ 'password' => env('REDIS_PASSWORD'), 'port' => env('REDIS_PORT', '6379'), 'database' => env('REDIS_CACHE_DB', '1'), - 'max_retries' => env('REDIS_MAX_RETRIES', 3), - 'backoff_algorithm' => env('REDIS_BACKOFF_ALGORITHM', 'decorrelated_jitter'), - 'backoff_base' => env('REDIS_BACKOFF_BASE', 100), - 'backoff_cap' => env('REDIS_BACKOFF_CAP', 1000), ], ], diff --git a/config/filesystems.php b/config/filesystems.php index ccaf2a9..b564035 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -35,16 +35,14 @@ return [ 'root' => storage_path('app/private'), 'serve' => true, 'throw' => false, - 'report' => false, ], 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), - 'url' => mb_rtrim(env('APP_URL'), '/').'/storage', + 'url' => env('APP_URL').'/storage', 'visibility' => 'public', 'throw' => false, - 'report' => false, ], 's3' => [ @@ -57,7 +55,6 @@ return [ 'endpoint' => env('AWS_ENDPOINT'), 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), 'throw' => false, - 'report' => false, ], ], diff --git a/config/fortify.php b/config/fortify.php deleted file mode 100644 index ed7b0c0..0000000 --- a/config/fortify.php +++ /dev/null @@ -1,159 +0,0 @@ - 'web', - - /* - |-------------------------------------------------------------------------- - | Fortify Password Broker - |-------------------------------------------------------------------------- - | - | Here you may specify which password broker Fortify can use when a user - | is resetting their password. This configured value should match one - | of your password brokers setup in your "auth" configuration file. - | - */ - - 'passwords' => 'users', - - /* - |-------------------------------------------------------------------------- - | Username / Email - |-------------------------------------------------------------------------- - | - | This value defines which model attribute should be considered as your - | application's "username" field. Typically, this might be the email - | address of the users but you are free to change this value here. - | - | Out of the box, Fortify expects forgot password and reset password - | requests to have a field named 'email'. If the application uses - | another name for the field you may define it below as needed. - | - */ - - 'username' => 'email', - - 'email' => 'email', - - /* - |-------------------------------------------------------------------------- - | Lowercase Usernames - |-------------------------------------------------------------------------- - | - | This value defines whether usernames should be lowercased before saving - | them in the database, as some database system string fields are case - | sensitive. You may disable this for your application if necessary. - | - */ - - 'lowercase_usernames' => true, - - /* - |-------------------------------------------------------------------------- - | Home Path - |-------------------------------------------------------------------------- - | - | Here you may configure the path where users will get redirected during - | authentication or password reset when the operations are successful - | and the user is authenticated. You are free to change this value. - | - */ - - 'home' => '/dashboard', - - /* - |-------------------------------------------------------------------------- - | Fortify Routes Prefix / Subdomain - |-------------------------------------------------------------------------- - | - | Here you may specify which prefix Fortify will assign to all the routes - | that it registers with the application. If necessary, you may change - | subdomain under which all of the Fortify routes will be available. - | - */ - - 'prefix' => '', - - 'domain' => null, - - /* - |-------------------------------------------------------------------------- - | Fortify Routes Middleware - |-------------------------------------------------------------------------- - | - | Here you may specify which middleware Fortify will assign to the routes - | that it registers with the application. If necessary, you may change - | these middleware but typically this provided default is preferred. - | - */ - - 'middleware' => ['web'], - - /* - |-------------------------------------------------------------------------- - | Rate Limiting - |-------------------------------------------------------------------------- - | - | By default, Fortify will throttle logins to five requests per minute for - | every email and IP address combination. However, if you would like to - | specify a custom rate limiter to call then you may specify it here. - | - */ - - 'limiters' => [ - 'login' => 'login', - 'two-factor' => 'two-factor', - ], - - /* - |-------------------------------------------------------------------------- - | Register View Routes - |-------------------------------------------------------------------------- - | - | Here you may specify if the routes returning views should be disabled as - | you may not need them when building your own application. This may be - | especially true if you're writing a custom single-page application. - | - */ - - 'views' => true, - - /* - |-------------------------------------------------------------------------- - | Features - |-------------------------------------------------------------------------- - | - | Some of the Fortify features are optional. You may disable the features - | by removing them from this array. You're free to only remove some of - | these features or you can even remove all of these if you need to. - | - */ - - 'features' => [ - config('app.registration.enabled') && Features::registration(), - Features::resetPasswords(), - Features::emailVerification(), - // Features::updateProfileInformation(), - // Features::updatePasswords(), - Features::twoFactorAuthentication([ - 'confirm' => true, - 'confirmPassword' => true, - // 'window' => 0, - ]), - ], - -]; diff --git a/config/livewire.php b/config/livewire.php deleted file mode 100644 index 4c68f45..0000000 --- a/config/livewire.php +++ /dev/null @@ -1,277 +0,0 @@ - [ - resource_path('views/components'), - resource_path('views/livewire'), - ], - - /* - |--------------------------------------------------------------------------- - | Component Namespaces - |--------------------------------------------------------------------------- - | - | This value sets default namespaces that will be used to resolve view-based - | components like single-file and multi-file components. These folders'll - | also be referenced when creating new components via the make command. - | - */ - - 'component_namespaces' => [ - 'layouts' => resource_path('views/layouts'), - 'pages' => resource_path('views/pages'), - ], - - /* - |--------------------------------------------------------------------------- - | Page Layout - |--------------------------------------------------------------------------- - | The view that will be used as the layout when rendering a single component as - | an entire page via `Route::livewire('/post/create', 'pages::create-post')`. - | In this case, the content of pages::create-post will render into $slot. - | - */ - - 'component_layout' => 'layouts::app', - - /* - |--------------------------------------------------------------------------- - | Lazy Loading Placeholder - |--------------------------------------------------------------------------- - | Livewire allows you to lazy load components that would otherwise slow down - | the initial page load. Every component can have a custom placeholder or - | you can define the default placeholder view for all components below. - | - */ - - 'component_placeholder' => null, // Example: 'placeholders::skeleton' - - /* - |--------------------------------------------------------------------------- - | Make Command - |--------------------------------------------------------------------------- - | This value determines the default configuration for the artisan make command - | You can configure the component type (sfc, mfc, class) and whether to use - | the high-voltage (⚑) emoji as a prefix in the sfc|mfc component names. - | - */ - - 'make_command' => [ - 'type' => 'sfc', // Options: 'sfc', 'mfc', 'class' - 'emoji' => false, // Options: true, false - ], - - /* - |--------------------------------------------------------------------------- - | Class Namespace - |--------------------------------------------------------------------------- - | - | This value sets the root class namespace for Livewire component classes in - | your application. This value will change where component auto-discovery - | finds components. It's also referenced by the file creation commands. - | - */ - - 'class_namespace' => 'App\\Livewire', - - /* - |--------------------------------------------------------------------------- - | Class Path - |--------------------------------------------------------------------------- - | - | This value is used to specify the path where Livewire component class files - | are created when running creation commands like `artisan make:livewire`. - | This path is customizable to match your projects directory structure. - | - */ - - 'class_path' => app_path('Livewire'), - - /* - |--------------------------------------------------------------------------- - | View Path - |--------------------------------------------------------------------------- - | - | This value is used to specify where Livewire component Blade templates are - | stored when running file creation commands like `artisan make:livewire`. - | It is also used if you choose to omit a component's render() method. - | - */ - - 'view_path' => resource_path('views/livewire'), - - /* - |--------------------------------------------------------------------------- - | Temporary File Uploads - |--------------------------------------------------------------------------- - | - | Livewire handles file uploads by storing uploads in a temporary directory - | before the file is stored permanently. All file uploads are directed to - | a global endpoint for temporary storage. You may configure this below: - | - */ - - 'temporary_file_upload' => [ - 'disk' => env('LIVEWIRE_TEMPORARY_FILE_UPLOAD_DISK'), // Example: 'local', 's3' | Default: 'default' - 'rules' => null, // Example: ['file', 'mimes:png,jpg'] | Default: ['required', 'file', 'max:12288'] (12MB) - 'directory' => null, // Example: 'tmp' | Default: 'livewire-tmp' - 'middleware' => null, // Example: 'throttle:5,1' | Default: 'throttle:60,1' - 'preview_mimes' => [ // Supported file types for temporary pre-signed file URLs... - 'png', 'gif', 'bmp', 'svg', 'wav', 'mp4', - 'mov', 'avi', 'wmv', 'mp3', 'm4a', - 'jpg', 'jpeg', 'mpga', 'webp', 'wma', - ], - 'max_upload_time' => 5, // Max duration (in minutes) before an upload is invalidated... - 'cleanup' => true, // Should cleanup temporary uploads older than 24 hrs... - ], - - /* - |--------------------------------------------------------------------------- - | Render On Redirect - |--------------------------------------------------------------------------- - | - | This value determines if Livewire will run a component's `render()` method - | after a redirect has been triggered using something like `redirect(...)` - | Setting this to true will render the view once more before redirecting - | - */ - - 'render_on_redirect' => false, - - /* - |--------------------------------------------------------------------------- - | Eloquent Model Binding - |--------------------------------------------------------------------------- - | - | Previous versions of Livewire supported binding directly to eloquent model - | properties using wire:model by default. However, this behavior has been - | deemed too "magical" and has therefore been put under a feature flag. - | - */ - - 'legacy_model_binding' => false, - - /* - |--------------------------------------------------------------------------- - | Auto-inject Frontend Assets - |--------------------------------------------------------------------------- - | - | By default, Livewire automatically injects its JavaScript and CSS into the - | and of pages containing Livewire components. By disabling - | this behavior, you need to use @livewireStyles and @livewireScripts. - | - */ - - 'inject_assets' => true, - - /* - |--------------------------------------------------------------------------- - | Navigate (SPA mode) - |--------------------------------------------------------------------------- - | - | By adding `wire:navigate` to links in your Livewire application, Livewire - | will prevent the default link handling and instead request those pages - | via AJAX, creating an SPA-like effect. Configure this behavior here. - | - */ - - 'navigate' => [ - 'show_progress_bar' => true, - 'progress_bar_color' => '#E05B45', - ], - - /* - |--------------------------------------------------------------------------- - | HTML Morph Markers - |--------------------------------------------------------------------------- - | - | Livewire intelligently "morphs" existing HTML into the newly rendered HTML - | after each update. To make this process more reliable, Livewire injects - | "markers" into the rendered Blade surrounding @if, @class & @foreach. - | - */ - - 'inject_morph_markers' => true, - - /* - |--------------------------------------------------------------------------- - | Smart Wire Keys - |--------------------------------------------------------------------------- - | - | Livewire uses loops and keys used within loops to generate smart keys that - | are applied to nested components that don't have them. This makes using - | nested components more reliable by ensuring that they all have keys. - | - */ - - 'smart_wire_keys' => true, - - /* - |--------------------------------------------------------------------------- - | Pagination Theme - |--------------------------------------------------------------------------- - | - | When enabling Livewire's pagination feature by using the `WithPagination` - | trait, Livewire will use Tailwind templates to render pagination views - | on the page. If you want Bootstrap CSS, you can specify: "bootstrap" - | - */ - - 'pagination_theme' => 'tailwind', - - /* - |--------------------------------------------------------------------------- - | Release Token - |--------------------------------------------------------------------------- - | - | This token is stored client-side and sent along with each request to check - | a users session to see if a new release has invalidated it. If there is - | a mismatch it will throw an error and prompt for a browser refresh. - | - */ - - 'release_token' => 'a', - - /* - |--------------------------------------------------------------------------- - | CSP Safe - |--------------------------------------------------------------------------- - | - | This config is used to determine if Livewire will use the CSP-safe version - | of Alpine in its bundle. This is useful for applications that are using - | strict Content Security Policy (CSP) to protect against XSS attacks. - | - */ - - 'csp_safe' => false, - - /* - |--------------------------------------------------------------------------- - | Payload Guards - |--------------------------------------------------------------------------- - | - | These settings protect against malicious or oversized payloads that could - | cause denial of service. The default values should feel reasonable for - | most web applications. Each can be set to null to disable the limit. - | - */ - - 'payload' => [ - 'max_size' => 1024 * 1024, // 1MB - maximum request payload size in bytes - 'max_nesting_depth' => 10, // Maximum depth of dot-notation property paths - 'max_calls' => 50, // Maximum method calls per request - 'max_components' => 20, // Maximum components per batch request - ], -]; diff --git a/config/logging.php b/config/logging.php index 9f6e543..47b1d08 100644 --- a/config/logging.php +++ b/config/logging.php @@ -54,7 +54,7 @@ return [ 'stack' => [ 'driver' => 'stack', - 'channels' => explode(',', (string) env('LOG_STACK', 'single')), + 'channels' => explode(',', env('LOG_STACK', 'single')), 'ignore_exceptions' => false, ], @@ -98,10 +98,10 @@ return [ 'driver' => 'monolog', 'level' => env('LOG_LEVEL', 'debug'), 'handler' => StreamHandler::class, - 'handler_with' => [ + 'formatter' => env('LOG_STDOUT_FORMATTER'), + 'with' => [ 'stream' => 'php://stdout', ], - 'formatter' => env('LOG_STDOUT_FORMATTER'), 'processors' => [PsrLogMessageProcessor::class], ], @@ -109,10 +109,10 @@ return [ 'driver' => 'monolog', 'level' => env('LOG_LEVEL', 'debug'), 'handler' => StreamHandler::class, - 'handler_with' => [ + 'formatter' => env('LOG_STDERR_FORMATTER'), + 'with' => [ 'stream' => 'php://stderr', ], - 'formatter' => env('LOG_STDERR_FORMATTER'), 'processors' => [PsrLogMessageProcessor::class], ], diff --git a/config/mail.php b/config/mail.php index 522b284..756305b 100644 --- a/config/mail.php +++ b/config/mail.php @@ -46,7 +46,7 @@ return [ 'username' => env('MAIL_USERNAME'), 'password' => env('MAIL_PASSWORD'), 'timeout' => null, - 'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url((string) env('APP_URL', 'http://localhost'), PHP_URL_HOST)), + 'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST)), ], 'ses' => [ @@ -85,7 +85,6 @@ return [ 'smtp', 'log', ], - 'retry_after' => 60, ], 'roundrobin' => [ @@ -94,7 +93,6 @@ return [ 'ses', 'postmark', ], - 'retry_after' => 60, ], ], diff --git a/config/queue.php b/config/queue.php index 79c2c0a..116bd8d 100644 --- a/config/queue.php +++ b/config/queue.php @@ -24,8 +24,7 @@ return [ | used by your application. An example configuration is provided for | each backend supported by Laravel. You're also free to add more. | - | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", - | "deferred", "background", "failover", "null" + | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" | */ @@ -73,22 +72,6 @@ return [ 'after_commit' => false, ], - 'deferred' => [ - 'driver' => 'deferred', - ], - - 'background' => [ - 'driver' => 'background', - ], - - 'failover' => [ - 'driver' => 'failover', - 'connections' => [ - 'database', - 'deferred', - ], - ], - ], /* diff --git a/config/services.php b/config/services.php index 82eeeef..14b9dd1 100644 --- a/config/services.php +++ b/config/services.php @@ -15,11 +15,7 @@ return [ */ 'postmark' => [ - 'key' => env('POSTMARK_API_KEY'), - ], - - 'resend' => [ - 'key' => env('RESEND_API_KEY'), + 'token' => env('POSTMARK_TOKEN'), ], 'ses' => [ @@ -28,6 +24,10 @@ return [ 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), ], + 'resend' => [ + 'key' => env('RESEND_KEY'), + ], + 'slack' => [ 'notifications' => [ 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), @@ -41,8 +41,6 @@ return [ 'proxy_refresh_cron' => env('TRMNL_PROXY_REFRESH_CRON'), 'override_orig_icon' => env('TRMNL_OVERRIDE_ORIG_ICON', false), 'image_url_timeout' => env('TRMNL_IMAGE_URL_TIMEOUT', 30), // 30 seconds; increase on low-powered devices - 'liquid_enabled' => env('TRMNL_LIQUID_ENABLED', false), - 'liquid_path' => env('TRMNL_LIQUID_PATH', '/usr/local/bin/trmnl-liquid-cli'), ], 'webhook' => [ @@ -52,16 +50,4 @@ return [ ], ], - 'oidc' => [ - 'enabled' => env('OIDC_ENABLED', false), - // OIDC_ENDPOINT can be either: - // - Base URL: https://your-provider.com (will append /.well-known/openid-configuration) - // - Full well-known URL: https://your-provider.com/.well-known/openid-configuration - 'endpoint' => env('OIDC_ENDPOINT'), - 'client_id' => env('OIDC_CLIENT_ID'), - 'client_secret' => env('OIDC_CLIENT_SECRET'), - 'redirect' => env('APP_URL', 'http://localhost:8000').'/auth/oidc/callback', - 'scopes' => explode(',', env('OIDC_SCOPES', 'openid,profile,email')), - ], - ]; diff --git a/config/session.php b/config/session.php index 5b541b7..f0b6541 100644 --- a/config/session.php +++ b/config/session.php @@ -13,8 +13,8 @@ return [ | incoming requests. Laravel supports a variety of storage options to | persist session data. Database storage is a great default choice. | - | Supported: "file", "cookie", "database", "memcached", - | "redis", "dynamodb", "array" + | Supported: "file", "cookie", "database", "apc", + | "memcached", "redis", "dynamodb", "array" | */ @@ -32,7 +32,7 @@ return [ | */ - 'lifetime' => (int) env('SESSION_LIFETIME', 120), + 'lifetime' => env('SESSION_LIFETIME', 120), 'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false), @@ -97,7 +97,7 @@ return [ | define the cache store which should be used to store the session data | between requests. This must match one of your defined cache stores. | - | Affects: "dynamodb", "memcached", "redis" + | Affects: "apc", "dynamodb", "memcached", "redis" | */ @@ -129,7 +129,7 @@ return [ 'cookie' => env( 'SESSION_COOKIE', - Str::slug((string) env('APP_NAME', 'laravel')).'-session' + Str::slug(env('APP_NAME', 'laravel'), '_').'_session' ), /* @@ -152,7 +152,7 @@ return [ | | This value determines the domain and subdomains the session cookie is | available to. By default, the cookie will be available to the root - | domain without subdomains. Typically, this shouldn't be changed. + | domain and all subdomains. Typically, this shouldn't be changed. | */ diff --git a/config/trustedproxy.php b/config/trustedproxy.php deleted file mode 100644 index 8557288..0000000 --- a/config/trustedproxy.php +++ /dev/null @@ -1,6 +0,0 @@ - ($proxies = env('TRUSTED_PROXIES', '')) === '*' ? '*' : array_filter(explode(',', $proxies)), -]; diff --git a/database/factories/DeviceModelFactory.php b/database/factories/DeviceModelFactory.php deleted file mode 100644 index ec3f77d..0000000 --- a/database/factories/DeviceModelFactory.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -class DeviceModelFactory extends Factory -{ - protected $model = DeviceModel::class; - - /** - * Define the model's default state. - * - * @return array - */ - public function definition(): array - { - return [ - 'name' => $this->faker->unique()->slug(), - 'label' => $this->faker->words(2, true), - 'description' => $this->faker->sentence(), - 'width' => $this->faker->randomElement([800, 1024, 1280, 1920]), - 'height' => $this->faker->randomElement([480, 600, 720, 1080]), - 'colors' => $this->faker->randomElement([2, 16, 256, 65536]), - 'bit_depth' => $this->faker->randomElement([1, 4, 8, 16]), - 'scale_factor' => $this->faker->randomElement([1, 2, 4]), - 'rotation' => $this->faker->randomElement([0, 90, 180, 270]), - 'mime_type' => $this->faker->randomElement(['image/png', 'image/jpeg', 'image/gif']), - 'offset_x' => $this->faker->numberBetween(-100, 100), - 'offset_y' => $this->faker->numberBetween(-100, 100), - 'published_at' => $this->faker->optional()->dateTimeBetween('-1 year', 'now'), - ]; - } -} diff --git a/database/factories/DevicePaletteFactory.php b/database/factories/DevicePaletteFactory.php deleted file mode 100644 index 1d7ed2d..0000000 --- a/database/factories/DevicePaletteFactory.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -class DevicePaletteFactory extends Factory -{ - protected $model = DevicePalette::class; - - /** - * Define the model's default state. - * - * @return array - */ - public function definition(): array - { - return [ - 'id' => 'test-'.$this->faker->unique()->slug(), - 'name' => $this->faker->words(3, true), - 'grays' => $this->faker->randomElement([2, 4, 16, 256]), - 'colors' => $this->faker->optional()->passthrough([ - '#FF0000', - '#00FF00', - '#0000FF', - '#FFFF00', - '#000000', - '#FFFFFF', - ]), - 'framework_class' => null, - 'source' => 'api', - ]; - } -} diff --git a/database/factories/PluginFactory.php b/database/factories/PluginFactory.php index 10a1580..a2d2e65 100644 --- a/database/factories/PluginFactory.php +++ b/database/factories/PluginFactory.php @@ -29,24 +29,8 @@ class PluginFactory extends Factory 'icon_url' => null, 'flux_icon_name' => null, 'author_name' => $this->faker->name(), - 'plugin_type' => 'recipe', 'created_at' => Carbon::now(), 'updated_at' => Carbon::now(), ]; } - - /** - * Indicate that the plugin is an image webhook plugin. - */ - public function imageWebhook(): static - { - return $this->state(fn (array $attributes): array => [ - 'plugin_type' => 'image_webhook', - 'data_strategy' => 'static', - 'data_stale_minutes' => 60, - 'polling_url' => null, - 'polling_verb' => 'get', - 'name' => $this->faker->randomElement(['Camera Feed', 'Security Camera', 'Webcam', 'Image Stream']), - ]); - } } diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 80da5ac..c5d3f2c 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -29,9 +29,7 @@ class UserFactory extends Factory 'email_verified_at' => now(), 'password' => static::$password ??= Hash::make('password'), 'remember_token' => Str::random(10), - 'two_factor_secret' => null, - 'two_factor_recovery_codes' => null, - 'two_factor_confirmed_at' => null, + 'assign_new_devices' => false, ]; } @@ -44,16 +42,4 @@ class UserFactory extends Factory 'email_verified_at' => null, ]); } - - /** - * Indicate that the model has two-factor authentication configured. - */ - public function withTwoFactor(): static - { - return $this->state(fn (array $attributes) => [ - 'two_factor_secret' => encrypt('secret'), - 'two_factor_recovery_codes' => encrypt(json_encode(['recovery-code-1'])), - 'two_factor_confirmed_at' => now(), - ]); - } } diff --git a/database/migrations/2025_06_13_102932_add_configuration_to_plugins_table.php b/database/migrations/2025_06_13_102932_add_configuration_to_plugins_table.php deleted file mode 100644 index 2ed9123..0000000 --- a/database/migrations/2025_06_13_102932_add_configuration_to_plugins_table.php +++ /dev/null @@ -1,30 +0,0 @@ -json('configuration_template')->nullable(); - $table->json('configuration')->nullable(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('plugins', function (Blueprint $table) { - $table->dropColumn('configuration_template'); - $table->dropColumn('configuration'); - }); - } -}; diff --git a/database/migrations/2025_08_04_064514_add_oidc_sub_to_users_table.php b/database/migrations/2025_08_04_064514_add_oidc_sub_to_users_table.php deleted file mode 100644 index 7ec1374..0000000 --- a/database/migrations/2025_08_04_064514_add_oidc_sub_to_users_table.php +++ /dev/null @@ -1,29 +0,0 @@ -string('oidc_sub')->nullable()->unique()->after('email'); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('users', function (Blueprint $table) { - $table->dropUnique(['oidc_sub']); - $table->dropColumn('oidc_sub'); - }); - } -}; diff --git a/database/migrations/2025_08_07_111635_create_device_models_table.php b/database/migrations/2025_08_07_111635_create_device_models_table.php deleted file mode 100644 index 338ca98..0000000 --- a/database/migrations/2025_08_07_111635_create_device_models_table.php +++ /dev/null @@ -1,41 +0,0 @@ -id(); - $table->string('name')->unique(); - $table->string('label'); - $table->text('description'); - $table->unsignedInteger('width'); - $table->unsignedInteger('height'); - $table->unsignedInteger('colors'); - $table->unsignedInteger('bit_depth'); - $table->float('scale_factor'); - $table->integer('rotation'); - $table->string('mime_type'); - $table->integer('offset_x')->default(0); - $table->integer('offset_y')->default(0); - $table->timestamp('published_at')->nullable(); - $table->string('source')->nullable(); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('device_models'); - } -}; diff --git a/database/migrations/2025_08_07_131843_add_device_model_id_to_devices_table.php b/database/migrations/2025_08_07_131843_add_device_model_id_to_devices_table.php deleted file mode 100644 index 727c545..0000000 --- a/database/migrations/2025_08_07_131843_add_device_model_id_to_devices_table.php +++ /dev/null @@ -1,29 +0,0 @@ -foreignId('device_model_id')->nullable()->constrained('device_models')->nullOnDelete(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('devices', function (Blueprint $table) { - $table->dropForeign(['device_model_id']); - $table->dropColumn('device_model_id'); - }); - } -}; diff --git a/database/migrations/2025_08_16_135740_seed_device_models.php b/database/migrations/2025_08_16_135740_seed_device_models.php deleted file mode 100644 index 355227f..0000000 --- a/database/migrations/2025_08_16_135740_seed_device_models.php +++ /dev/null @@ -1,285 +0,0 @@ - 'og_png', - 'label' => 'TRMNL OG (1-bit)', - 'description' => 'TRMNL OG (1-bit)', - 'width' => 800, - 'height' => 480, - 'colors' => 2, - 'bit_depth' => 1, - 'scale_factor' => 1, - 'rotation' => 0, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'published_at' => '2024-01-01 00:00:00', - 'source' => 'api', - 'created_at' => now(), - 'updated_at' => now(), - ], - [ - 'name' => 'og_plus', - 'label' => 'TRMNL OG (2-bit)', - 'description' => 'TRMNL OG (2-bit)', - 'width' => 800, - 'height' => 480, - 'colors' => 4, - 'bit_depth' => 2, - 'scale_factor' => 1, - 'rotation' => 0, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'published_at' => '2024-01-01 00:00:00', - 'source' => 'api', - 'created_at' => now(), - 'updated_at' => now(), - ], - [ - 'name' => 'amazon_kindle_2024', - 'label' => 'Amazon Kindle 2024', - 'description' => 'Amazon Kindle 2024', - 'width' => 1400, - 'height' => 840, - 'colors' => 256, - 'bit_depth' => 8, - 'scale_factor' => 2.414, - 'rotation' => 90, - 'mime_type' => 'image/png', - 'offset_x' => 75, - 'offset_y' => 25, - 'published_at' => '2024-01-01 00:00:00', - 'source' => 'api', - 'created_at' => now(), - 'updated_at' => now(), - ], - [ - 'name' => 'amazon_kindle_paperwhite_6th_gen', - 'label' => 'Amazon Kindle PW 6th Gen', - 'description' => 'Amazon Kindle PW 6th Gen', - 'width' => 1024, - 'height' => 768, - 'colors' => 256, - 'bit_depth' => 8, - 'scale_factor' => 1, - 'rotation' => 90, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'published_at' => '2024-01-01 00:00:00', - 'source' => 'api', - 'created_at' => now(), - 'updated_at' => now(), - ], - [ - 'name' => 'amazon_kindle_paperwhite_7th_gen', - 'label' => 'Amazon Kindle PW 7th Gen', - 'description' => 'Amazon Kindle PW 7th Gen', - 'width' => 1448, - 'height' => 1072, - 'colors' => 256, - 'bit_depth' => 8, - 'scale_factor' => 1, - 'rotation' => 90, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'published_at' => '2024-01-01 00:00:00', - 'source' => 'api', - 'created_at' => now(), - 'updated_at' => now(), - ], - [ - 'name' => 'inkplate_10', - 'label' => 'Inkplate 10', - 'description' => 'Inkplate 10', - 'width' => 1200, - 'height' => 820, - 'colors' => 8, - 'bit_depth' => 3, - 'scale_factor' => 1, - 'rotation' => 0, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'published_at' => '2024-01-01 00:00:00', - 'source' => 'api', - 'created_at' => now(), - 'updated_at' => now(), - ], - [ - 'name' => 'amazon_kindle_7', - 'label' => 'Amazon Kindle 7', - 'description' => 'Amazon Kindle 7', - 'width' => 800, - 'height' => 600, - 'colors' => 256, - 'bit_depth' => 8, - 'scale_factor' => 1, - 'rotation' => 90, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'published_at' => '2024-01-01 00:00:00', - 'source' => 'api', - 'created_at' => now(), - 'updated_at' => now(), - ], - [ - 'name' => 'inky_impression_7_3', - 'label' => 'Inky Impression 7.3', - 'description' => 'Inky Impression 7.3', - 'width' => 800, - 'height' => 480, - 'colors' => 2, - 'bit_depth' => 1, - 'scale_factor' => 1, - 'rotation' => 0, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'published_at' => '2024-01-01 00:00:00', - 'source' => 'api', - 'created_at' => now(), - 'updated_at' => now(), - ], - [ - 'name' => 'kobo_libra_2', - 'label' => 'Kobo Libra 2', - 'description' => 'Kobo Libra 2', - 'width' => 1680, - 'height' => 1264, - 'colors' => 256, - 'bit_depth' => 8, - 'scale_factor' => 1, - 'rotation' => 90, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'published_at' => '2024-01-01 00:00:00', - 'source' => 'api', - 'created_at' => now(), - 'updated_at' => now(), - ], - [ - 'name' => 'amazon_kindle_oasis_2', - 'label' => 'Amazon Kindle Oasis 2', - 'description' => 'Amazon Kindle Oasis 2', - 'width' => 1680, - 'height' => 1264, - 'colors' => 256, - 'bit_depth' => 8, - 'scale_factor' => 1, - 'rotation' => 90, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'published_at' => '2024-01-01 00:00:00', - 'source' => 'api', - 'created_at' => now(), - 'updated_at' => now(), - ], - [ - 'name' => 'kobo_aura_one', - 'label' => 'Kobo Aura One', - 'description' => 'Kobo Aura One', - 'width' => 1872, - 'height' => 1404, - 'colors' => 256, - 'bit_depth' => 8, - 'scale_factor' => 1, - 'rotation' => 90, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'published_at' => '2024-01-01 00:00:00', - 'source' => 'api', - 'created_at' => now(), - 'updated_at' => now(), - ], - [ - 'name' => 'kobo_aura_hd', - 'label' => 'Kobo Aura HD', - 'description' => 'Kobo Aura HD', - 'width' => 1440, - 'height' => 1080, - 'colors' => 16, - 'bit_depth' => 4, - 'scale_factor' => 1, - 'rotation' => 90, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'published_at' => '2024-01-01 00:00:00', - 'source' => 'api', - 'created_at' => now(), - 'updated_at' => now(), - ], - [ - 'name' => 'inky_impression_13_3', - 'label' => 'Inky Impression 13.3', - 'description' => 'Inky Impression 13.3', - 'width' => 1600, - 'height' => 1200, - 'colors' => 2, - 'bit_depth' => 1, - 'scale_factor' => 1, - 'rotation' => 0, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'published_at' => '2024-01-01 00:00:00', - 'source' => 'api', - 'created_at' => now(), - 'updated_at' => now(), - ], - ]; - - // Upsert by unique 'name' to avoid duplicates and keep data fresh - DeviceModel::query()->upsert( - $deviceModels, - ['name'], - [ - 'label', 'description', 'width', 'height', 'colors', 'bit_depth', 'scale_factor', - 'rotation', 'mime_type', 'offset_x', 'offset_y', 'published_at', 'source', - 'created_at', 'updated_at', - ] - ); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - $names = [ - 'og_png', - 'amazon_kindle_2024', - 'amazon_kindle_paperwhite_6th_gen', - 'amazon_kindle_paperwhite_7th_gen', - 'inkplate_10', - 'amazon_kindle_7', - 'inky_impression_7_3', - 'kobo_libra_2', - 'amazon_kindle_oasis_2', - 'og_plus', - 'kobo_aura_one', - 'kobo_aura_hd', - 'inky_impression_13_3', - ]; - - DeviceModel::query()->whereIn('name', $names)->delete(); - } -}; diff --git a/database/migrations/2025_08_22_231823_add_trmnlp_to_plugins_table.php b/database/migrations/2025_08_22_231823_add_trmnlp_to_plugins_table.php deleted file mode 100644 index 4c90d29..0000000 --- a/database/migrations/2025_08_22_231823_add_trmnlp_to_plugins_table.php +++ /dev/null @@ -1,28 +0,0 @@ -string('trmnlp_id')->nullable()->after('uuid'); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('plugins', function (Blueprint $table) { - $table->dropColumn('trmnlp_id'); - }); - } -}; diff --git a/database/migrations/2025_10_30_144500_add_no_bleed_and_dark_mode_to_plugins_table.php b/database/migrations/2025_10_30_144500_add_no_bleed_and_dark_mode_to_plugins_table.php deleted file mode 100644 index f7329c8..0000000 --- a/database/migrations/2025_10_30_144500_add_no_bleed_and_dark_mode_to_plugins_table.php +++ /dev/null @@ -1,32 +0,0 @@ -boolean('no_bleed')->default(false)->after('configuration_template'); - } - if (! Schema::hasColumn('plugins', 'dark_mode')) { - $table->boolean('dark_mode')->default(false)->after('no_bleed'); - } - }); - } - - public function down(): void - { - Schema::table('plugins', function (Blueprint $table): void { - if (Schema::hasColumn('plugins', 'dark_mode')) { - $table->dropColumn('dark_mode'); - } - if (Schema::hasColumn('plugins', 'no_bleed')) { - $table->dropColumn('no_bleed'); - } - }); - } -}; diff --git a/database/migrations/2025_11_03_213452_add_preferred_renderer_to_plugins_table.php b/database/migrations/2025_11_03_213452_add_preferred_renderer_to_plugins_table.php deleted file mode 100644 index a998420..0000000 --- a/database/migrations/2025_11_03_213452_add_preferred_renderer_to_plugins_table.php +++ /dev/null @@ -1,28 +0,0 @@ -string('preferred_renderer')->nullable()->after('markup_language'); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('plugins', function (Blueprint $table) { - $table->dropColumn('preferred_renderer'); - }); - } -}; diff --git a/database/migrations/2025_11_22_084119_create_device_palettes_table.php b/database/migrations/2025_11_22_084119_create_device_palettes_table.php deleted file mode 100644 index 9262dac..0000000 --- a/database/migrations/2025_11_22_084119_create_device_palettes_table.php +++ /dev/null @@ -1,33 +0,0 @@ -id(); - $table->string('name')->unique(); - $table->string('description')->nullable(); - $table->integer('grays'); - $table->json('colors')->nullable(); - $table->string('framework_class')->default(''); - $table->string('source')->default('api'); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('device_palettes'); - } -}; diff --git a/database/migrations/2025_11_22_084208_add_palette_id_to_device_models_table.php b/database/migrations/2025_11_22_084208_add_palette_id_to_device_models_table.php deleted file mode 100644 index 1993fcf..0000000 --- a/database/migrations/2025_11_22_084208_add_palette_id_to_device_models_table.php +++ /dev/null @@ -1,29 +0,0 @@ -foreignId('palette_id')->nullable()->after('source')->constrained('device_palettes')->onDelete('set null'); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('device_models', function (Blueprint $table) { - $table->dropForeign(['palette_id']); - $table->dropColumn('palette_id'); - }); - } -}; diff --git a/database/migrations/2025_11_22_084211_add_palette_id_to_devices_table.php b/database/migrations/2025_11_22_084211_add_palette_id_to_devices_table.php deleted file mode 100644 index 3a47afe..0000000 --- a/database/migrations/2025_11_22_084211_add_palette_id_to_devices_table.php +++ /dev/null @@ -1,29 +0,0 @@ -foreignId('palette_id')->nullable()->constrained('device_palettes')->onDelete('set null'); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('devices', function (Blueprint $table) { - $table->dropForeign(['palette_id']); - $table->dropColumn('palette_id'); - }); - } -}; diff --git a/database/migrations/2025_11_22_084425_seed_palettes_and_relationships.php b/database/migrations/2025_11_22_084425_seed_palettes_and_relationships.php deleted file mode 100644 index c198d81..0000000 --- a/database/migrations/2025_11_22_084425_seed_palettes_and_relationships.php +++ /dev/null @@ -1,124 +0,0 @@ - 'bw', - 'description' => 'Black & White', - 'grays' => 2, - 'colors' => null, - 'framework_class' => 'screen--1bit', - 'source' => 'api', - ], - [ - 'name' => 'gray-4', - 'description' => '4 Grays', - 'grays' => 4, - 'colors' => null, - 'framework_class' => 'screen--2bit', - 'source' => 'api', - ], - [ - 'name' => 'gray-16', - 'description' => '16 Grays', - 'grays' => 16, - 'colors' => null, - 'framework_class' => 'screen--4bit', - 'source' => 'api', - ], - [ - 'name' => 'gray-256', - 'description' => '256 Grays', - 'grays' => 256, - 'colors' => null, - 'framework_class' => 'screen--4bit', - 'source' => 'api', - ], - [ - 'name' => 'color-6a', - 'description' => '6 Colors', - 'grays' => 2, - 'colors' => json_encode(['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#000000', '#FFFFFF']), - 'framework_class' => '', - 'source' => 'api', - ], - [ - 'name' => 'color-7a', - 'description' => '7 Colors', - 'grays' => 2, - 'colors' => json_encode(['#000000', '#FFFFFF', '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FFA500']), - 'framework_class' => '', - 'source' => 'api', - ], - ]; - - $now = now(); - $paletteIdMap = []; - - foreach ($palettes as $paletteData) { - $paletteName = $paletteData['name']; - $paletteData['created_at'] = $now; - $paletteData['updated_at'] = $now; - - DB::table('device_palettes')->updateOrInsert( - ['name' => $paletteName], - $paletteData - ); - - // Get the ID of the palette (either newly created or existing) - $paletteRecord = DB::table('device_palettes')->where('name', $paletteName)->first(); - $paletteIdMap[$paletteName] = $paletteRecord->id; - } - - // Set default palette_id on DeviceModel based on first palette_ids entry - $models = [ - ['name' => 'og_png', 'palette_name' => 'bw'], - ['name' => 'og_plus', 'palette_name' => 'gray-4'], - ['name' => 'amazon_kindle_2024', 'palette_name' => 'gray-256'], - ['name' => 'amazon_kindle_paperwhite_6th_gen', 'palette_name' => 'gray-256'], - ['name' => 'amazon_kindle_paperwhite_7th_gen', 'palette_name' => 'gray-256'], - ['name' => 'inkplate_10', 'palette_name' => 'gray-4'], - ['name' => 'amazon_kindle_7', 'palette_name' => 'gray-256'], - ['name' => 'inky_impression_7_3', 'palette_name' => 'color-7a'], - ['name' => 'kobo_libra_2', 'palette_name' => 'gray-16'], - ['name' => 'amazon_kindle_oasis_2', 'palette_name' => 'gray-256'], - ['name' => 'kobo_aura_one', 'palette_name' => 'gray-16'], - ['name' => 'kobo_aura_hd', 'palette_name' => 'gray-16'], - ['name' => 'inky_impression_13_3', 'palette_name' => 'color-6a'], - ['name' => 'm5_paper_s3', 'palette_name' => 'gray-16'], - ['name' => 'amazon_kindle_scribe', 'palette_name' => 'gray-256'], - ['name' => 'seeed_e1001', 'palette_name' => 'gray-4'], - ['name' => 'seeed_e1002', 'palette_name' => 'gray-4'], - ['name' => 'waveshare_4_26', 'palette_name' => 'gray-4'], - ['name' => 'waveshare_7_5_bw', 'palette_name' => 'bw'], - ]; - - foreach ($models as $modelData) { - $deviceModel = DeviceModel::where('name', $modelData['name'])->first(); - if ($deviceModel && ! $deviceModel->palette_id && isset($paletteIdMap[$modelData['palette_name']])) { - $deviceModel->update(['palette_id' => $paletteIdMap[$modelData['palette_name']]]); - } - } - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - // Remove palette_id from device models but keep palettes - DeviceModel::query()->update(['palette_id' => null]); - } -}; diff --git a/database/migrations/2025_12_02_154228_add_timezone_to_users_table.php b/database/migrations/2025_12_02_154228_add_timezone_to_users_table.php deleted file mode 100644 index 8a92627..0000000 --- a/database/migrations/2025_12_02_154228_add_timezone_to_users_table.php +++ /dev/null @@ -1,28 +0,0 @@ -string('timezone')->nullable()->after('oidc_sub'); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('users', function (Blueprint $table) { - $table->dropColumn('timezone'); - }); - } -}; diff --git a/database/migrations/2026_01_05_153321_add_plugin_type_to_plugins_table.php b/database/migrations/2026_01_05_153321_add_plugin_type_to_plugins_table.php deleted file mode 100644 index 558fe2c..0000000 --- a/database/migrations/2026_01_05_153321_add_plugin_type_to_plugins_table.php +++ /dev/null @@ -1,28 +0,0 @@ -string('plugin_type')->default('recipe')->after('uuid'); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('plugins', function (Blueprint $table): void { - $table->dropColumn('plugin_type'); - }); - } -}; diff --git a/database/migrations/2026_01_08_173521_add_kind_to_device_models_table.php b/database/migrations/2026_01_08_173521_add_kind_to_device_models_table.php deleted file mode 100644 index d230657..0000000 --- a/database/migrations/2026_01_08_173521_add_kind_to_device_models_table.php +++ /dev/null @@ -1,33 +0,0 @@ -string('kind')->nullable()->index(); - }); - - // Set existing og_png and og_plus to kind "trmnl" - DeviceModel::whereIn('name', ['og_png', 'og_plus'])->update(['kind' => 'trmnl']); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('device_models', function (Blueprint $table) { - $table->dropIndex(['kind']); - $table->dropColumn('kind'); - }); - } -}; diff --git a/database/migrations/2026_01_11_121809_make_trmnlp_id_unique_in_plugins_table.php b/database/migrations/2026_01_11_121809_make_trmnlp_id_unique_in_plugins_table.php deleted file mode 100644 index 3b9b1b7..0000000 --- a/database/migrations/2026_01_11_121809_make_trmnlp_id_unique_in_plugins_table.php +++ /dev/null @@ -1,58 +0,0 @@ -selectRaw('user_id, trmnlp_id, COUNT(*) as duplicate_count') - ->whereNotNull('trmnlp_id') - ->groupBy('user_id', 'trmnlp_id') - ->havingRaw('COUNT(*) > ?', [1]) - ->get(); - - // For each duplicate combination, keep the first one (by id) and set others to null - foreach ($duplicates as $duplicate) { - $plugins = Plugin::query() - ->where('user_id', $duplicate->user_id) - ->where('trmnlp_id', $duplicate->trmnlp_id) - ->orderBy('id') - ->get(); - - // Keep the first one, set the rest to null - $keepFirst = true; - foreach ($plugins as $plugin) { - if ($keepFirst) { - $keepFirst = false; - - continue; - } - - $plugin->update(['trmnlp_id' => null]); - } - } - - Schema::table('plugins', function (Blueprint $table) { - $table->unique(['user_id', 'trmnlp_id']); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('plugins', function (Blueprint $table) { - $table->dropUnique(['user_id', 'trmnlp_id']); - }); - } -}; diff --git a/database/migrations/2026_01_11_173757_add_alias_to_plugins_table.php b/database/migrations/2026_01_11_173757_add_alias_to_plugins_table.php deleted file mode 100644 index 0a527d7..0000000 --- a/database/migrations/2026_01_11_173757_add_alias_to_plugins_table.php +++ /dev/null @@ -1,28 +0,0 @@ -boolean('alias')->default(false); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('plugins', function (Blueprint $table) { - $table->dropColumn('alias'); - }); - } -}; diff --git a/database/migrations/2026_01_15_075243_add_two_factor_columns_to_users_table.php b/database/migrations/2026_01_15_075243_add_two_factor_columns_to_users_table.php deleted file mode 100644 index 187d974..0000000 --- a/database/migrations/2026_01_15_075243_add_two_factor_columns_to_users_table.php +++ /dev/null @@ -1,34 +0,0 @@ -text('two_factor_secret')->after('password')->nullable(); - $table->text('two_factor_recovery_codes')->after('two_factor_secret')->nullable(); - $table->timestamp('two_factor_confirmed_at')->after('two_factor_recovery_codes')->nullable(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('users', function (Blueprint $table) { - $table->dropColumn([ - 'two_factor_secret', - 'two_factor_recovery_codes', - 'two_factor_confirmed_at', - ]); - }); - } -}; diff --git a/database/seeders/ExampleRecipesSeeder.php b/database/seeders/ExampleRecipesSeeder.php index 890eed9..9d8e9bb 100644 --- a/database/seeders/ExampleRecipesSeeder.php +++ b/database/seeders/ExampleRecipesSeeder.php @@ -13,8 +13,8 @@ class ExampleRecipesSeeder extends Seeder public function run($user_id = 1): void { Plugin::updateOrCreate( - ['uuid' => '9e46c6cf-358c-4bfe-8998-436b3a207fec'], [ + 'uuid' => '9e46c6cf-358c-4bfe-8998-436b3a207fec', 'name' => 'Γ–BB Departures', 'user_id' => $user_id, 'data_payload' => null, @@ -32,8 +32,8 @@ class ExampleRecipesSeeder extends Seeder ); Plugin::updateOrCreate( - ['uuid' => '3b046eda-34e9-4232-b935-c33b989a284b'], [ + 'uuid' => '3b046eda-34e9-4232-b935-c33b989a284b', 'name' => 'Weather', 'user_id' => $user_id, 'data_payload' => null, @@ -51,8 +51,8 @@ class ExampleRecipesSeeder extends Seeder ); Plugin::updateOrCreate( - ['uuid' => '21464b16-5f5a-4099-a967-f5c915e3da54'], [ + 'uuid' => '21464b16-5f5a-4099-a967-f5c915e3da54', 'name' => 'Zen Quotes', 'user_id' => $user_id, 'data_payload' => null, @@ -70,8 +70,8 @@ class ExampleRecipesSeeder extends Seeder ); Plugin::updateOrCreate( - ['uuid' => '8d472959-400f-46ee-afb2-4a9f1cfd521f'], [ + 'uuid' => '8d472959-400f-46ee-afb2-4a9f1cfd521f', 'name' => 'This Day in History', 'user_id' => $user_id, 'data_payload' => null, @@ -89,8 +89,8 @@ class ExampleRecipesSeeder extends Seeder ); Plugin::updateOrCreate( - ['uuid' => '4349fdad-a273-450b-aa00-3d32f2de788d'], [ + 'uuid' => '4349fdad-a273-450b-aa00-3d32f2de788d', 'name' => 'Home Assistant', 'user_id' => $user_id, 'data_payload' => null, @@ -108,8 +108,8 @@ class ExampleRecipesSeeder extends Seeder ); Plugin::updateOrCreate( - ['uuid' => 'be5f7e1f-3ad8-4d66-93b2-36f7d6dcbd80'], [ + 'uuid' => 'be5f7e1f-3ad8-4d66-93b2-36f7d6dcbd80', 'name' => 'Sunrise/Sunset', 'user_id' => $user_id, 'data_payload' => null, @@ -127,8 +127,8 @@ class ExampleRecipesSeeder extends Seeder ); Plugin::updateOrCreate( - ['uuid' => '82d3ee14-d578-4969-bda5-2bbf825435fe'], [ + 'uuid' => '82d3ee14-d578-4969-bda5-2bbf825435fe', 'name' => 'Pollen Forecast', 'user_id' => $user_id, 'data_payload' => null, @@ -144,42 +144,5 @@ class ExampleRecipesSeeder extends Seeder 'flux_icon_name' => 'flower', ] ); - - Plugin::updateOrCreate( - ['uuid' => '1d98bca4-837d-4b01-b1a1-e3b6e56eca90'], - [ - 'name' => 'Holidays (iCal)', - 'user_id' => $user_id, - 'data_payload' => null, - 'data_stale_minutes' => 720, - 'data_strategy' => 'polling', - 'configuration_template' => [ - 'custom_fields' => [ - [ - 'keyname' => 'calendar', - 'field_type' => 'select', - 'name' => 'Public Holidays Calendar', - 'options' => [ - ['USA' => 'usa'], - ['Austria' => 'austria'], - ['Australia' => 'australia'], - ['Canada' => 'canada'], - ['Germany' => 'germany'], - ['UK' => 'united-kingdom'], - ], - ], - ], - ], - 'configuration' => ['calendar' => 'usa'], - 'polling_url' => 'https://www.officeholidays.com/ics-clean/{{calendar}}', - 'polling_verb' => 'get', - 'polling_header' => null, - 'render_markup' => null, - 'render_markup_view' => 'recipes.holidays-ical', - 'detail_view_route' => null, - 'icon_url' => null, - 'flux_icon_name' => 'calendar', - ] - ); } } diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 40bcbd3..c7bca71 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -1,4 +1,4 @@ -## Local Development +### Local Development #### Requirements @@ -16,20 +16,14 @@ git clone git@github.com:usetrmnl/byos_laravel.git ```bash cp .env.example .env +php artisan key:generate ``` -#### Install dependencies and build frontend +#### Install dependencies ```bash composer install npm i -npm run build -``` - -#### Generate application key - -```bash -php artisan key:generate ``` #### Run migrations @@ -38,12 +32,6 @@ php artisan key:generate php artisan migrate --seed ``` -#### Link storage to expose public assets - -```bash -php artisan storage:link -``` - #### Run the server To expose the built-in server to the local network, you can run the following command: @@ -52,9 +40,7 @@ To expose the built-in server to the local network, you can run the following co php artisan serve --host=0.0.0.0 --port 4567 ``` ---- - -## Docker +### Docker Use the provided Dockerfile, or docker-compose file to run the server in a container. #### .devcontainer diff --git a/lang/de/custom_plugins.php b/lang/de/custom_plugins.php deleted file mode 100644 index 3fd8785..0000000 --- a/lang/de/custom_plugins.php +++ /dev/null @@ -1,7 +0,0 @@ - 'heute', - 'tomorrow' => 'morgen', - 'yesterday' => 'gestern', -]; diff --git a/package-lock.json b/package-lock.json index e722432..0fdc023 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,31 +1,18 @@ { - "name": "laravel", + "name": "byos_laravel", "lockfileVersion": 3, "requires": true, "packages": { "": { "dependencies": { - "@codemirror/commands": "^6.9.0", - "@codemirror/lang-css": "^6.3.1", - "@codemirror/lang-html": "^6.4.11", - "@codemirror/lang-javascript": "^6.2.4", - "@codemirror/lang-json": "^6.0.2", - "@codemirror/lang-liquid": "^6.3.0", - "@codemirror/language": "^6.11.3", - "@codemirror/search": "^6.5.11", - "@codemirror/state": "^6.5.2", - "@codemirror/theme-one-dark": "^6.1.3", - "@codemirror/view": "^6.38.5", - "@fsegurai/codemirror-theme-github-light": "^6.2.2", - "@tailwindcss/vite": "^4.1.11", + "@tailwindcss/vite": "^4.0.7", "autoprefixer": "^10.4.20", "axios": "^1.8.2", - "codemirror": "^6.0.2", "concurrently": "^9.0.1", - "laravel-vite-plugin": "^2.0", - "puppeteer": "24.30.0", + "laravel-vite-plugin": "^1.0", + "puppeteer": "^24.3.0", "tailwindcss": "^4.0.7", - "vite": "^7.0.4" + "vite": "^6.3" }, "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "4.9.5", @@ -33,6 +20,19 @@ "lightningcss-linux-x64-gnu": "^1.29.1" } }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -48,182 +48,18 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, - "node_modules/@codemirror/autocomplete": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.0.tgz", - "integrity": "sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg==", - "license": "MIT", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@codemirror/commands": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.0.tgz", - "integrity": "sha512-2xUIc5mHXQzT16JnyOFkh8PvfeXuIut3pslWGfsGOhxP/lpgRm9HOl/mpzLErgt5mXDovqA0d11P21gofRLb9w==", - "license": "MIT", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.27.0", - "@lezer/common": "^1.1.0" - } - }, - "node_modules/@codemirror/lang-css": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz", - "integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==", - "license": "MIT", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.0.2", - "@lezer/css": "^1.1.7" - } - }, - "node_modules/@codemirror/lang-html": { - "version": "6.4.11", - "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.11.tgz", - "integrity": "sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==", - "license": "MIT", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/lang-css": "^6.0.0", - "@codemirror/lang-javascript": "^6.0.0", - "@codemirror/language": "^6.4.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0", - "@lezer/css": "^1.1.0", - "@lezer/html": "^1.3.12" - } - }, - "node_modules/@codemirror/lang-javascript": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.4.tgz", - "integrity": "sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==", - "license": "MIT", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.6.0", - "@codemirror/lint": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0", - "@lezer/javascript": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-json": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", - "integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==", - "license": "MIT", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@lezer/json": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-liquid": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@codemirror/lang-liquid/-/lang-liquid-6.3.0.tgz", - "integrity": "sha512-fY1YsUExcieXRTsCiwX/bQ9+PbCTA/Fumv7C7mTUZHoFkibfESnaXwpr2aKH6zZVwysEunsHHkaIpM/pl3xETQ==", - "license": "MIT", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/lang-html": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.3.1" - } - }, - "node_modules/@codemirror/language": { - "version": "6.11.3", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.3.tgz", - "integrity": "sha512-9HBM2XnwDj7fnu0551HkGdrUrrqmYq/WC5iv6nbY2WdicXdGbhR/gfbZOH73Aqj4351alY1+aoG9rCNfiwS1RA==", - "license": "MIT", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.23.0", - "@lezer/common": "^1.1.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0", - "style-mod": "^4.0.0" - } - }, - "node_modules/@codemirror/lint": { - "version": "6.9.2", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.2.tgz", - "integrity": "sha512-sv3DylBiIyi+xKwRCJAAsBZZZWo82shJ/RTMymLabAdtbkV5cSKwWDeCgtUq3v8flTaXS2y1kKkICuRYtUswyQ==", - "license": "MIT", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.35.0", - "crelt": "^1.0.5" - } - }, - "node_modules/@codemirror/search": { - "version": "6.5.11", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.11.tgz", - "integrity": "sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==", - "license": "MIT", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "crelt": "^1.0.5" - } - }, - "node_modules/@codemirror/state": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", - "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==", - "license": "MIT", - "dependencies": { - "@marijn/find-cluster-break": "^1.0.0" - } - }, - "node_modules/@codemirror/theme-one-dark": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.3.tgz", - "integrity": "sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==", - "license": "MIT", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/highlight": "^1.0.0" - } - }, - "node_modules/@codemirror/view": { - "version": "6.38.8", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.8.tgz", - "integrity": "sha512-XcE9fcnkHCbWkjeKyi0lllwXmBLtyYb5dt89dJyx23I9+LSh5vZDIuk7OLG4VM1lgrXZQcY6cxyZyk5WVPRv/A==", - "license": "MIT", - "dependencies": { - "@codemirror/state": "^6.5.0", - "crelt": "^1.0.6", - "style-mod": "^4.1.0", - "w3c-keyname": "^2.2.4" - } - }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", "cpu": [ "ppc64" ], @@ -237,9 +73,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", "cpu": [ "arm" ], @@ -253,9 +89,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", "cpu": [ "arm64" ], @@ -269,9 +105,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", "cpu": [ "x64" ], @@ -285,9 +121,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", "cpu": [ "arm64" ], @@ -301,9 +137,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", "cpu": [ "x64" ], @@ -317,9 +153,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", "cpu": [ "arm64" ], @@ -333,9 +169,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", "cpu": [ "x64" ], @@ -349,9 +185,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", "cpu": [ "arm" ], @@ -365,9 +201,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", "cpu": [ "arm64" ], @@ -381,9 +217,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", "cpu": [ "ia32" ], @@ -397,9 +233,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", "cpu": [ "loong64" ], @@ -413,9 +249,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", "cpu": [ "mips64el" ], @@ -429,9 +265,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", "cpu": [ "ppc64" ], @@ -445,9 +281,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", "cpu": [ "riscv64" ], @@ -461,9 +297,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", "cpu": [ "s390x" ], @@ -477,9 +313,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", "cpu": [ "x64" ], @@ -493,9 +329,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", "cpu": [ "arm64" ], @@ -509,9 +345,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", "cpu": [ "x64" ], @@ -525,9 +361,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", "cpu": [ "arm64" ], @@ -541,9 +377,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", "cpu": [ "x64" ], @@ -556,26 +392,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", "cpu": [ "x64" ], @@ -589,9 +409,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", "cpu": [ "arm64" ], @@ -605,9 +425,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", "cpu": [ "ia32" ], @@ -621,9 +441,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", "cpu": [ "x64" ], @@ -636,36 +456,30 @@ "node": ">=18" } }, - "node_modules/@fsegurai/codemirror-theme-github-light": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@fsegurai/codemirror-theme-github-light/-/codemirror-theme-github-light-6.2.3.tgz", - "integrity": "sha512-vbwyznBoTrLQdWvQ6/vjIpoDojd7VIMK+sQnMXkKOjXbm5cGul6A3mqM2RSt9Z5NhIRikmxKkApflvWOJrDuWA==", - "license": "MIT", - "peerDependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/highlight": "^1.0.0" + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -677,108 +491,43 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@lezer/common": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.4.0.tgz", - "integrity": "sha512-DVeMRoGrgn/k45oQNu189BoW4SZwgZFzJ1+1TV5j2NJ/KFC83oa/enRqZSGshyeMk5cPWMhsKs9nx+8o0unwGg==", - "license": "MIT" - }, - "node_modules/@lezer/css": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.0.tgz", - "integrity": "sha512-pBL7hup88KbI7hXnZV3PQsn43DHy6TWyzuyk2AO9UyoXcDltvIdqWKE1dLL/45JVZ+YZkHe1WVHqO6wugZZWcw==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.3.0" - } - }, - "node_modules/@lezer/highlight": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", - "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.3.0" - } - }, - "node_modules/@lezer/html": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.12.tgz", - "integrity": "sha512-RJ7eRWdaJe3bsiiLLHjCFT1JMk8m1YP9kaUbvu2rMLEoOnke9mcTVDyfOslsln0LtujdWespjJ39w6zo+RsQYw==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/javascript": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.4.tgz", - "integrity": "sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.1.3", - "@lezer/lr": "^1.3.0" - } - }, - "node_modules/@lezer/json": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", - "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/lr": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.4.tgz", - "integrity": "sha512-LHL17Mq0OcFXm1pGQssuGTQFPPdxARjKM8f7GA5+sGtHi0K3R84YaSbmche0+RKWHnCsx9asEe5OWOI4FHfe4A==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@marijn/find-cluster-break": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", - "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", - "license": "MIT" - }, "node_modules/@puppeteer/browsers": { - "version": "2.10.13", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.13.tgz", - "integrity": "sha512-a9Ruw3j3qlnB5a/zHRTkruppynxqaeE4H9WNj5eYGRWqw0ZauZ23f4W2ARf3hghF5doozyD+CRtt7XSYuYRI/Q==", + "version": "2.10.5", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.5.tgz", + "integrity": "sha512-eifa0o+i8dERnngJwKrfp3dEq7ia5XFyoqB17S4gK8GhsQE4/P8nxOfQSE0zQHxzzLo/cmF+7+ywEQ7wK7Fb+w==", "license": "Apache-2.0", "dependencies": { - "debug": "^4.4.3", + "debug": "^4.4.1", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", - "semver": "^7.7.3", - "tar-fs": "^3.1.1", + "semver": "^7.7.2", + "tar-fs": "^3.0.8", "yargs": "^17.7.2" }, "bin": { @@ -789,9 +538,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", - "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz", + "integrity": "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==", "cpu": [ "arm" ], @@ -802,9 +551,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", - "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz", + "integrity": "sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==", "cpu": [ "arm64" ], @@ -815,9 +564,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", - "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz", + "integrity": "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==", "cpu": [ "arm64" ], @@ -828,9 +577,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", - "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz", + "integrity": "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==", "cpu": [ "x64" ], @@ -841,9 +590,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", - "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz", + "integrity": "sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==", "cpu": [ "arm64" ], @@ -854,9 +603,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", - "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz", + "integrity": "sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==", "cpu": [ "x64" ], @@ -867,9 +616,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", - "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz", + "integrity": "sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==", "cpu": [ "arm" ], @@ -880,9 +629,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", - "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz", + "integrity": "sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==", "cpu": [ "arm" ], @@ -893,9 +642,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", - "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz", + "integrity": "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==", "cpu": [ "arm64" ], @@ -906,9 +655,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", - "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz", + "integrity": "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==", "cpu": [ "arm64" ], @@ -918,10 +667,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", - "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz", + "integrity": "sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==", "cpu": [ "loong64" ], @@ -931,10 +680,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", - "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz", + "integrity": "sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==", "cpu": [ "ppc64" ], @@ -945,9 +694,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", - "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz", + "integrity": "sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==", "cpu": [ "riscv64" ], @@ -958,9 +707,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", - "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz", + "integrity": "sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==", "cpu": [ "riscv64" ], @@ -971,9 +720,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", - "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz", + "integrity": "sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==", "cpu": [ "s390x" ], @@ -997,9 +746,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", - "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz", + "integrity": "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==", "cpu": [ "x64" ], @@ -1009,23 +758,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", - "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", - "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz", + "integrity": "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==", "cpu": [ "arm64" ], @@ -1036,9 +772,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", - "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz", + "integrity": "sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==", "cpu": [ "ia32" ], @@ -1048,23 +784,10 @@ "win32" ] }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", - "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", - "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz", + "integrity": "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==", "cpu": [ "x64" ], @@ -1075,47 +798,52 @@ ] }, "node_modules/@tailwindcss/node": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.17.tgz", - "integrity": "sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.8.tgz", + "integrity": "sha512-OWwBsbC9BFAJelmnNcrKuf+bka2ZxCE2A4Ft53Tkg4uoiE67r/PMEYwCsourC26E+kmxfwE0hVzMdxqeW+xu7Q==", "license": "MIT", "dependencies": { - "@jridgewell/remapping": "^2.3.4", - "enhanced-resolve": "^5.18.3", - "jiti": "^2.6.1", - "lightningcss": "1.30.2", - "magic-string": "^0.30.21", + "@ampproject/remapping": "^2.3.0", + "enhanced-resolve": "^5.18.1", + "jiti": "^2.4.2", + "lightningcss": "1.30.1", + "magic-string": "^0.30.17", "source-map-js": "^1.2.1", - "tailwindcss": "4.1.17" + "tailwindcss": "4.1.8" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.17.tgz", - "integrity": "sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.8.tgz", + "integrity": "sha512-d7qvv9PsM5N3VNKhwVUhpK6r4h9wtLkJ6lz9ZY9aeZgrUWk1Z8VPyqyDT9MZlem7GTGseRQHkeB1j3tC7W1P+A==", + "hasInstallScript": true, "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.4.3" + }, "engines": { "node": ">= 10" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.17", - "@tailwindcss/oxide-darwin-arm64": "4.1.17", - "@tailwindcss/oxide-darwin-x64": "4.1.17", - "@tailwindcss/oxide-freebsd-x64": "4.1.17", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.17", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.17", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.17", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.17", - "@tailwindcss/oxide-linux-x64-musl": "4.1.17", - "@tailwindcss/oxide-wasm32-wasi": "4.1.17", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.17", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.17" + "@tailwindcss/oxide-android-arm64": "4.1.8", + "@tailwindcss/oxide-darwin-arm64": "4.1.8", + "@tailwindcss/oxide-darwin-x64": "4.1.8", + "@tailwindcss/oxide-freebsd-x64": "4.1.8", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.8", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.8", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.8", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.8", + "@tailwindcss/oxide-linux-x64-musl": "4.1.8", + "@tailwindcss/oxide-wasm32-wasi": "4.1.8", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.8", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.8" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.17.tgz", - "integrity": "sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.8.tgz", + "integrity": "sha512-Fbz7qni62uKYceWYvUjRqhGfZKwhZDQhlrJKGtnZfuNtHFqa8wmr+Wn74CTWERiW2hn3mN5gTpOoxWKk0jRxjg==", "cpu": [ "arm64" ], @@ -1129,9 +857,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.17.tgz", - "integrity": "sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.8.tgz", + "integrity": "sha512-RdRvedGsT0vwVVDztvyXhKpsU2ark/BjgG0huo4+2BluxdXo8NDgzl77qh0T1nUxmM11eXwR8jA39ibvSTbi7A==", "cpu": [ "arm64" ], @@ -1145,9 +873,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.17.tgz", - "integrity": "sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.8.tgz", + "integrity": "sha512-t6PgxjEMLp5Ovf7uMb2OFmb3kqzVTPPakWpBIFzppk4JE4ix0yEtbtSjPbU8+PZETpaYMtXvss2Sdkx8Vs4XRw==", "cpu": [ "x64" ], @@ -1161,9 +889,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.17.tgz", - "integrity": "sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.8.tgz", + "integrity": "sha512-g8C8eGEyhHTqwPStSwZNSrOlyx0bhK/V/+zX0Y+n7DoRUzyS8eMbVshVOLJTDDC+Qn9IJnilYbIKzpB9n4aBsg==", "cpu": [ "x64" ], @@ -1177,9 +905,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.17.tgz", - "integrity": "sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.8.tgz", + "integrity": "sha512-Jmzr3FA4S2tHhaC6yCjac3rGf7hG9R6Gf2z9i9JFcuyy0u79HfQsh/thifbYTF2ic82KJovKKkIB6Z9TdNhCXQ==", "cpu": [ "arm" ], @@ -1193,9 +921,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.17.tgz", - "integrity": "sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.8.tgz", + "integrity": "sha512-qq7jXtO1+UEtCmCeBBIRDrPFIVI4ilEQ97qgBGdwXAARrUqSn/L9fUrkb1XP/mvVtoVeR2bt/0L77xx53bPZ/Q==", "cpu": [ "arm64" ], @@ -1209,9 +937,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.17.tgz", - "integrity": "sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.8.tgz", + "integrity": "sha512-O6b8QesPbJCRshsNApsOIpzKt3ztG35gfX9tEf4arD7mwNinsoCKxkj8TgEE0YRjmjtO3r9FlJnT/ENd9EVefQ==", "cpu": [ "arm64" ], @@ -1225,9 +953,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.17.tgz", - "integrity": "sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.8.tgz", + "integrity": "sha512-32iEXX/pXwikshNOGnERAFwFSfiltmijMIAbUhnNyjFr3tmWmMJWQKU2vNcFX0DACSXJ3ZWcSkzNbaKTdngH6g==", "cpu": [ "x64" ], @@ -1241,9 +969,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.17.tgz", - "integrity": "sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.8.tgz", + "integrity": "sha512-s+VSSD+TfZeMEsCaFaHTaY5YNj3Dri8rST09gMvYQKwPphacRG7wbuQ5ZJMIJXN/puxPcg/nU+ucvWguPpvBDg==", "cpu": [ "x64" ], @@ -1257,9 +985,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.17.tgz", - "integrity": "sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.8.tgz", + "integrity": "sha512-CXBPVFkpDjM67sS1psWohZ6g/2/cd+cq56vPxK4JeawelxwK4YECgl9Y9TjkE2qfF+9/s1tHHJqrC4SS6cVvSg==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -1274,21 +1002,21 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.6.0", - "@emnapi/runtime": "^1.6.0", - "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.0.7", - "@tybys/wasm-util": "^0.10.1", - "tslib": "^2.4.0" + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@emnapi/wasi-threads": "^1.0.2", + "@napi-rs/wasm-runtime": "^0.2.10", + "@tybys/wasm-util": "^0.9.0", + "tslib": "^2.8.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.17.tgz", - "integrity": "sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.8.tgz", + "integrity": "sha512-7GmYk1n28teDHUjPlIx4Z6Z4hHEgvP5ZW2QS9ygnDAdI/myh3HTHjDqtSqgu1BpRoI4OiLx+fThAyA1JePoENA==", "cpu": [ "arm64" ], @@ -1302,9 +1030,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.17.tgz", - "integrity": "sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.8.tgz", + "integrity": "sha512-fou+U20j+Jl0EHwK92spoWISON2OBnCazIc038Xj2TdweYV33ZRkS9nwqiUi2d/Wba5xg5UoHfvynnb/UB49cQ==", "cpu": [ "x64" ], @@ -1318,17 +1046,17 @@ } }, "node_modules/@tailwindcss/vite": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.17.tgz", - "integrity": "sha512-4+9w8ZHOiGnpcGI6z1TVVfWaX/koK7fKeSYF3qlYg2xpBtbteP2ddBxiarL+HVgfSJGeK5RIxRQmKm4rTJJAwA==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.8.tgz", + "integrity": "sha512-CQ+I8yxNV5/6uGaJjiuymgw0kEQiNKRinYbZXPdx1fk5WgiyReG0VaUx/Xq6aVNSUNJFzxm6o8FNKS5aMaim5A==", "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.1.17", - "@tailwindcss/oxide": "4.1.17", - "tailwindcss": "4.1.17" + "@tailwindcss/node": "4.1.8", + "@tailwindcss/oxide": "4.1.8", + "tailwindcss": "4.1.8" }, "peerDependencies": { - "vite": "^5.2.0 || ^6 || ^7" + "vite": "^5.2.0 || ^6" } }, "node_modules/@tootallnate/quickjs-emscripten": { @@ -1338,19 +1066,19 @@ "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "license": "MIT" }, "node_modules/@types/node": { - "version": "24.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", - "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "version": "22.15.29", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.29.tgz", + "integrity": "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==", "license": "MIT", "optional": true, "dependencies": { - "undici-types": "~7.16.0" + "undici-types": "~6.21.0" } }, "node_modules/@types/yauzl": { @@ -1364,9 +1092,9 @@ } }, "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "license": "MIT", "engines": { "node": ">= 14" @@ -1421,9 +1149,9 @@ "license": "MIT" }, "node_modules/autoprefixer": { - "version": "10.4.22", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", - "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", "funding": [ { "type": "opencollective", @@ -1440,9 +1168,9 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.27.0", - "caniuse-lite": "^1.0.30001754", - "fraction.js": "^5.3.4", + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" @@ -1458,56 +1186,39 @@ } }, "node_modules/axios": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", - "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", + "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "node_modules/b4a": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", - "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", - "license": "Apache-2.0", - "peerDependencies": { - "react-native-b4a": "*" - }, - "peerDependenciesMeta": { - "react-native-b4a": { - "optional": true - } - } + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", + "license": "Apache-2.0" }, "node_modules/bare-events": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", - "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", + "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", "license": "Apache-2.0", - "peerDependencies": { - "bare-abort-controller": "*" - }, - "peerDependenciesMeta": { - "bare-abort-controller": { - "optional": true - } - } + "optional": true }, "node_modules/bare-fs": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.2.tgz", - "integrity": "sha512-veTnRzkb6aPHOvSKIOy60KzURfBdUflr5VReI+NSaPL6xf+XLdONQgZgpYvUuZLVQ8dCqxpBAudaOM1+KpAUxw==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.1.5.tgz", + "integrity": "sha512-1zccWBMypln0jEE05LzZt+V/8y8AQsQQqxtklqaIyg5nu6OAYFhZxPXinJTSG+kU5qyNmeLgcn9AW7eHiCHVLA==", "license": "Apache-2.0", "optional": true, "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", - "bare-stream": "^2.6.4", - "bare-url": "^2.2.2", - "fast-fifo": "^1.3.2" + "bare-stream": "^2.6.4" }, "engines": { "bare": ">=1.16.0" @@ -1522,9 +1233,9 @@ } }, "node_modules/bare-os": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.2.tgz", - "integrity": "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.1.tgz", + "integrity": "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==", "license": "Apache-2.0", "optional": true, "engines": { @@ -1542,9 +1253,9 @@ } }, "node_modules/bare-stream": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz", - "integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==", + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.5.tgz", + "integrity": "sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -1563,25 +1274,6 @@ } } }, - "node_modules/bare-url": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.3.2.tgz", - "integrity": "sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-path": "^3.0.0" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.3.tgz", - "integrity": "sha512-8QdH6czo+G7uBsNo0GiUfouPN1lRzKdJTGnKXwe12gkFbnnOUaUKGN55dMkfy+mnxmvjwl9zcI4VncczcVXDhA==", - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, "node_modules/basic-ftp": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", @@ -1592,9 +1284,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", "funding": [ { "type": "opencollective", @@ -1611,11 +1303,10 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" + "caniuse-lite": "^1.0.30001718", + "electron-to-chromium": "^1.5.160", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -1656,9 +1347,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001759", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", - "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", + "version": "1.0.30001720", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001720.tgz", + "integrity": "sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==", "funding": [ { "type": "opencollective", @@ -1703,10 +1394,19 @@ "node": ">=8" } }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/chromium-bidi": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-11.0.0.tgz", - "integrity": "sha512-cM3DI+OOb89T3wO8cpPSro80Q9eKYJ7hGVXoGS3GkDPxnYSqiv+6xwpIf6XERyJ9Tdsl09hmNmY94BkgZdVekw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-5.1.0.tgz", + "integrity": "sha512-9MSRhWRVoRPDG0TgzkHrshFSJJNZzfY5UFqUMuksg7zL1yoZIZ3jLB0YAgHclbiAxPI86pBnwDX1tbzoiV8aFw==", "license": "Apache-2.0", "dependencies": { "mitt": "^3.0.1", @@ -1730,21 +1430,6 @@ "node": ">=12" } }, - "node_modules/codemirror": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz", - "integrity": "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==", - "license": "MIT", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/commands": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/lint": "^6.0.0", - "@codemirror/search": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1776,17 +1461,18 @@ } }, "node_modules/concurrently": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz", - "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.1.2.tgz", + "integrity": "sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==", "license": "MIT", "dependencies": { - "chalk": "4.1.2", - "rxjs": "7.8.2", - "shell-quote": "1.8.3", - "supports-color": "8.1.1", - "tree-kill": "1.2.2", - "yargs": "17.7.2" + "chalk": "^4.1.2", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" }, "bin": { "conc": "dist/bin/concurrently.js", @@ -1825,12 +1511,6 @@ } } }, - "node_modules/crelt": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", - "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", - "license": "MIT" - }, "node_modules/data-uri-to-buffer": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", @@ -1841,9 +1521,9 @@ } }, "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1881,18 +1561,18 @@ } }, "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", "license": "Apache-2.0", "engines": { "node": ">=8" } }, "node_modules/devtools-protocol": { - "version": "0.0.1521046", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1521046.tgz", - "integrity": "sha512-vhE6eymDQSKWUXwwA37NtTTVEzjtGVfDr3pRbsWEQ5onH/Snp2c+2xZHWJJawG/0hCCJLRGt4xVtEVUVILol4w==", + "version": "0.0.1439962", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1439962.tgz", + "integrity": "sha512-jJF48UdryzKiWhJ1bLKr7BFWUQCEIT5uCNbDLqkQJBtkFxYzILJH44WN0PDKMIlGDN7Utb8vyUY85C3w4R/t2g==", "license": "BSD-3-Clause" }, "node_modules/dunder-proto": { @@ -1910,9 +1590,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.266", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.266.tgz", - "integrity": "sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==", + "version": "1.5.161", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.161.tgz", + "integrity": "sha512-hwtetwfKNZo/UlwHIVBlKZVdy7o8bIZxxKs0Mv/ROPiQQQmDgdm5a+KvKtBsxM8ZjFzTaCeLoodZ8jiBE3o9rA==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -1922,18 +1602,18 @@ "license": "MIT" }, "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "license": "MIT", "dependencies": { "once": "^1.4.0" } }, "node_modules/enhanced-resolve": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", - "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -1953,9 +1633,9 @@ } }, "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" @@ -2007,9 +1687,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -2019,32 +1699,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" } }, "node_modules/escalade": { @@ -2108,15 +1787,6 @@ "node": ">=0.10.0" } }, - "node_modules/events-universal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", - "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", - "license": "Apache-2.0", - "dependencies": { - "bare-events": "^2.7.0" - } - }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -2153,13 +1823,10 @@ } }, "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", + "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -2170,9 +1837,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", @@ -2190,15 +1857,14 @@ } }, "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -2206,15 +1872,15 @@ } }, "node_modules/fraction.js": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", - "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "license": "MIT", "engines": { "node": "*" }, "funding": { - "type": "github", + "type": "patreon", "url": "https://github.com/sponsors/rawify" } }, @@ -2303,9 +1969,9 @@ } }, "node_modules/get-uri": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", - "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", + "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", "license": "MIT", "dependencies": { "basic-ftp": "^5.0.2", @@ -2425,10 +2091,14 @@ } }, "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, "engines": { "node": ">= 12" } @@ -2449,9 +2119,9 @@ } }, "node_modules/jiti": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", - "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -2464,9 +2134,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -2475,6 +2145,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT" + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -2482,9 +2158,9 @@ "license": "MIT" }, "node_modules/laravel-vite-plugin": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-2.0.1.tgz", - "integrity": "sha512-zQuvzWfUKQu9oNVi1o0RZAJCwhGsdhx4NEOyrVQwJHaWDseGP9tl7XUPLY2T8Cj6+IrZ6lmyxlR1KC8unf3RLA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.2.0.tgz", + "integrity": "sha512-R0pJ+IcTVeqEMoKz/B2Ij57QVq3sFTABiFmb06gAwFdivbOgsUtuhX6N2MGLEArajrS3U5JbberzwOe7uXHMHQ==", "license": "MIT", "dependencies": { "picocolors": "^1.0.0", @@ -2494,16 +2170,16 @@ "clean-orphaned-assets": "bin/clean.js" }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "peerDependencies": { - "vite": "^7.0.0" + "vite": "^5.0.0 || ^6.0.0" } }, "node_modules/lightningcss": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", - "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" @@ -2516,43 +2192,22 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-android-arm64": "1.30.2", - "lightningcss-darwin-arm64": "1.30.2", - "lightningcss-darwin-x64": "1.30.2", - "lightningcss-freebsd-x64": "1.30.2", - "lightningcss-linux-arm-gnueabihf": "1.30.2", - "lightningcss-linux-arm64-gnu": "1.30.2", - "lightningcss-linux-arm64-musl": "1.30.2", - "lightningcss-linux-x64-gnu": "1.30.2", - "lightningcss-linux-x64-musl": "1.30.2", - "lightningcss-win32-arm64-msvc": "1.30.2", - "lightningcss-win32-x64-msvc": "1.30.2" - } - }, - "node_modules/lightningcss-android-arm64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", - "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", - "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", "cpu": [ "arm64" ], @@ -2570,9 +2225,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", - "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", "cpu": [ "x64" ], @@ -2590,9 +2245,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", - "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", "cpu": [ "x64" ], @@ -2610,9 +2265,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", - "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", "cpu": [ "arm" ], @@ -2630,9 +2285,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", - "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", "cpu": [ "arm64" ], @@ -2650,9 +2305,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", - "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", "cpu": [ "arm64" ], @@ -2670,9 +2325,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", - "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", "cpu": [ "x64" ], @@ -2690,9 +2345,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", - "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", "cpu": [ "x64" ], @@ -2710,9 +2365,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", - "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", "cpu": [ "arm64" ], @@ -2730,9 +2385,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", - "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", "cpu": [ "x64" ], @@ -2755,6 +2410,12 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, "node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -2765,12 +2426,12 @@ } }, "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/math-intrinsics": { @@ -2803,12 +2464,48 @@ "node": ">= 0.6" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "license": "MIT" }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2843,9 +2540,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "license": "MIT" }, "node_modules/normalize-range": { @@ -2941,9 +2638,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "license": "MIT", "engines": { "node": ">=12" @@ -2953,9 +2650,9 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", + "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", "funding": [ { "type": "opencollective", @@ -3021,9 +2718,9 @@ "license": "MIT" }, "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -3031,17 +2728,17 @@ } }, "node_modules/puppeteer": { - "version": "24.30.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.30.0.tgz", - "integrity": "sha512-A5OtCi9WpiXBQgJ2vQiZHSyrAzQmO/WDsvghqlN4kgw21PhxA5knHUaUQq/N3EMt8CcvSS0RM+kmYLJmedR3TQ==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.9.0.tgz", + "integrity": "sha512-L0pOtALIx8rgDt24Y+COm8X52v78gNtBOW6EmUcEPci0TYD72SAuaXKqasRIx4JXxmg2Tkw5ySKcpPOwN8xXnQ==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.10.13", - "chromium-bidi": "11.0.0", + "@puppeteer/browsers": "2.10.5", + "chromium-bidi": "5.1.0", "cosmiconfig": "^9.0.0", - "devtools-protocol": "0.0.1521046", - "puppeteer-core": "24.30.0", + "devtools-protocol": "0.0.1439962", + "puppeteer-core": "24.9.0", "typed-query-selector": "^2.12.0" }, "bin": { @@ -3052,18 +2749,17 @@ } }, "node_modules/puppeteer-core": { - "version": "24.30.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.30.0.tgz", - "integrity": "sha512-2S3Smy0t0W4wJnNvDe7W0bE7wDmZjfZ3ljfMgJd6hn2Hq/f0jgN+x9PULZo2U3fu5UUIJ+JP8cNUGllu8P91Pg==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.9.0.tgz", + "integrity": "sha512-HFdCeH/wx6QPz8EncafbCqJBqaCG1ENW75xg3cLFMRUoqZDgByT6HSueiumetT2uClZxwqj0qS4qMVZwLHRHHw==", "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.10.13", - "chromium-bidi": "11.0.0", - "debug": "^4.4.3", - "devtools-protocol": "0.0.1521046", + "@puppeteer/browsers": "2.10.5", + "chromium-bidi": "5.1.0", + "debug": "^4.4.1", + "devtools-protocol": "0.0.1439962", "typed-query-selector": "^2.12.0", - "webdriver-bidi-protocol": "0.3.8", - "ws": "^8.18.3" + "ws": "^8.18.2" }, "engines": { "node": ">=18" @@ -3088,12 +2784,12 @@ } }, "node_modules/rollup": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", - "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz", + "integrity": "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==", "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@types/estree": "1.0.7" }, "bin": { "rollup": "dist/bin/rollup" @@ -3103,35 +2799,33 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.3", - "@rollup/rollup-android-arm64": "4.53.3", - "@rollup/rollup-darwin-arm64": "4.53.3", - "@rollup/rollup-darwin-x64": "4.53.3", - "@rollup/rollup-freebsd-arm64": "4.53.3", - "@rollup/rollup-freebsd-x64": "4.53.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", - "@rollup/rollup-linux-arm-musleabihf": "4.53.3", - "@rollup/rollup-linux-arm64-gnu": "4.53.3", - "@rollup/rollup-linux-arm64-musl": "4.53.3", - "@rollup/rollup-linux-loong64-gnu": "4.53.3", - "@rollup/rollup-linux-ppc64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-musl": "4.53.3", - "@rollup/rollup-linux-s390x-gnu": "4.53.3", - "@rollup/rollup-linux-x64-gnu": "4.53.3", - "@rollup/rollup-linux-x64-musl": "4.53.3", - "@rollup/rollup-openharmony-arm64": "4.53.3", - "@rollup/rollup-win32-arm64-msvc": "4.53.3", - "@rollup/rollup-win32-ia32-msvc": "4.53.3", - "@rollup/rollup-win32-x64-gnu": "4.53.3", - "@rollup/rollup-win32-x64-msvc": "4.53.3", + "@rollup/rollup-android-arm-eabi": "4.41.1", + "@rollup/rollup-android-arm64": "4.41.1", + "@rollup/rollup-darwin-arm64": "4.41.1", + "@rollup/rollup-darwin-x64": "4.41.1", + "@rollup/rollup-freebsd-arm64": "4.41.1", + "@rollup/rollup-freebsd-x64": "4.41.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.41.1", + "@rollup/rollup-linux-arm-musleabihf": "4.41.1", + "@rollup/rollup-linux-arm64-gnu": "4.41.1", + "@rollup/rollup-linux-arm64-musl": "4.41.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.41.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.41.1", + "@rollup/rollup-linux-riscv64-gnu": "4.41.1", + "@rollup/rollup-linux-riscv64-musl": "4.41.1", + "@rollup/rollup-linux-s390x-gnu": "4.41.1", + "@rollup/rollup-linux-x64-gnu": "4.41.1", + "@rollup/rollup-linux-x64-musl": "4.41.1", + "@rollup/rollup-win32-arm64-msvc": "4.41.1", + "@rollup/rollup-win32-ia32-msvc": "4.41.1", + "@rollup/rollup-win32-x64-msvc": "4.41.1", "fsevents": "~2.3.2" } }, "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", - "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz", + "integrity": "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==", "cpu": [ "x64" ], @@ -3151,9 +2845,9 @@ } }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -3163,9 +2857,9 @@ } }, "node_modules/shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", + "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -3185,12 +2879,12 @@ } }, "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", + "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", "license": "MIT", "dependencies": { - "ip-address": "^10.0.1", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { @@ -3231,15 +2925,23 @@ "node": ">=0.10.0" } }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause" + }, "node_modules/streamx": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", - "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", + "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==", "license": "MIT", "dependencies": { - "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" } }, "node_modules/string-width": { @@ -3268,12 +2970,6 @@ "node": ">=8" } }, - "node_modules/style-mod": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", - "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", - "license": "MIT" - }, "node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -3290,28 +2986,41 @@ } }, "node_modules/tailwindcss": { - "version": "4.1.17", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.17.tgz", - "integrity": "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.8.tgz", + "integrity": "sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==", "license": "MIT" }, "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", "license": "MIT", "engines": { "node": ">=6" + } + }, + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "engines": { + "node": ">=18" } }, "node_modules/tar-fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", - "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.9.tgz", + "integrity": "sha512-XF4w9Xp+ZQgifKakjZYmFdkLoSWd34VGKcsTCwlNWM7QG3ZbaxnTsaBwnjFZqHRf/rROxaR8rXnbtwdvaDI+lA==", "license": "MIT", "dependencies": { "pump": "^3.0.0", @@ -3343,13 +3052,13 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "license": "MIT", "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "fdir": "^6.4.4", + "picomatch": "^4.0.2" }, "engines": { "node": ">=12.0.0" @@ -3380,16 +3089,16 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "license": "MIT", "optional": true }, "node_modules/update-browserslist-db": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", - "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "funding": [ { "type": "opencollective", @@ -3417,23 +3126,23 @@ } }, "node_modules/vite": { - "version": "7.2.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz", - "integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==", + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "license": "MIT", "dependencies": { "esbuild": "^0.25.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -3442,14 +3151,14 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", - "less": "^4.0.0", + "less": "*", "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" @@ -3512,18 +3221,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/w3c-keyname": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", - "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", - "license": "MIT" - }, - "node_modules/webdriver-bidi-protocol": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.3.8.tgz", - "integrity": "sha512-21Yi2GhGntMc671vNBCjiAeEVknXjVRoyu+k+9xOMShu+ZQfpGQwnBqbNz/Sv4GXZ6JmutlPAi2nIJcrymAWuQ==", - "license": "Apache-2.0" - }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -3548,9 +3245,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", + "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -3577,6 +3274,15 @@ "node": ">=10" } }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -3615,9 +3321,9 @@ } }, "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "version": "3.25.46", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.46.tgz", + "integrity": "sha512-IqRxcHEIjqLd4LNS/zKffB3Jzg3NwqJxQQ0Ns7pdrvgGkwQsEBdEQcOHaBVqvvZArShRzI39+aMST3FBGmTrLQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index 7262ad1..5073158 100644 --- a/package.json +++ b/package.json @@ -6,27 +6,14 @@ "dev": "vite" }, "dependencies": { - "@codemirror/commands": "^6.9.0", - "@codemirror/lang-css": "^6.3.1", - "@codemirror/lang-html": "^6.4.11", - "@codemirror/lang-javascript": "^6.2.4", - "@codemirror/lang-json": "^6.0.2", - "@codemirror/lang-liquid": "^6.3.0", - "@codemirror/language": "^6.11.3", - "@codemirror/search": "^6.5.11", - "@codemirror/state": "^6.5.2", - "@codemirror/theme-one-dark": "^6.1.3", - "@codemirror/view": "^6.38.5", - "@fsegurai/codemirror-theme-github-light": "^6.2.2", - "@tailwindcss/vite": "^4.1.11", + "@tailwindcss/vite": "^4.0.7", "autoprefixer": "^10.4.20", "axios": "^1.8.2", - "codemirror": "^6.0.2", "concurrently": "^9.0.1", - "laravel-vite-plugin": "^2.0", - "puppeteer": "24.30.0", + "laravel-vite-plugin": "^1.0", + "puppeteer": "^24.3.0", "tailwindcss": "^4.0.7", - "vite": "^7.0.4" + "vite": "^6.3" }, "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "4.9.5", diff --git a/public/mirror/assets/apple-touch-icon-120x120.png b/public/mirror/assets/apple-touch-icon-120x120.png deleted file mode 100644 index 5e51318..0000000 Binary files a/public/mirror/assets/apple-touch-icon-120x120.png and /dev/null differ diff --git a/public/mirror/assets/apple-touch-icon-152x152.png b/public/mirror/assets/apple-touch-icon-152x152.png deleted file mode 100644 index 9f8d9e3..0000000 Binary files a/public/mirror/assets/apple-touch-icon-152x152.png and /dev/null differ diff --git a/public/mirror/assets/apple-touch-icon-167x167.png b/public/mirror/assets/apple-touch-icon-167x167.png deleted file mode 100644 index 79d1211..0000000 Binary files a/public/mirror/assets/apple-touch-icon-167x167.png and /dev/null differ diff --git a/public/mirror/assets/apple-touch-icon-180x180.png b/public/mirror/assets/apple-touch-icon-180x180.png deleted file mode 100644 index 0499ff4..0000000 Binary files a/public/mirror/assets/apple-touch-icon-180x180.png and /dev/null differ diff --git a/public/mirror/assets/apple-touch-icon-76x76.png b/public/mirror/assets/apple-touch-icon-76x76.png deleted file mode 100644 index df3943a..0000000 Binary files a/public/mirror/assets/apple-touch-icon-76x76.png and /dev/null differ diff --git a/public/mirror/assets/favicon-16x16.png b/public/mirror/assets/favicon-16x16.png deleted file mode 100644 index b36f23b..0000000 Binary files a/public/mirror/assets/favicon-16x16.png and /dev/null differ diff --git a/public/mirror/assets/favicon-32x32.png b/public/mirror/assets/favicon-32x32.png deleted file mode 100644 index ae12e60..0000000 Binary files a/public/mirror/assets/favicon-32x32.png and /dev/null differ diff --git a/public/mirror/assets/favicon.ico b/public/mirror/assets/favicon.ico deleted file mode 100644 index da17cd5..0000000 Binary files a/public/mirror/assets/favicon.ico and /dev/null differ diff --git a/public/mirror/assets/logo--brand.svg b/public/mirror/assets/logo--brand.svg deleted file mode 100644 index 1b84f50..0000000 --- a/public/mirror/assets/logo--brand.svg +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/mirror/index.html b/public/mirror/index.html deleted file mode 100644 index 64746fe..0000000 --- a/public/mirror/index.html +++ /dev/null @@ -1,521 +0,0 @@ - - - - - - TRMNL BYOS Laravel Mirror - - - - - - - - - - - - - - - - - - - -
-
- - - -
- - - \ No newline at end of file diff --git a/public/mirror/manifest.json b/public/mirror/manifest.json deleted file mode 100644 index 4d44e44..0000000 --- a/public/mirror/manifest.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "TRMNL BYOS Laravel Mirror", - "short_name": "TRMNL BYOS", - "display": "standalone", - "background_color": "#ffffff", - "theme_color": "#ffffff" -} diff --git a/rector.php b/rector.php deleted file mode 100644 index dde2f14..0000000 --- a/rector.php +++ /dev/null @@ -1,26 +0,0 @@ -paths([ - __DIR__.'/app', - __DIR__.'/tests', - ]); - - $rectorConfig->sets([ - LevelSetList::UP_TO_PHP_82, - SetList::CODE_QUALITY, - SetList::DEAD_CODE, - SetList::EARLY_RETURN, - SetList::TYPE_DECLARATION, - ]); - - $rectorConfig->skip([ - // Skip any specific rules if needed - ]); -}; diff --git a/resources/css/app.css b/resources/css/app.css index de95b81..46b9ca1 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -59,10 +59,6 @@ @apply !mb-0 !leading-tight; } -[data-flux-description] a { - @apply text-accent underline hover:opacity-80; -} - input:focus[data-flux-control], textarea:focus[data-flux-control], select:focus[data-flux-control] { @@ -72,39 +68,3 @@ select:focus[data-flux-control] { /* \[:where(&)\]:size-4 { @apply size-4; } */ - -@layer components { - /* standard container for app */ - .styled-container, - .tab-button { - @apply rounded-xl border bg-white dark:bg-stone-950 dark:border-zinc-700 text-stone-800 shadow-xs; - } - - .tab-button { - @apply flex items-center gap-2 px-4 py-2 text-sm font-medium; - @apply rounded-b-none shadow-none bg-inherit; - - /* This makes the button sit slightly over the box border */ - margin-bottom: -1px; - position: relative; - z-index: 1; - } - - .tab-button.is-active { - @apply text-zinc-700 dark:text-zinc-300; - @apply border-b-white dark:border-b-zinc-800; - - /* Z-index 10 ensures the bottom border of the tab hides the top border of the box */ - z-index: 10; - } - - .tab-button:not(.is-active) { - @apply text-zinc-500 border-transparent; - } - - .tab-button:not(.is-active):hover { - @apply text-zinc-700 dark:text-zinc-300; - @apply border-zinc-300 dark:border-zinc-700; - cursor: pointer; - } -} diff --git a/resources/js/app.js b/resources/js/app.js index db3ebf3..e69de29 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -1,3 +0,0 @@ -import { codeEditorFormComponent } from './codemirror-alpine.js'; - -window.codeEditorFormComponent = codeEditorFormComponent; diff --git a/resources/js/codemirror-alpine.js b/resources/js/codemirror-alpine.js deleted file mode 100644 index 9ce12f1..0000000 --- a/resources/js/codemirror-alpine.js +++ /dev/null @@ -1,198 +0,0 @@ -import { createCodeMirror, getSystemTheme, watchThemeChange } from './codemirror-core.js'; -import { EditorView } from '@codemirror/view'; - -/** - * Alpine.js component for CodeMirror that integrates with textarea and Livewire - * Inspired by Filament's approach with proper state entanglement - * @param {Object} config - Configuration object - * @returns {Object} Alpine.js component object - */ -export function codeEditorFormComponent(config) { - return { - editor: null, - textarea: null, - isLoading: false, - unwatchTheme: null, - - // Configuration - isDisabled: config.isDisabled || false, - language: config.language || 'html', - state: config.state || '', - textareaId: config.textareaId || null, - - /** - * Initialize the component - */ - async init() { - this.isLoading = true; - - try { - // Wait for textarea if provided - if (this.textareaId) { - await this.waitForTextarea(); - } - - await this.$nextTick(); - this.createEditor(); - this.setupEventListeners(); - } finally { - this.isLoading = false; - } - }, - - /** - * Wait for textarea to be available in the DOM - */ - async waitForTextarea() { - let attempts = 0; - const maxAttempts = 50; // 5 seconds max wait - - while (attempts < maxAttempts) { - this.textarea = document.getElementById(this.textareaId); - if (this.textarea) { - return; - } - - // Wait 100ms before trying again - await new Promise(resolve => setTimeout(resolve, 100)); - attempts++; - } - - console.error(`Textarea with ID "${this.textareaId}" not found after ${maxAttempts} attempts`); - }, - - /** - * Update both Livewire state and textarea with new value - */ - updateState(value) { - this.state = value; - if (this.textarea) { - this.textarea.value = value; - this.textarea.dispatchEvent(new Event('input', { bubbles: true })); - } - }, - - /** - * Create the CodeMirror editor instance - */ - createEditor() { - // Clean up any existing editor first - if (this.editor) { - this.editor.destroy(); - } - - const effectiveTheme = this.getEffectiveTheme(); - const initialValue = this.textarea ? this.textarea.value : this.state; - - this.editor = createCodeMirror(this.$refs.editor, { - value: initialValue || '', - language: this.language, - theme: effectiveTheme, - readOnly: this.isDisabled, - onChange: (value) => this.updateState(value), - onUpdate: (value) => this.updateState(value), - onBlur: () => { - if (this.editor) { - this.updateState(this.editor.state.doc.toString()); - } - } - }); - }, - - /** - * Get effective theme - */ - getEffectiveTheme() { - return getSystemTheme(); - }, - - /** - * Update editor content with new value - */ - updateEditorContent(value) { - if (this.editor && value !== this.editor.state.doc.toString()) { - this.editor.dispatch({ - changes: { - from: 0, - to: this.editor.state.doc.length, - insert: value - } - }); - } - }, - - /** - * Setup event listeners for theme changes and state synchronization - */ - setupEventListeners() { - // Watch for state changes from Livewire - this.$watch('state', (newValue) => { - this.updateEditorContent(newValue); - }); - - // Watch for disabled state changes - this.$watch('isDisabled', (newValue) => { - if (this.editor) { - this.editor.dispatch({ - effects: EditorView.editable.reconfigure(!newValue) - }); - } - }); - - // Watch for textarea changes (from Livewire updates) - if (this.textarea) { - this.textarea.addEventListener('input', (event) => { - this.updateEditorContent(event.target.value); - this.state = event.target.value; - }); - - // Listen for Livewire updates that might change the textarea value - const observer = new MutationObserver((mutations) => { - mutations.forEach((mutation) => { - if (mutation.type === 'attributes' && mutation.attributeName === 'value') { - this.updateEditorContent(this.textarea.value); - this.state = this.textarea.value; - } - }); - }); - - observer.observe(this.textarea, { - attributes: true, - attributeFilter: ['value'] - }); - } - - // Listen for theme changes - this.unwatchTheme = watchThemeChange(() => { - this.recreateEditor(); - }); - }, - - /** - * Recreate the editor (useful for theme changes) - */ - async recreateEditor() { - if (this.editor) { - this.editor.destroy(); - this.editor = null; - await this.$nextTick(); - this.createEditor(); - } - }, - - - /** - * Clean up resources when component is destroyed - */ - destroy() { - if (this.editor) { - this.editor.destroy(); - this.editor = null; - } - if (this.unwatchTheme) { - this.unwatchTheme(); - } - } - }; -} - diff --git a/resources/js/codemirror-core.js b/resources/js/codemirror-core.js deleted file mode 100644 index f23389f..0000000 --- a/resources/js/codemirror-core.js +++ /dev/null @@ -1,265 +0,0 @@ -import { EditorView, lineNumbers, keymap } from '@codemirror/view'; -import { ViewPlugin } from '@codemirror/view'; -import { indentWithTab, selectAll } from '@codemirror/commands'; -import { foldGutter, foldKeymap } from '@codemirror/language'; -import { history, historyKeymap } from '@codemirror/commands'; -import { searchKeymap } from '@codemirror/search'; -import { html } from '@codemirror/lang-html'; -import { javascript } from '@codemirror/lang-javascript'; -import { json } from '@codemirror/lang-json'; -import { css } from '@codemirror/lang-css'; -import { liquid } from '@codemirror/lang-liquid'; -import { oneDark } from '@codemirror/theme-one-dark'; -import { githubLight } from '@fsegurai/codemirror-theme-github-light'; - -// Language support mapping -const LANGUAGE_MAP = { - 'javascript': javascript, - 'js': javascript, - 'json': json, - 'css': css, - 'liquid': liquid, - 'html': html, -}; - -// Theme support mapping -const THEME_MAP = { - 'light': githubLight, - 'dark': oneDark, -}; - -/** - * Get language support based on language parameter - * @param {string} language - Language name or comma-separated list - * @returns {Array|Extension} Language extension(s) - */ -function getLanguageSupport(language) { - // Handle comma-separated languages - if (language.includes(',')) { - const languages = language.split(',').map(lang => lang.trim().toLowerCase()); - const languageExtensions = []; - - languages.forEach(lang => { - const languageFn = LANGUAGE_MAP[lang]; - if (languageFn) { - languageExtensions.push(languageFn()); - } - }); - - return languageExtensions; - } - - // Handle single language - const languageFn = LANGUAGE_MAP[language.toLowerCase()] || LANGUAGE_MAP.html; - return languageFn(); -} - -/** - * Get theme support - * @param {string} theme - Theme name - * @returns {Array} Theme extensions - */ -function getThemeSupport(theme) { - const themeFn = THEME_MAP[theme] || THEME_MAP.light; - return [themeFn]; -} - -/** - * Create a resize plugin that handles container resizing - * @returns {ViewPlugin} Resize plugin - */ -function createResizePlugin() { - return ViewPlugin.fromClass(class { - constructor(view) { - this.view = view; - this.resizeObserver = null; - this.setupResizeObserver(); - } - - setupResizeObserver() { - const container = this.view.dom.parentElement; - if (container) { - this.resizeObserver = new ResizeObserver(() => { - // Use requestAnimationFrame to ensure proper timing - requestAnimationFrame(() => { - this.view.requestMeasure(); - }); - }); - this.resizeObserver.observe(container); - } - } - - destroy() { - if (this.resizeObserver) { - this.resizeObserver.disconnect(); - } - } - }); -} - -/** - * Get Flux-like theme styling based on theme - * @param {string} theme - Theme name ('light', 'dark', or 'auto') - * @returns {Object} Theme-specific styling - */ -function getFluxThemeStyling(theme) { - const isDark = theme === 'dark' || (theme === 'auto' && getSystemTheme() === 'dark'); - - if (isDark) { - return { - backgroundColor: 'oklab(0.999994 0.0000455678 0.0000200868 / 0.1)', - gutterBackgroundColor: 'oklch(26.9% 0 0)', - borderColor: '#374151', - focusBorderColor: 'rgb(224 91 68)', - }; - } else { - return { - backgroundColor: '#fff', // zinc-50 - gutterBackgroundColor: '#fafafa', // zinc-50 - borderColor: '#e5e7eb', // gray-200 - focusBorderColor: 'rgb(224 91 68)', // red-500 - }; - } -} - -/** - * Create CodeMirror editor instance - * @param {HTMLElement} element - DOM element to mount editor - * @param {Object} options - Editor options - * @returns {EditorView} CodeMirror editor instance - */ -export function createCodeMirror(element, options = {}) { - const { - value = '', - language = 'html', - theme = 'light', - readOnly = false, - onChange = () => {}, - onUpdate = () => {}, - onBlur = () => {} - } = options; - - // Get language and theme support - const languageSupport = getLanguageSupport(language); - const themeSupport = getThemeSupport(theme); - const fluxStyling = getFluxThemeStyling(theme); - - // Create editor - const editor = new EditorView({ - doc: value, - extensions: [ - lineNumbers(), - foldGutter(), - history(), - EditorView.lineWrapping, - createResizePlugin(), - ...(Array.isArray(languageSupport) ? languageSupport : [languageSupport]), - ...themeSupport, - keymap.of([ - indentWithTab, - ...foldKeymap, - ...historyKeymap, - ...searchKeymap, - { - key: 'Mod-a', - run: selectAll, - }, - ]), - EditorView.theme({ - '&': { - fontSize: '14px', - border: `1px solid ${fluxStyling.borderColor}`, - borderRadius: '0.375rem', - height: '100%', - maxHeight: '100%', - overflow: 'hidden', - backgroundColor: fluxStyling.backgroundColor + ' !important', - resize: 'vertical', - minHeight: '200px', - }, - '.cm-gutters': { - borderTopLeftRadius: '0.375rem', - backgroundColor: fluxStyling.gutterBackgroundColor + ' !important', - }, - '.cm-gutter': { - backgroundColor: fluxStyling.gutterBackgroundColor + ' !important', - }, - '&.cm-focused': { - outline: 'none', - borderColor: fluxStyling.focusBorderColor, - }, - '.cm-content': { - padding: '12px', - }, - '.cm-scroller': { - fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Monaco, Consolas, "Liberation Mono", "Courier New", monospace', - height: '100%', - overflow: 'auto', - }, - '.cm-editor': { - height: '100%', - }, - '.cm-editor .cm-scroller': { - height: '100%', - overflow: 'auto', - }, - '.cm-foldGutter': { - width: '12px', - }, - '.cm-foldGutter .cm-gutterElement': { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - cursor: 'pointer', - fontSize: '12px', - color: '#6b7280', - }, - '.cm-foldGutter .cm-gutterElement:hover': { - color: '#374151', - }, - '.cm-foldGutter .cm-gutterElement.cm-folded': { - color: '#3b82f6', - } - }), - EditorView.updateListener.of((update) => { - if (update.docChanged) { - const newValue = update.state.doc.toString(); - onChange(newValue); - onUpdate(newValue); - } - }), - EditorView.domEventHandlers({ - blur: onBlur - }), - EditorView.editable.of(!readOnly), - ], - parent: element - }); - - return editor; -} - -/** - * Auto-detect system theme preference - * @returns {string} 'dark' or 'light' - */ -export function getSystemTheme() { - if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { - return 'dark'; - } - return 'light'; -} - -/** - * Watch for system theme changes - * @param {Function} callback - Callback function when theme changes - * @returns {Function} Unwatch function - */ -export function watchThemeChange(callback) { - if (window.matchMedia) { - const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); - mediaQuery.addEventListener('change', callback); - return () => mediaQuery.removeEventListener('change', callback); - } - return () => {}; -} diff --git a/resources/views/components/action-message.blade.php b/resources/views/components/action-message.blade.php index d313ee6..db63acf 100644 --- a/resources/views/components/action-message.blade.php +++ b/resources/views/components/action-message.blade.php @@ -8,7 +8,7 @@ x-show.transition.out.opacity.duration.1500ms="shown" x-transition:leave.opacity.duration.1500ms style="display: none" - {{ $attributes->merge(['class' => 'text-sm']) }} + {{ $attributes->merge(['class' => 'text-sm text-gray-600']) }} > {{ $slot->isEmpty() ? __('Saved.') : $slot }}
diff --git a/resources/views/components/auth-header.blade.php b/resources/views/components/auth-header.blade.php index e596a3f..a68f69d 100644 --- a/resources/views/components/auth-header.blade.php +++ b/resources/views/components/auth-header.blade.php @@ -3,7 +3,7 @@ 'description', ]) -
- {{ $title }} - {{ $description }} +
+

{{ $title }}

+

{{ $description }}

diff --git a/resources/views/components/desktop-user-menu.blade.php b/resources/views/components/desktop-user-menu.blade.php deleted file mode 100644 index 5b386c5..0000000 --- a/resources/views/components/desktop-user-menu.blade.php +++ /dev/null @@ -1,39 +0,0 @@ - - only('name') }} - :initials="auth()->user()->initials()" - icon:trailing="chevrons-up-down" - data-test="sidebar-menu-button" - /> - - -
- -
- {{ auth()->user()->name }} - {{ auth()->user()->email }} -
-
- - - - {{ __('Settings') }} - -
- @csrf - - {{ __('Log Out') }} - -
-
-
-
diff --git a/resources/views/layouts/app.blade.php b/resources/views/components/layouts/app.blade.php similarity index 51% rename from resources/views/layouts/app.blade.php rename to resources/views/components/layouts/app.blade.php index e20d56b..ec0ebf7 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/components/layouts/app.blade.php @@ -1,5 +1,5 @@ - + {{ $slot }} - + diff --git a/resources/views/layouts/app/header.blade.php b/resources/views/components/layouts/app/header.blade.php similarity index 87% rename from resources/views/layouts/app/header.blade.php rename to resources/views/components/layouts/app/header.blade.php index 7a9f2c0..85eac00 100644 --- a/resources/views/layouts/app/header.blade.php +++ b/resources/views/components/layouts/app/header.blade.php @@ -4,8 +4,6 @@ @include('partials.head') - - @@ -68,8 +66,7 @@ - Settings - Support + Settings @@ -94,23 +91,23 @@ - + Dashboard - Devices - - + Plugins & Recipes - - + Playlists - + diff --git a/resources/views/components/layouts/app/sidebar.blade.php b/resources/views/components/layouts/app/sidebar.blade.php new file mode 100644 index 0000000..d0e913e --- /dev/null +++ b/resources/views/components/layouts/app/sidebar.blade.php @@ -0,0 +1,132 @@ + + + + @include('partials.head') + + + + + + + + + + + + Dashboard + + + + + + + + Repository + + + + Documentation + + + + + + + + + +
+
+ + + {{ auth()->user()->initials() }} + + + +
+ {{ auth()->user()->name }} + {{ auth()->user()->email }} +
+
+
+
+ + + + + Settings + + + + +
+ @csrf + + {{ __('Log Out') }} + +
+
+
+
+ + + + + + + + + + + + +
+
+ + + {{ auth()->user()->initials() }} + + + +
+ {{ auth()->user()->name }} + {{ auth()->user()->email }} +
+
+
+
+ + + + + Settings + + + + +
+ @csrf + + {{ __('Log Out') }} + +
+
+
+
+ + {{ $slot }} + + @fluxScripts + + diff --git a/resources/views/components/layouts/auth.blade.php b/resources/views/components/layouts/auth.blade.php new file mode 100644 index 0000000..4ddd14d --- /dev/null +++ b/resources/views/components/layouts/auth.blade.php @@ -0,0 +1,3 @@ + + {{ $slot }} + diff --git a/resources/views/layouts/auth/card.blade.php b/resources/views/components/layouts/auth/card.blade.php similarity index 95% rename from resources/views/layouts/auth/card.blade.php rename to resources/views/components/layouts/auth/card.blade.php index db94716..1a316ef 100644 --- a/resources/views/layouts/auth/card.blade.php +++ b/resources/views/components/layouts/auth/card.blade.php @@ -6,7 +6,7 @@
- + diff --git a/resources/views/layouts/auth/simple.blade.php b/resources/views/components/layouts/auth/simple.blade.php similarity index 95% rename from resources/views/layouts/auth/simple.blade.php rename to resources/views/components/layouts/auth/simple.blade.php index 6e0d909..9dbbe92 100644 --- a/resources/views/layouts/auth/simple.blade.php +++ b/resources/views/components/layouts/auth/simple.blade.php @@ -6,7 +6,7 @@
- + diff --git a/resources/views/layouts/auth/split.blade.php b/resources/views/components/layouts/auth/split.blade.php similarity index 80% rename from resources/views/layouts/auth/split.blade.php rename to resources/views/components/layouts/auth/split.blade.php index 4e9788b..e7b5c67 100644 --- a/resources/views/layouts/auth/split.blade.php +++ b/resources/views/components/layouts/auth/split.blade.php @@ -5,11 +5,11 @@
-