diff --git a/.gitignore b/.gitignore index aeeb3ff72..45e43f2ad 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ yarn-error.log /data /config/caddy /config/composer +/AGENTS.md diff --git a/app/Actions/Fortify/CreateNewUser.php b/app/Actions/Fortify/CreateNewUser.php index a66c0b4a7..3f1ae30f7 100644 --- a/app/Actions/Fortify/CreateNewUser.php +++ b/app/Actions/Fortify/CreateNewUser.php @@ -16,7 +16,6 @@ use Illuminate\Validation\ValidationException; use Korridor\LaravelModelValidationRules\Rules\UniqueEloquent; use Laravel\Fortify\Contracts\CreatesNewUsers; -use Laravel\Jetstream\Jetstream; use Log; class CreateNewUser implements CreatesNewUsers @@ -55,7 +54,7 @@ public function create(array $input): User }), ], 'password' => $this->passwordRules(), - 'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['accepted', 'required'] : '', + 'terms' => ['accepted', 'required'], 'newsletter_consent' => [ 'boolean', ], diff --git a/app/Actions/Fortify/UpdateUserProfileInformation.php b/app/Actions/Fortify/UpdateUserProfileInformation.php index ccc2a4967..eb3f53f3b 100644 --- a/app/Actions/Fortify/UpdateUserProfileInformation.php +++ b/app/Actions/Fortify/UpdateUserProfileInformation.php @@ -4,13 +4,9 @@ namespace App\Actions\Fortify; -use App\Enums\Weekday; +use App\Exceptions\MovedToApiException; use App\Models\User; -use Illuminate\Database\Eloquent\Builder; -use Illuminate\Support\Facades\Validator; -use Illuminate\Validation\Rule; use Illuminate\Validation\ValidationException; -use Korridor\LaravelModelValidationRules\Rules\UniqueEloquent; use Laravel\Fortify\Contracts\UpdatesUserProfileInformation; class UpdateUserProfileInformation implements UpdatesUserProfileInformation @@ -24,56 +20,6 @@ class UpdateUserProfileInformation implements UpdatesUserProfileInformation */ public function update(User $user, array $input): void { - Validator::make($input, [ - 'name' => [ - 'required', - 'string', - 'max:255', - ], - 'email' => [ - 'required', - 'email', - 'max:255', - UniqueEloquent::make(User::class, 'email')->ignore($user->id)->query(function (Builder $query) { - /** @var Builder $query */ - return $query->where('is_placeholder', '=', false); - }), - ], - 'photo' => [ - 'nullable', - 'mimes:jpg,jpeg,png', - 'max:1024', - ], - 'timezone' => [ - 'required', - 'timezone:all', - ], - 'week_start' => [ - 'required', - Rule::enum(Weekday::class), - ], - ])->validateWithBag('updateProfileInformation'); - - if (isset($input['photo'])) { - $user->updateProfilePhoto($input['photo']); - } - - if ($input['email'] !== $user->email) { - $user->forceFill([ - 'name' => $input['name'], - 'email' => $input['email'], - 'email_verified_at' => null, - 'timezone' => $input['timezone'], - 'week_start' => $input['week_start'], - ])->save(); - - $user->sendEmailVerificationNotification(); - } else { - $user->forceFill([ - 'name' => $input['name'], - 'timezone' => $input['timezone'], - 'week_start' => $input['week_start'], - ])->save(); - } + throw new MovedToApiException; } } diff --git a/app/Actions/Jetstream/AddOrganizationMember.php b/app/Actions/Jetstream/AddOrganizationMember.php deleted file mode 100644 index 7c8cc0f62..000000000 --- a/app/Actions/Jetstream/AddOrganizationMember.php +++ /dev/null @@ -1,94 +0,0 @@ -authorize('addTeamMember', $organization); // TODO: refactor after owner refactoring - - $this->validate($organization, $email, $role); - - $newOrganizationMember = User::query() - ->where('email', $email) - ->where('is_placeholder', '=', false) - ->firstOrFail(); - - app(MemberService::class)->addMember($newOrganizationMember, $organization, Role::from($role)); - } - - /** - * Validate the add member operation. - */ - protected function validate(Organization $organization, string $email, ?string $role): void - { - Validator::make([ - 'email' => $email, - 'role' => $role, - ], $this->rules())->after( - $this->ensureUserIsNotAlreadyOnTeam($organization, $email) - )->validateWithBag('addTeamMember'); - } - - /** - * Get the validation rules for adding a team member. - * - * @return array> - */ - protected function rules(): array - { - return [ - 'email' => [ - 'required', - 'email', - ExistsEloquent::make(User::class, 'email', function (Builder $builder) { - /** @var Builder $builder */ - return $builder->where('is_placeholder', '=', false); - })->withMessage(__('We were unable to find a registered user with this email address.')), - ], - 'role' => [ - 'required', - 'string', - Rule::in([ - Role::Admin->value, - Role::Manager->value, - Role::Employee->value, - ]), - ], - ]; - } - - /** - * Ensure that the user is not already on the team. - */ - protected function ensureUserIsNotAlreadyOnTeam(Organization $team, string $email): Closure - { - return function ($validator) use ($team, $email): void { - $validator->errors()->addIf( - $team->hasRealUserWithEmail($email), - 'email', - __('This user already belongs to the team.') - ); - }; - } -} diff --git a/app/Actions/Jetstream/CreateOrganization.php b/app/Actions/Jetstream/CreateOrganization.php deleted file mode 100644 index 13981abcf..000000000 --- a/app/Actions/Jetstream/CreateOrganization.php +++ /dev/null @@ -1,59 +0,0 @@ - $input - * - * @throws AuthorizationException - * @throws ValidationException - */ - public function create(User $user, array $input): Organization - { - Gate::forUser($user)->authorize('create', Jetstream::newTeamModel()); - - Validator::make($input, [ - 'name' => ['required', 'string', 'max:255'], - ])->validateWithBag('createTeam'); - - $ipLookupResponse = app(IpLookupServiceContract::class)->lookup(request()->ip()); - - $currency = null; - if ($ipLookupResponse !== null) { - $currency = $ipLookupResponse->currency; - } - - $organization = app(OrganizationService::class)->createOrganization( - $input['name'], - $user, - false, - $currency - ); - - $user->switchTeam($organization); - - // Note: The refresh is necessary for currently unknown reasons. Do not remove it. - $organization = $organization->refresh(); - AfterCreateOrganization::dispatch($organization); - - return $organization; - } -} diff --git a/app/Actions/Jetstream/DeleteOrganization.php b/app/Actions/Jetstream/DeleteOrganization.php deleted file mode 100644 index a33e62d17..000000000 --- a/app/Actions/Jetstream/DeleteOrganization.php +++ /dev/null @@ -1,21 +0,0 @@ -deleteOrganization($organization); - } -} diff --git a/app/Actions/Jetstream/DeleteUser.php b/app/Actions/Jetstream/DeleteUser.php deleted file mode 100644 index 4385b3f5f..000000000 --- a/app/Actions/Jetstream/DeleteUser.php +++ /dev/null @@ -1,30 +0,0 @@ -deleteUser($user); - } catch (ApiException $exception) { - throw ValidationException::withMessages([ - 'password' => $exception->getTranslatedMessage(), - ]); - } - } -} diff --git a/app/Actions/Jetstream/InviteOrganizationMember.php b/app/Actions/Jetstream/InviteOrganizationMember.php deleted file mode 100644 index 1fb7288e4..000000000 --- a/app/Actions/Jetstream/InviteOrganizationMember.php +++ /dev/null @@ -1,24 +0,0 @@ - $input - * - * @throws AuthorizationException - * @throws ValidationException - */ - public function update(User $user, Organization $organization, array $input): void - { - Gate::forUser($user)->authorize('update', $organization); - - Validator::make($input, [ - 'name' => [ - 'required', - 'string', - 'max:255', - ], - 'currency' => [ - 'required', - 'string', - new CurrencyRule, - ], - ])->validateWithBag('updateTeamName'); - - $organization->forceFill([ - 'name' => $input['name'], - 'currency' => $input['currency'], - ])->save(); - } -} diff --git a/app/Actions/Jetstream/ValidateOrganizationDeletion.php b/app/Actions/Jetstream/ValidateOrganizationDeletion.php deleted file mode 100644 index e9eb7abd6..000000000 --- a/app/Actions/Jetstream/ValidateOrganizationDeletion.php +++ /dev/null @@ -1,28 +0,0 @@ -userHas($organization, $user, 'organizations:delete')) { - throw new AuthorizationException; - } - } -} diff --git a/app/Console/Commands/Admin/UserCreateCommand.php b/app/Console/Commands/Admin/UserCreateCommand.php index 65b471fe0..43670d096 100644 --- a/app/Console/Commands/Admin/UserCreateCommand.php +++ b/app/Console/Commands/Admin/UserCreateCommand.php @@ -69,7 +69,7 @@ public function handle(): int ); }); /** @var Organization|null $organization */ - $organization = $user->ownedTeams->first(); + $organization = $user->ownedOrganizations->first(); if ($organization === null) { throw new LogicException('User does not have an organization'); } diff --git a/app/Enums/Role.php b/app/Enums/Role.php index e9ed774d0..d37e97c98 100644 --- a/app/Enums/Role.php +++ b/app/Enums/Role.php @@ -4,8 +4,12 @@ namespace App\Enums; +use Datomatic\LaravelEnumHelper\LaravelEnumHelper; + enum Role: string { + use LaravelEnumHelper; + case Owner = 'owner'; case Admin = 'admin'; case Manager = 'manager'; diff --git a/app/Events/MemberAdded.php b/app/Events/MemberAdded.php new file mode 100644 index 000000000..f7ab63b7f --- /dev/null +++ b/app/Events/MemberAdded.php @@ -0,0 +1,28 @@ +member = $member; + $this->organization = $organization; + $this->user = $user; + } +} diff --git a/app/Events/MemberAdding.php b/app/Events/MemberAdding.php new file mode 100644 index 000000000..3aea036d4 --- /dev/null +++ b/app/Events/MemberAdding.php @@ -0,0 +1,28 @@ +user = $user; + $this->organization = $organization; + $this->role = $role; + } +} diff --git a/app/Events/OrganizationInvitationAdding.php b/app/Events/OrganizationInvitationAdding.php new file mode 100644 index 000000000..52b8d5409 --- /dev/null +++ b/app/Events/OrganizationInvitationAdding.php @@ -0,0 +1,35 @@ +role = $role; + $this->email = $email; + $this->organization = $organization; + $this->inviter = $inviter; + } +} diff --git a/app/Exceptions/Api/UserResendEmailVerificationNoPendingEmailApiException.php b/app/Exceptions/Api/UserResendEmailVerificationNoPendingEmailApiException.php new file mode 100644 index 000000000..ef8d442ad --- /dev/null +++ b/app/Exceptions/Api/UserResendEmailVerificationNoPendingEmailApiException.php @@ -0,0 +1,10 @@ +disabled(), // make text a little bit smaller because often a complete Stack Trace is shown: - TextArea::make('exception')->disabled()->columnSpan(4)->extraInputAttributes(['style' => 'font-size: 80%;']), + Textarea::make('exception')->disabled()->columnSpan(4)->extraInputAttributes(['style' => 'font-size: 80%;']), PrettyJsonField::make('payload')->disabled()->columnSpan(4), ])->columns(4); } diff --git a/app/Filament/Resources/OrganizationInvitationResource.php b/app/Filament/Resources/OrganizationInvitationResource.php index 88ca23a56..c03a38115 100644 --- a/app/Filament/Resources/OrganizationInvitationResource.php +++ b/app/Filament/Resources/OrganizationInvitationResource.php @@ -39,7 +39,7 @@ public static function form(Form $form): Form ->required(), Select::make('role') ->options(Role::class), - Forms\Components\Select::make('organization_id') + Select::make('organization_id') ->label('Organization') ->relationship(name: 'organization', titleAttribute: 'name') ->searchable(['name']) diff --git a/app/Filament/Resources/OrganizationResource.php b/app/Filament/Resources/OrganizationResource.php index 040fa3023..460de0dca 100644 --- a/app/Filament/Resources/OrganizationResource.php +++ b/app/Filament/Resources/OrganizationResource.php @@ -55,7 +55,7 @@ public static function form(Form $form): Form ->label('Is personal?') ->hiddenOn(['create']) ->required(), - Forms\Components\Select::make('user_id') + Select::make('user_id') ->label('Owner') ->relationship(name: 'owner', titleAttribute: 'email') ->searchable(['name', 'email']) @@ -76,7 +76,7 @@ public static function form(Form $form): Form Select::make('time_format') ->options(TimeFormat::toSelectArray()) ->required(), - Forms\Components\Select::make('currency') + Select::make('currency') ->label('Currency') ->options(function (): array { $currencies = ISOCurrencyProvider::getInstance()->getAvailableCurrencies(); @@ -114,22 +114,22 @@ public static function table(Table $table): Table { return $table ->columns([ - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->searchable() ->sortable(), Tables\Columns\IconColumn::make('personal_team') ->boolean() ->label('Is personal?') ->sortable(), - Tables\Columns\TextColumn::make('owner.email') + TextColumn::make('owner.email') ->sortable(), - Tables\Columns\TextColumn::make('currency'), + TextColumn::make('currency'), TextColumn::make('billable_rate') ->money(fn (Organization $resource) => $resource->currency, divideBy: 100), - Tables\Columns\TextColumn::make('created_at') + TextColumn::make('created_at') ->dateTime() ->sortable(), - Tables\Columns\TextColumn::make('updated_at') + TextColumn::make('updated_at') ->dateTime() ->sortable() ->toggleable(isToggledHiddenByDefault: true), @@ -223,7 +223,7 @@ public static function table(Table $table): Table return $select; }), - Forms\Components\Select::make('timezone') + Select::make('timezone') ->label('Timezone') ->options(fn (): array => app(TimezoneService::class)->getSelectOptions()) ->searchable() diff --git a/app/Filament/Resources/OrganizationResource/RelationManagers/InvitationsRelationManager.php b/app/Filament/Resources/OrganizationResource/RelationManagers/InvitationsRelationManager.php index be5e7e5d4..a4cdaf471 100644 --- a/app/Filament/Resources/OrganizationResource/RelationManagers/InvitationsRelationManager.php +++ b/app/Filament/Resources/OrganizationResource/RelationManagers/InvitationsRelationManager.php @@ -21,7 +21,7 @@ class InvitationsRelationManager extends RelationManager { - protected static string $relationship = 'teamInvitations'; + protected static string $relationship = 'organizationInvitations'; protected static ?string $title = 'Invitations'; @@ -64,7 +64,7 @@ public function table(Table $table): Table $ownerRecord = $this->getOwnerRecord(); return app(InvitationService::class) - ->inviteUser($ownerRecord, $data['email'], Role::from($data['role'])); + ->inviteUser($ownerRecord, $data['email'], Role::from($data['role']), auth()->user()); }), ]) ->actions([ diff --git a/app/Filament/Resources/OrganizationResource/RelationManagers/UsersRelationManager.php b/app/Filament/Resources/OrganizationResource/RelationManagers/UsersRelationManager.php index d027d4dce..841ed6ae8 100644 --- a/app/Filament/Resources/OrganizationResource/RelationManagers/UsersRelationManager.php +++ b/app/Filament/Resources/OrganizationResource/RelationManagers/UsersRelationManager.php @@ -49,13 +49,13 @@ public function table(Table $table): Table return $table ->recordTitleAttribute('name') ->columns([ - Tables\Columns\TextColumn::make('name'), - Tables\Columns\TextColumn::make('role'), + TextColumn::make('name'), + TextColumn::make('role'), TextColumn::make('billable_rate') ->money($organization->currency, divideBy: 100), ]) ->headerActions([ - Tables\Actions\AttachAction::make() + AttachAction::make() ->recordTitle(fn (User $record): string => "{$record->name} ({$record->email})") ->form(fn (AttachAction $action): array => [ $action->getRecordSelect(), diff --git a/app/Filament/Resources/ReportResource.php b/app/Filament/Resources/ReportResource.php index b757e9fe0..6c3081e53 100644 --- a/app/Filament/Resources/ReportResource.php +++ b/app/Filament/Resources/ReportResource.php @@ -63,11 +63,11 @@ public static function form(Form $form): Form return $record->getRawOriginal('properties'); }) ->disabled(), - Forms\Components\DateTimePicker::make('created_at') + DateTimePicker::make('created_at') ->label('Created At') ->hiddenOn(['create']) ->disabled(), - Forms\Components\DateTimePicker::make('updated_at') + DateTimePicker::make('updated_at') ->label('Updated At') ->hiddenOn(['create']) ->disabled(), @@ -78,10 +78,10 @@ public static function table(Table $table): Table { return $table ->columns([ - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->searchable() ->sortable(), - Tables\Columns\TextColumn::make('description') + TextColumn::make('description') ->searchable() ->sortable(), ToggleColumn::make('is_public') @@ -90,10 +90,10 @@ public static function table(Table $table): Table TextColumn::make('organization.name') ->searchable() ->sortable(), - Tables\Columns\TextColumn::make('created_at') + TextColumn::make('created_at') ->dateTime() ->sortable(), - Tables\Columns\TextColumn::make('updated_at') + TextColumn::make('updated_at') ->dateTime() ->sortable() ->toggleable(isToggledHiddenByDefault: true), diff --git a/app/Filament/Resources/TimeEntryResource.php b/app/Filament/Resources/TimeEntryResource.php index c54a46786..53d459c70 100644 --- a/app/Filament/Resources/TimeEntryResource.php +++ b/app/Filament/Resources/TimeEntryResource.php @@ -93,11 +93,11 @@ public static function table(Table $table): Table ($record->end?->toDateTimeString('minute') ?? '...').')'; }) ->label('Time'), - Tables\Columns\TextColumn::make('organization.name') + TextColumn::make('organization.name') ->sortable(), - Tables\Columns\TextColumn::make('created_at') + TextColumn::make('created_at') ->sortable(), - Tables\Columns\TextColumn::make('updated_at') + TextColumn::make('updated_at') ->sortable(), ]) ->filters([ diff --git a/app/Filament/Resources/UserResource.php b/app/Filament/Resources/UserResource.php index c68dcf41c..cd96ed527 100644 --- a/app/Filament/Resources/UserResource.php +++ b/app/Filament/Resources/UserResource.php @@ -12,6 +12,7 @@ use App\Models\User; use App\Service\DeletionService; use App\Service\TimezoneService; +use App\Service\UserService; use Brick\Money\ISOCurrencyProvider; use Exception; use Filament\Forms; @@ -47,17 +48,17 @@ public static function form(Form $form): Form return $form ->columns(1) ->schema([ - Forms\Components\TextInput::make('id') + TextInput::make('id') ->label('ID') ->disabled() ->visibleOn(['update', 'show']) ->readOnly() ->maxLength(255), - Forms\Components\TextInput::make('name') + TextInput::make('name') ->label('Name') ->required() ->maxLength(255), - Forms\Components\TextInput::make('email') + TextInput::make('email') ->label('Email') ->required() ->rules($record?->is_placeholder ? [] : [ @@ -179,7 +180,7 @@ public static function table(Table $table): Table ]) ->actions([ Impersonate::make()->before(function (User $record): void { - if ($record->currentTeam === null) { + if ($record->currentOrganization === null) { $organization = $record->organizations()->where('personal_team', '=', true)->first(); if ($organization === null) { $organization = $record->organizations()->first(); @@ -187,8 +188,7 @@ public static function table(Table $table): Table if ($organization === null) { throw new Exception('User has no organization'); } - $record->currentTeam()->associate($organization); - $record->save(); + app(UserService::class)->switchCurrentOrganization($record, $organization); } }), Tables\Actions\EditAction::make(), diff --git a/app/Filament/Resources/UserResource/RelationManagers/OwnedOrganizationsRelationManager.php b/app/Filament/Resources/UserResource/RelationManagers/OwnedOrganizationsRelationManager.php index 07c593c2f..c348c3dc7 100644 --- a/app/Filament/Resources/UserResource/RelationManagers/OwnedOrganizationsRelationManager.php +++ b/app/Filament/Resources/UserResource/RelationManagers/OwnedOrganizationsRelationManager.php @@ -16,7 +16,7 @@ class OwnedOrganizationsRelationManager extends RelationManager { protected static ?string $title = 'Owned Organizations'; - protected static string $relationship = 'ownedTeams'; + protected static string $relationship = 'ownedOrganizations'; public function form(Form $form): Form { diff --git a/app/Http/Controllers/Api/V1/ApiTokenController.php b/app/Http/Controllers/Api/V1/ApiTokenController.php index 1fbf12d80..4cbb3cc9b 100644 --- a/app/Http/Controllers/Api/V1/ApiTokenController.php +++ b/app/Http/Controllers/Api/V1/ApiTokenController.php @@ -20,7 +20,7 @@ class ApiTokenController extends Controller /** * List all api token of the currently authenticated user * - * This endpoint is independent of organization. + * This endpoint is independent of the organization. * * @operationId getApiTokens * diff --git a/app/Http/Controllers/Api/V1/InvitationController.php b/app/Http/Controllers/Api/V1/InvitationController.php index 4e7a0dcdc..fe7d6b903 100644 --- a/app/Http/Controllers/Api/V1/InvitationController.php +++ b/app/Http/Controllers/Api/V1/InvitationController.php @@ -40,7 +40,7 @@ public function index(Organization $organization, InvitationIndexRequest $reques { $this->checkPermission($organization, 'invitations:view'); - $invitations = $organization->teamInvitations() + $invitations = $organization->organizationInvitations() ->orderBy('created_at', 'desc') ->paginate(config('app.pagination_per_page_default')); @@ -63,7 +63,7 @@ public function store(Organization $organization, InvitationStoreRequest $reques $email = $request->getEmail(); $role = $request->getRole(); - $invitationService->inviteUser($organization, $email, $role); + $invitationService->inviteUser($organization, $email, $role, $this->user()); return response()->json(null, 204); } diff --git a/app/Http/Controllers/Api/V1/MemberController.php b/app/Http/Controllers/Api/V1/MemberController.php index 6dde1b6e4..cd699cfdc 100644 --- a/app/Http/Controllers/Api/V1/MemberController.php +++ b/app/Http/Controllers/Api/V1/MemberController.php @@ -192,7 +192,7 @@ public function invitePlaceholder(Organization $organization, Member $member, In throw new ThisPlaceholderCanNotBeInvitedUseTheMergeToolInsteadException; } - $invitationService->inviteUser($organization, $user->email, Role::Employee); + $invitationService->inviteUser($organization, $user->email, Role::Employee, $this->user()); return response()->json(null, 204); } diff --git a/app/Http/Controllers/Api/V1/OrganizationController.php b/app/Http/Controllers/Api/V1/OrganizationController.php index 4475acc12..2d8e327d6 100644 --- a/app/Http/Controllers/Api/V1/OrganizationController.php +++ b/app/Http/Controllers/Api/V1/OrganizationController.php @@ -5,11 +5,18 @@ namespace App\Http\Controllers\Api\V1; use App\Enums\Role; +use App\Events\AfterCreateOrganization; +use App\Http\Requests\V1\Organization\OrganizationStoreRequest; use App\Http\Requests\V1\Organization\OrganizationUpdateRequest; use App\Http\Resources\V1\Organization\OrganizationResource; use App\Models\Organization; use App\Service\BillableRateService; +use App\Service\DeletionService; +use App\Service\IpLookup\IpLookupServiceContract; +use App\Service\OrganizationService; +use App\Service\UserService; use Illuminate\Auth\Access\AuthorizationException; +use Illuminate\Http\JsonResponse; class OrganizationController extends Controller { @@ -43,6 +50,9 @@ public function update(Organization $organization, OrganizationUpdateRequest $re if ($request->getName() !== null) { $organization->name = $request->getName(); } + if ($request->getCurrency() !== null) { + $organization->currency = $request->getCurrency(); + } if ($request->getEmployeesCanSeeBillableRates() !== null) { $organization->employees_can_see_billable_rates = $request->getEmployeesCanSeeBillableRates(); } @@ -80,4 +90,46 @@ public function update(Organization $organization, OrganizationUpdateRequest $re return new OrganizationResource($organization, true); } + + /** + * Create organization + * + * @operationId createOrganization + */ + public function store(OrganizationStoreRequest $request, OrganizationService $organizationService): OrganizationResource + { + $user = $this->user(); + $ipLookupResponse = app(IpLookupServiceContract::class)->lookup($request->ip()); + + $currency = $ipLookupResponse?->currency; + + $organization = $organizationService->createOrganization( + $request->getName(), + $user, + false, + $currency + ); + + app(UserService::class)->switchCurrentOrganization($user, $organization); + + AfterCreateOrganization::dispatch($organization); + + return new OrganizationResource($organization, true); + } + + /** + * Delete organization + * + * @operationId deleteOrganization + * + * @throws AuthorizationException + */ + public function destroy(Organization $organization, DeletionService $deletionService): JsonResponse + { + $this->checkPermission($organization, 'organizations:delete'); + + $deletionService->deleteOrganization($organization); + + return response()->json(null, 204); + } } diff --git a/app/Http/Controllers/Api/V1/TimeEntryController.php b/app/Http/Controllers/Api/V1/TimeEntryController.php index 07fc62cfd..4dad185ba 100644 --- a/app/Http/Controllers/Api/V1/TimeEntryController.php +++ b/app/Http/Controllers/Api/V1/TimeEntryController.php @@ -59,7 +59,7 @@ class TimeEntryController extends Controller { - private function assertNoOverlap(Organization $organization, Member $member, \Illuminate\Support\Carbon $start, ?\Illuminate\Support\Carbon $end, ?TimeEntry $exclude = null): void + private function assertNoOverlap(Organization $organization, Member $member, Carbon $start, ?Carbon $end, ?TimeEntry $exclude = null): void { if (! $organization->prevent_overlapping_time_entries) { return; diff --git a/app/Http/Controllers/Api/V1/TimeZoneController.php b/app/Http/Controllers/Api/V1/TimeZoneController.php new file mode 100644 index 000000000..d921e2691 --- /dev/null +++ b/app/Http/Controllers/Api/V1/TimeZoneController.php @@ -0,0 +1,33 @@ +getTimezones(); + + $response = []; + + foreach ($timezones as $timezone) { + $response[] = (object) [ + 'key' => $timezone, + ]; + } + + return response()->json($response); + } +} diff --git a/app/Http/Controllers/Api/V1/UserController.php b/app/Http/Controllers/Api/V1/UserController.php index d4338916f..b8d3fc422 100644 --- a/app/Http/Controllers/Api/V1/UserController.php +++ b/app/Http/Controllers/Api/V1/UserController.php @@ -4,15 +4,29 @@ namespace App\Http\Controllers\Api\V1; +use App\Exceptions\Api\CanNotDeleteUserWhoIsOwnerOfOrganizationWithMultipleMembers; +use App\Exceptions\Api\UserResendEmailVerificationNoPendingEmailApiException; +use App\Http\Requests\V1\User\UserUpdateCurrentOrganizationRequest; +use App\Http\Requests\V1\User\UserUpdateRequest; use App\Http\Resources\V1\User\UserResource; +use App\Mail\VerifyUpdatedEmailMail; +use App\Models\Organization; +use App\Models\User; +use App\Service\DeletionService; +use App\Service\UserService; +use App\Support\Base64File; use Illuminate\Auth\Access\AuthorizationException; +use Illuminate\Http\JsonResponse; +use Illuminate\Support\Facades\Mail; +use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Str; class UserController extends Controller { /** * Get the current user * - * This endpoint is independent of organization. + * This endpoint is independent of the organization. * * @operationId getMe * @@ -24,4 +38,169 @@ public function me(): UserResource return new UserResource($user); } + + /** + * Update the current organization of the current user + * + * Switches the organization that the user is currently working in. The user + * must be a member of the given organization. This endpoint is independent of + * the organization. + * + * @operationId updateMyCurrentOrganization + * + * @throws AuthorizationException + */ + public function updateMyCurrentOrganization(UserUpdateCurrentOrganizationRequest $request, UserService $userService): UserResource + { + $user = $this->user(); + + /** @var Organization|null $organization */ + $organization = $user->organizations() + ->whereKey($request->getOrganizationId()) + ->first(); + + if ($organization === null) { + throw new AuthorizationException; + } + + $userService->switchCurrentOrganization($user, $organization); + + return new UserResource($user->refresh()); + } + + /** + * Update the current user + * + * This endpoint is independent of the organization. + * + * @operationId updateUser + */ + public function update(User $user, UserUpdateRequest $request): UserResource + { + if ($user->getKey() !== $this->user()->getKey()) { + throw new AuthorizationException; + } + + if ($request->hasPhotoKey()) { + $photoDisk = (string) config('filesystems.public'); + $previousPhotoPath = $user->profile_photo_path; + $newPhoto = $request->getPhoto(); + + if ($newPhoto === null) { + $user->profile_photo_path = null; + } else { + $decoded = Base64File::decode($newPhoto); + assert($decoded !== null); + $extension = Base64File::extension($decoded['mime_type']); + assert($extension !== null); + + $photoPath = 'profile-photos/'.Str::uuid().'.'.$extension; + Storage::disk($photoDisk)->put($photoPath, $decoded['data'], 'public'); + $user->profile_photo_path = $photoPath; + } + + if ($previousPhotoPath !== null) { + Storage::disk($photoDisk)->delete($previousPhotoPath); + } + } + + $emailToVerify = null; + $email = $request->getEmail(); + if ($email !== null && $email !== Str::lower($user->email)) { + $emailToVerify = $email; + $user->pending_email = $email; + } + + if ($request->getName() !== null) { + $user->name = $request->getName(); + } + + if ($request->getTimezone() !== null) { + $user->timezone = $request->getTimezone(); + } + + if ($request->getWeekStart() !== null) { + $user->week_start = $request->getWeekStart(); + } + + $user->save(); + + if ($emailToVerify !== null) { + Mail::to($emailToVerify)->send(new VerifyUpdatedEmailMail($user, $emailToVerify)); + } + + return new UserResource($user); + } + + /** + * Reset the pending email for a user. + * + * This endpoint is independent of the organization. + * + * @operationId resetUserPendingEmail + * + * @throws AuthorizationException Thrown when the authenticated user does not match the user whose email is pending verification. + */ + public function resetPendingEmail(User $user): JsonResponse + { + if ($user->getKey() !== $this->user()->getKey()) { + throw new AuthorizationException; + } + + $user->pending_email = null; + $user->save(); + + return response()->json(null, 204); + } + + /** + * Resend the pending email update verification email. + * + * This endpoint is independent of the organization. + * + * @operationId resendUserEmailVerification + * + * @throws AuthorizationException Thrown when the authenticated user does not match the user whose email is pending verification. + * @throws UserResendEmailVerificationNoPendingEmailApiException Thrown when the user does not have a pending email to verify. + */ + public function resendEmailVerification(User $user): JsonResponse + { + if ($user->getKey() !== $this->user()->getKey()) { + throw new AuthorizationException; + } + + if ($user->pending_email === null) { + throw new UserResendEmailVerificationNoPendingEmailApiException; + } + + Mail::to($user->pending_email) + ->queue(new VerifyUpdatedEmailMail($user, $user->pending_email)); + + return response()->json(null, 204); + } + + /** + * Handles the deletion of a user. + * + * This endpoint is independent of the organization. + * + * @operationId deleteUser + * + * @param User $user The user instance to be deleted. + * @param DeletionService $deletionService The service responsible for performing the user deletion. + * @return JsonResponse A JSON response with a 204 No Content status upon successful deletion. + * + * @throws AuthorizationException Thrown when the authenticated user does not match the user to be deleted. + * @throws CanNotDeleteUserWhoIsOwnerOfOrganizationWithMultipleMembers Thrown when the user to be deleted is the owner of an organization with multiple members. + */ + public function destroy(User $user, DeletionService $deletionService): JsonResponse + { + if ($user->getKey() !== $this->user()->getKey()) { + throw new AuthorizationException; + } + + $deletionService->deleteUser($user); + + return response()->json(null, 204); + } } diff --git a/app/Http/Controllers/Api/V1/UserMembershipController.php b/app/Http/Controllers/Api/V1/UserMembershipController.php index ea7a92a38..e1bb0ad00 100644 --- a/app/Http/Controllers/Api/V1/UserMembershipController.php +++ b/app/Http/Controllers/Api/V1/UserMembershipController.php @@ -14,7 +14,7 @@ class UserMembershipController extends Controller /** * Get the memberships of the current user * - * This endpoint is independent of organization. + * This endpoint is independent of the organization. * * @operationId getMyMemberships * diff --git a/app/Http/Controllers/Api/V1/UserTimeEntryController.php b/app/Http/Controllers/Api/V1/UserTimeEntryController.php index 7c69fce4d..79cefecc5 100644 --- a/app/Http/Controllers/Api/V1/UserTimeEntryController.php +++ b/app/Http/Controllers/Api/V1/UserTimeEntryController.php @@ -17,7 +17,7 @@ class UserTimeEntryController extends Controller /** * Get the active time entry of the current user * - * This endpoint is independent of organization. + * This endpoint is independent of the organization. * * @operationId getMyActiveTimeEntry */ diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 96fda0200..bba772801 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -59,7 +59,7 @@ protected function member(Organization $organization): Member protected function currentOrganization(): Organization { $user = $this->user(); - $organization = $user->currentTeam; + $organization = $user->currentOrganization; if ($organization === null) { $organization = $user->organizations()->first(); } diff --git a/app/Http/Controllers/Web/Controller.php b/app/Http/Controllers/Web/Controller.php index 03c287257..111996cc6 100644 --- a/app/Http/Controllers/Web/Controller.php +++ b/app/Http/Controllers/Web/Controller.php @@ -4,4 +4,21 @@ namespace App\Http\Controllers\Web; -abstract class Controller extends \App\Http\Controllers\Controller {} +use App\Models\Organization; +use App\Service\PermissionStore; +use Illuminate\Auth\Access\AuthorizationException; + +abstract class Controller extends \App\Http\Controllers\Controller +{ + public function __construct( + protected PermissionStore $permissionStore, + ) {} + + /** + * @throws AuthorizationException + */ + protected function hasPermission(Organization $organization, string $permission): bool + { + return $this->permissionStore->has($organization, $permission); + } +} diff --git a/app/Http/Controllers/Web/DashboardController.php b/app/Http/Controllers/Web/DashboardController.php index ccb4c15a7..d29472434 100644 --- a/app/Http/Controllers/Web/DashboardController.php +++ b/app/Http/Controllers/Web/DashboardController.php @@ -4,30 +4,13 @@ namespace App\Http\Controllers\Web; -use App\Enums\Role; -use App\Service\DashboardService; -use App\Service\PermissionStore; -use Illuminate\Auth\Access\AuthorizationException; use Inertia\Inertia; use Inertia\Response; class DashboardController extends Controller { - /** - * @throws AuthorizationException - */ - public function dashboard(DashboardService $dashboardService, PermissionStore $permissionStore): Response + public function dashboard(): Response { - $user = $this->user(); - $organization = $this->currentOrganization(); - - $latestTeamActivity = null; - if ($permissionStore->has($organization, 'time-entries:view:all')) { - $latestTeamActivity = $dashboardService->latestTeamActivity($organization); - } - - $showBillableRate = $this->member($organization)->role !== Role::Employee->value || $organization->employees_can_see_billable_rates; - return Inertia::render('Dashboard'); } } diff --git a/app/Http/Controllers/Web/OrganizationController.php b/app/Http/Controllers/Web/OrganizationController.php new file mode 100644 index 000000000..7969eb829 --- /dev/null +++ b/app/Http/Controllers/Web/OrganizationController.php @@ -0,0 +1,63 @@ +route('dashboard'); + } + if (! $this->hasPermission($organization, 'organizations:view')) { + return redirect()->route('dashboard'); + } + + $owner = $organization->owner; + + return Inertia::render('Teams/Show', [ + 'team' => [ + 'id' => $organization->getKey(), + 'name' => $organization->name, + 'currency' => $organization->currency, + 'owner' => [ + 'id' => $owner->getKey(), + 'name' => $owner->name, + 'profile_photo_url' => $owner->profile_photo_url, + ], + ], + 'currencies' => array_map(function (Currency $currency): string { + return $currency->getName(); + }, ISOCurrencyProvider::getInstance()->getAvailableCurrencies()), + 'permissions' => [ + 'canDeleteTeam' => $this->hasPermission($organization, 'organizations:delete'), + 'canUpdateTeam' => $this->hasPermission($organization, 'organizations:update'), + ], + ]); + } +} diff --git a/app/Http/Controllers/Web/OrganizationInvitationController.php b/app/Http/Controllers/Web/OrganizationInvitationController.php new file mode 100644 index 000000000..8d6e65816 --- /dev/null +++ b/app/Http/Controllers/Web/OrganizationInvitationController.php @@ -0,0 +1,75 @@ +email); + $role = Role::tryFrom($invitation->role); + if ($role === null || $role === Role::Owner || $role === Role::Placeholder) { + throw new RuntimeException('Invalid role'); + } + + $organization = $invitation->organization; + $invitee = User::query() + ->where('email', $email) + ->where('is_placeholder', '=', false) + ->first(); + + // No account yet — finish on registration. + if ($invitee === null) { + if ($invitation->accepted_at === null) { + $invitation->accepted_at = now(); + $invitation->save(); + } + + return redirect(route('register')) + ->with('bannerText', __('Please create an account to finish joining the :organization organization.', [ + 'organization' => $organization->name, + ])) + ->with('bannerStyle', 'info'); + } + + $alreadyMember = $memberService->isEmailAlreadyMember($organization, $email); + if (! $alreadyMember) { + $memberService->addMember($invitee, $organization, $role); + $invitation->delete(); + } + + // Logged out — banner on /login. + if (! Auth::check()) { + return redirect(route('login')) + ->with('bannerText', __('Great! You have accepted the invitation to join the :organization organization. Please log in to access it.', [ + 'organization' => $organization->name, + ])) + ->with('bannerStyle', 'success'); + } + + // Logged in — banner on /dashboard. + if ($alreadyMember) { + return redirect(route('dashboard')) + ->with('bannerText', __('You are already a member of the :organization organization.', [ + 'organization' => $organization->name, + ])) + ->with('bannerStyle', 'danger'); + } + + return redirect(route('dashboard')) + ->with('bannerText', __('Great! You have accepted the invitation to join the :organization organization.', [ + 'organization' => $organization->name, + ])) + ->with('bannerStyle', 'success'); + } +} diff --git a/app/Http/Controllers/Web/OtherBrowserSessionsController.php b/app/Http/Controllers/Web/OtherBrowserSessionsController.php new file mode 100644 index 000000000..0ad71ce73 --- /dev/null +++ b/app/Http/Controllers/Web/OtherBrowserSessionsController.php @@ -0,0 +1,54 @@ +string('password'); + + $confirmed = app(ConfirmPassword::class)($guard, $request->user(), $password); + + if (! $confirmed) { + throw ValidationException::withMessages([ + 'password' => __('The password is incorrect.'), + ]); + } + + $guard->logoutOtherDevices($password); + + $this->deleteOtherSessionRecords($request); + + return back(303); + } + + /** + * Delete the other browser session records from storage. + */ + protected function deleteOtherSessionRecords(Request $request): void + { + if (config('session.driver') !== 'database') { + return; + } + + DB::connection(config('session.connection')) + ->table(config('session.table', 'sessions')) + ->where('user_id', $request->user()->getAuthIdentifier()) + ->where('id', '!=', $request->session()->getId()) + ->delete(); + } +} diff --git a/app/Http/Controllers/Web/UserController.php b/app/Http/Controllers/Web/UserController.php new file mode 100644 index 000000000..0b4009857 --- /dev/null +++ b/app/Http/Controllers/Web/UserController.php @@ -0,0 +1,53 @@ +user()?->getAuthIdentifier() !== $user->getKey()) { + abort(403); + } + + $email = $request->query('email'); + if (! is_string($email)) { + abort(403); + } + + $email = Str::lower($email); + + if ($user->pending_email !== $email) { + abort(403); + } + + $emailAlreadyInUse = User::query() + ->where('email', '=', $email) + ->where('is_placeholder', '=', false) + ->whereKeyNot($user->getKey()) + ->exists(); + + if ($emailAlreadyInUse) { + return redirect(route('dashboard')) + ->with('bannerStyle', 'danger') + ->with('bannerText', __('The email address is already in use.')); + } + + $user->email = $email; + $user->pending_email = null; + $user->email_verified_at = Carbon::now(); + $user->save(); + + return redirect(route('dashboard')) + ->with('bannerStyle', 'success') + ->with('bannerText', __('Your email address has been updated successfully.')); + } +} diff --git a/app/Http/Controllers/Web/UserProfileController.php b/app/Http/Controllers/Web/UserProfileController.php new file mode 100644 index 000000000..a247b842e --- /dev/null +++ b/app/Http/Controllers/Web/UserProfileController.php @@ -0,0 +1,142 @@ +twoFactorAuthenticationDisabled($request)) { + $request->session()->put('two_factor_empty_at', $currentTime); + } + + // If was previously totally disabled this session but is now confirming, notate time... + if ($this->hasJustBegunConfirmingTwoFactorAuthentication($request)) { + $request->session()->put('two_factor_confirming_at', $currentTime); + } + + // If the profile is reloaded and is not confirmed but was previously in confirming state, disable... + if ($this->neverFinishedConfirmingTwoFactorAuthentication($request, $currentTime)) { + app(DisableTwoFactorAuthentication::class)(Auth::user()); + + $request->session()->put('two_factor_empty_at', $currentTime); + $request->session()->remove('two_factor_confirming_at'); + } + } + + /** + * Determine if two-factor authentication is totally disabled. + * + * @return bool + */ + protected function twoFactorAuthenticationDisabled(Request $request) + { + return is_null($request->user()->two_factor_secret) && + is_null($request->user()->two_factor_confirmed_at); + } + + /** + * Determine if two-factor authentication is just now being confirmed within the last request cycle. + * + * @return bool + */ + protected function hasJustBegunConfirmingTwoFactorAuthentication(Request $request) + { + return ! is_null($request->user()->two_factor_secret) && + is_null($request->user()->two_factor_confirmed_at) && + $request->session()->has('two_factor_empty_at') && + is_null($request->session()->get('two_factor_confirming_at')); + } + + /** + * Determine if two-factor authentication was never totally confirmed once confirmation started. + * + * @return bool + */ + protected function neverFinishedConfirmingTwoFactorAuthentication(Request $request, int $currentTime) + { + return ! array_key_exists('code', $request->session()->getOldInput()) && + is_null($request->user()->two_factor_confirmed_at) && + $request->session()->get('two_factor_confirming_at', 0) !== $currentTime; + } + + /** + * Show the general profile settings screen. + */ + public function show(Request $request): Response + { + $this->validateTwoFactorAuthenticationState($request); + + return Inertia::render('Profile/Show', [ + 'timezones' => app(TimezoneService::class)->getSelectOptions(), + 'weekdays' => Weekday::toSelectArray(), + 'confirmsTwoFactorAuthentication' => Features::optionEnabled(Features::twoFactorAuthentication(), 'confirm'), + 'sessions' => $this->sessions($request), + ]); + } + + /** + * Get the current sessions. + * + * @return array + */ + public function sessions(Request $request): array + { + if (config('session.driver') !== 'database') { + return []; + } + + return collect( + DB::connection(config('session.connection'))->table(config('session.table', 'sessions')) + ->where('user_id', $request->user()->getAuthIdentifier()) + ->orderBy('last_activity', 'desc') + ->get() + )->map(function (object $session) use ($request): object { + $agent = $this->createAgent(is_string($session->user_agent) ? $session->user_agent : ''); + + return (object) [ + 'agent' => [ + 'is_desktop' => $agent->isDesktop(), + 'platform' => $agent->platform(), + 'browser' => $agent->browser(), + ], + 'ip_address' => is_string($session->ip_address) ? $session->ip_address : '', + 'is_current_device' => $session->id === $request->session()->getId(), + 'last_active' => Carbon::createFromTimestamp($session->last_activity)->diffForHumans(), + ]; + })->all(); + } + + /** + * Create a new agent instance from the given session. + */ + protected function createAgent(string $userAgent): UserAgentDto + { + return tap(new UserAgentDto, fn ($agent) => $agent->setUserAgent($userAgent)); + } +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 236acc795..4d9af16b1 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -4,9 +4,37 @@ namespace App\Http; +use App\Http\Middleware\Authenticate; use App\Http\Middleware\CheckOrganizationBlocked; +use App\Http\Middleware\EncryptCookies; +use App\Http\Middleware\EnsureEmailIsVerified; +use App\Http\Middleware\ForceHttps; use App\Http\Middleware\ForceJsonResponse; +use App\Http\Middleware\HandleInertiaRequests; +use App\Http\Middleware\PreventRequestsDuringMaintenance; +use App\Http\Middleware\RedirectIfAuthenticated; +use App\Http\Middleware\ShareInertiaData; +use App\Http\Middleware\TrimStrings; +use App\Http\Middleware\TrustProxies; +use App\Http\Middleware\ValidateSignature; +use App\Http\Middleware\VerifyCsrfToken; +use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth; +use Illuminate\Auth\Middleware\Authorize; +use Illuminate\Auth\Middleware\RequirePassword; +use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; use Illuminate\Foundation\Http\Kernel as HttpKernel; +use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull; +use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests; +use Illuminate\Foundation\Http\Middleware\ValidatePostSize; +use Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets; +use Illuminate\Http\Middleware\HandleCors; +use Illuminate\Http\Middleware\SetCacheHeaders; +use Illuminate\Routing\Middleware\SubstituteBindings; +use Illuminate\Routing\Middleware\ThrottleRequests; +use Illuminate\Session\Middleware\AuthenticateSession; +use Illuminate\Session\Middleware\StartSession; +use Illuminate\View\Middleware\ShareErrorsFromSession; +use Laravel\Passport\Http\Middleware\CreateFreshApiToken; class Kernel extends HttpKernel { @@ -18,13 +46,13 @@ class Kernel extends HttpKernel * @var array */ protected $middleware = [ - \App\Http\Middleware\ForceHttps::class, - \App\Http\Middleware\TrustProxies::class, - \Illuminate\Http\Middleware\HandleCors::class, - \App\Http\Middleware\PreventRequestsDuringMaintenance::class, - \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, - \App\Http\Middleware\TrimStrings::class, - \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, + ForceHttps::class, + TrustProxies::class, + HandleCors::class, + PreventRequestsDuringMaintenance::class, + ValidatePostSize::class, + TrimStrings::class, + ConvertEmptyStringsToNull::class, ]; /** @@ -34,21 +62,21 @@ class Kernel extends HttpKernel */ protected $middlewareGroups = [ 'web' => [ - \App\Http\Middleware\EncryptCookies::class, - \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, - \Illuminate\Session\Middleware\StartSession::class, - \Illuminate\View\Middleware\ShareErrorsFromSession::class, - \App\Http\Middleware\VerifyCsrfToken::class, - \Illuminate\Routing\Middleware\SubstituteBindings::class, - \App\Http\Middleware\HandleInertiaRequests::class, - \App\Http\Middleware\ShareInertiaData::class, - \Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets::class, - \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class, + EncryptCookies::class, + AddQueuedCookiesToResponse::class, + StartSession::class, + ShareErrorsFromSession::class, + VerifyCsrfToken::class, + SubstituteBindings::class, + HandleInertiaRequests::class, + ShareInertiaData::class, + AddLinkHeadersForPreloadedAssets::class, + CreateFreshApiToken::class, ], 'api' => [ - \Illuminate\Routing\Middleware\ThrottleRequests::class.':api', - \Illuminate\Routing\Middleware\SubstituteBindings::class, + ThrottleRequests::class.':api', + SubstituteBindings::class, ForceJsonResponse::class, ], @@ -64,17 +92,17 @@ class Kernel extends HttpKernel * @var array */ protected $middlewareAliases = [ - 'auth' => \App\Http\Middleware\Authenticate::class, - 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, - 'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class, - 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, - 'can' => \Illuminate\Auth\Middleware\Authorize::class, - 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, - 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, - 'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class, - 'signed' => \App\Http\Middleware\ValidateSignature::class, - 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, - 'verified' => \App\Http\Middleware\EnsureEmailIsVerified::class, + 'auth' => Authenticate::class, + 'auth.basic' => AuthenticateWithBasicAuth::class, + 'auth.session' => AuthenticateSession::class, + 'cache.headers' => SetCacheHeaders::class, + 'can' => Authorize::class, + 'guest' => RedirectIfAuthenticated::class, + 'password.confirm' => RequirePassword::class, + 'precognitive' => HandlePrecognitiveRequests::class, + 'signed' => ValidateSignature::class, + 'throttle' => ThrottleRequests::class, + 'verified' => EnsureEmailIsVerified::class, 'check-organization-blocked' => CheckOrganizationBlocked::class, ]; } diff --git a/app/Http/Middleware/ForceHttps.php b/app/Http/Middleware/ForceHttps.php index 2b23e3152..072924113 100644 --- a/app/Http/Middleware/ForceHttps.php +++ b/app/Http/Middleware/ForceHttps.php @@ -14,7 +14,7 @@ class ForceHttps /** * Handle an incoming request. * - * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next + * @param Closure(Request): (Response) $next */ public function handle(Request $request, Closure $next, string ...$guards): Response { diff --git a/app/Http/Middleware/ForceJsonResponse.php b/app/Http/Middleware/ForceJsonResponse.php index bae7216cc..f3f27d301 100644 --- a/app/Http/Middleware/ForceJsonResponse.php +++ b/app/Http/Middleware/ForceJsonResponse.php @@ -13,7 +13,7 @@ class ForceJsonResponse /** * Handle an incoming request. * - * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next + * @param Closure(Request): (Response) $next */ public function handle(Request $request, Closure $next, string ...$guards): Response { diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 0c2f1265b..a27bacf8b 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -46,7 +46,7 @@ public function share(Request $request): array /** @var BillingContract $billing */ $billing = app(BillingContract::class); - $currentOrganization = $request->user()?->currentTeam; + $currentOrganization = $request->user()?->currentOrganization; return array_merge(parent::share($request), [ 'has_billing_extension' => $hasBilling, @@ -60,6 +60,8 @@ public function share(Request $request): array ] : null, 'flash' => [ 'message' => fn () => $request->session()->get('message'), + 'bannerText' => fn () => $request->session()->get('bannerText'), + 'bannerStyle' => fn () => $request->session()->get('bannerStyle'), ], ]); } diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index 67666da3a..8c37fae33 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -15,7 +15,7 @@ class RedirectIfAuthenticated /** * Handle an incoming request. * - * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next + * @param Closure(Request): (Response) $next */ public function handle(Request $request, Closure $next, string ...$guards): Response { diff --git a/app/Http/Middleware/ShareInertiaData.php b/app/Http/Middleware/ShareInertiaData.php index b37a5c5a3..cdf8c223f 100644 --- a/app/Http/Middleware/ShareInertiaData.php +++ b/app/Http/Middleware/ShareInertiaData.php @@ -9,12 +9,10 @@ use App\Service\PermissionStore; use Closure; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Session; use Illuminate\Support\MessageBag; use Inertia\Inertia; use Laravel\Fortify\Features; -use Laravel\Jetstream\Jetstream; use Symfony\Component\HttpFoundation\Response; class ShareInertiaData @@ -27,28 +25,8 @@ public function handle(Request $request, Closure $next): Response /** @var PermissionStore $permissions */ $permissions = app(PermissionStore::class); Inertia::share([ - 'jetstream' => function () use ($request) { - /** @var User|null $user */ - $user = $request->user(); - - return [ - 'canCreateTeams' => $user !== null && - Jetstream::userHasTeamFeatures($user) && - Gate::forUser($user)->check('create', Jetstream::newTeamModel()), - 'canManageTwoFactorAuthentication' => Features::canManageTwoFactorAuthentication(), - 'canUpdatePassword' => Features::enabled(Features::updatePasswords()), - 'canUpdateProfileInformation' => Features::canUpdateProfileInformation(), - 'hasEmailVerification' => Features::enabled(Features::emailVerification()), - 'flash' => $request->session()->get('flash', []), - 'hasAccountDeletionFeatures' => Jetstream::hasAccountDeletionFeatures(), - 'hasApiFeatures' => Jetstream::hasApiFeatures(), - 'hasTeamFeatures' => Jetstream::hasTeamFeatures(), - 'hasTermsAndPrivacyPolicyFeature' => Jetstream::hasTermsAndPrivacyPolicyFeature(), - 'managesProfilePhotos' => Jetstream::managesProfilePhotos(), - ]; - }, 'auth' => [ - 'permissions' => $request->user() !== null && $request->user()->currentTeam !== null ? $permissions->getPermissions($request->user()->currentTeam) : [], + 'permissions' => $request->user() !== null && $request->user()->currentOrganization !== null ? $permissions->getPermissions($request->user()->currentOrganization) : [], 'user' => function () use ($request): array { /** @var User|null $user */ $user = $request->user(); @@ -57,6 +35,8 @@ public function handle(Request $request, Closure $next): Response return []; } + $currentOrganization = $user->currentOrganization; + return array_merge([ 'id' => $user->id, 'name' => $user->name, @@ -69,12 +49,12 @@ public function handle(Request $request, Closure $next): Response 'profile_photo_url' => $user->profile_photo_url, 'two_factor_enabled' => Features::enabled(Features::twoFactorAuthentication()) && ! is_null($user->two_factor_secret), - 'current_team' => $user->currentTeam !== null ? [ - 'id' => $user->currentTeam->id, - 'user_id' => $user->currentTeam->user_id, - 'name' => $user->currentTeam->name, - 'personal_team' => $user->currentTeam->personal_team, - 'currency' => $user->currentTeam->currency, + 'current_team' => $currentOrganization !== null ? [ + 'id' => $currentOrganization->id, + 'user_id' => $currentOrganization->user_id, + 'name' => $currentOrganization->name, + 'personal_team' => $currentOrganization->personal_team, + 'currency' => $currentOrganization->currency, ] : null, ], array_filter([ 'all_teams' => $user->organizations->map(function (Organization $organization): array { diff --git a/app/Http/Requests/V1/Member/MemberMergeIntoRequest.php b/app/Http/Requests/V1/Member/MemberMergeIntoRequest.php index cf63ae280..409c3bb21 100644 --- a/app/Http/Requests/V1/Member/MemberMergeIntoRequest.php +++ b/app/Http/Requests/V1/Member/MemberMergeIntoRequest.php @@ -7,6 +7,7 @@ use App\Http\Requests\V1\BaseFormRequest; use App\Models\Member; use App\Models\Organization; +use Illuminate\Contracts\Validation\Rule; use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Database\Eloquent\Builder; use Korridor\LaravelModelValidationRules\Rules\ExistsEloquent; @@ -19,7 +20,7 @@ class MemberMergeIntoRequest extends BaseFormRequest /** * Get the validation rules that apply to the request. * - * @return array> + * @return array> */ public function rules(): array { diff --git a/app/Http/Requests/V1/Organization/OrganizationStoreRequest.php b/app/Http/Requests/V1/Organization/OrganizationStoreRequest.php new file mode 100644 index 000000000..021a9f774 --- /dev/null +++ b/app/Http/Requests/V1/Organization/OrganizationStoreRequest.php @@ -0,0 +1,36 @@ +> + */ + public function rules(): array + { + return [ + 'name' => [ + 'required', + 'string', + 'max:255', + ], + ]; + } + + public function getName(): string + { + return (string) $this->input('name'); + } +} diff --git a/app/Http/Requests/V1/Organization/OrganizationUpdateRequest.php b/app/Http/Requests/V1/Organization/OrganizationUpdateRequest.php index 4def93fe1..f9ff12034 100644 --- a/app/Http/Requests/V1/Organization/OrganizationUpdateRequest.php +++ b/app/Http/Requests/V1/Organization/OrganizationUpdateRequest.php @@ -11,6 +11,7 @@ use App\Enums\TimeFormat; use App\Http\Requests\V1\BaseFormRequest; use App\Models\Organization; +use App\Rules\CurrencyRule; use Illuminate\Validation\Rule; /** @@ -21,7 +22,7 @@ class OrganizationUpdateRequest extends BaseFormRequest /** * Get the validation rules that apply to the request. * - * @return array> + * @return array> */ public function rules(): array { @@ -30,6 +31,10 @@ public function rules(): array 'string', 'max:255', ], + 'currency' => [ + 'string', + new CurrencyRule, + ], 'billable_rate' => array_merge( [ 'nullable', @@ -68,6 +73,11 @@ public function getName(): ?string return $this->has('name') ? (string) $this->input('name') : null; } + public function getCurrency(): ?string + { + return $this->has('currency') ? (string) $this->input('currency') : null; + } + public function getNumberFormat(): ?NumberFormat { return $this->has('number_format') ? NumberFormat::from($this->input('number_format')) : null; diff --git a/app/Http/Requests/V1/User/UserUpdateCurrentOrganizationRequest.php b/app/Http/Requests/V1/User/UserUpdateCurrentOrganizationRequest.php new file mode 100644 index 000000000..9bc6e481b --- /dev/null +++ b/app/Http/Requests/V1/User/UserUpdateCurrentOrganizationRequest.php @@ -0,0 +1,32 @@ +> + */ + public function rules(): array + { + return [ + 'organization_id' => [ + 'required', + 'string', + 'uuid', + ], + ]; + } + + public function getOrganizationId(): string + { + return (string) $this->input('organization_id'); + } +} diff --git a/app/Http/Requests/V1/User/UserUpdateRequest.php b/app/Http/Requests/V1/User/UserUpdateRequest.php new file mode 100644 index 000000000..caff56092 --- /dev/null +++ b/app/Http/Requests/V1/User/UserUpdateRequest.php @@ -0,0 +1,95 @@ +has('email') && is_string($this->input('email'))) { + $this->merge([ + 'email' => Str::lower((string) $this->input('email')), + ]); + } + } + + /** + * Get the validation rules that apply to the request. + * + * @return array> + */ + public function rules(): array + { + return [ + 'name' => [ + 'string', + 'max:255', + ], + 'email' => [ + 'email', + 'max:255', + UniqueEloquent::make(User::class, 'email')->ignore($this->user->id)->query(function (Builder $query) { + /** @var Builder $query */ + return $query->where('is_placeholder', '=', false); + }), + ], + 'photo' => [ + 'nullable', + new Base64ImageRule, + ], + 'timezone' => [ + 'timezone:all', + ], + 'week_start' => [ + Rule::enum(Weekday::class), + ], + ]; + } + + public function getName(): ?string + { + return $this->has('name') ? (string) $this->input('name') : null; + } + + public function getEmail(): ?string + { + return $this->has('email') ? Str::lower((string) $this->input('email')) : null; + } + + public function getTimezone(): ?string + { + return $this->has('timezone') ? (string) $this->input('timezone') : null; + } + + public function getWeekStart(): ?Weekday + { + return $this->has('week_start') ? Weekday::from($this->input('week_start')) : null; + } + + public function hasPhotoKey(): bool + { + return $this->has('photo'); + } + + public function getPhoto(): ?string + { + $value = $this->input('photo'); + + return is_string($value) ? $value : null; + } +} diff --git a/app/Http/Resources/V1/User/UserResource.php b/app/Http/Resources/V1/User/UserResource.php index ad2525c11..675380d3d 100644 --- a/app/Http/Resources/V1/User/UserResource.php +++ b/app/Http/Resources/V1/User/UserResource.php @@ -28,6 +28,8 @@ public function toArray(Request $request): array 'name' => $this->resource->name, /** @var string $email Email of user */ 'email' => $this->resource->email, + /** @var string|null $pending_email Email address awaiting verification (set when the user has requested an email change but not yet verified the new address) */ + 'pending_email' => $this->resource->pending_email, /** @var string $profile_photo_url Profile photo URL */ 'profile_photo_url' => $this->resource->profile_photo_url, /** @var string $timezone Timezone (f.e. Europe/Berlin or America/New_York) */ diff --git a/app/Listeners/RemovePlaceholder.php b/app/Listeners/RemovePlaceholder.php deleted file mode 100644 index 4b932db3e..000000000 --- a/app/Listeners/RemovePlaceholder.php +++ /dev/null @@ -1,43 +0,0 @@ -whereBelongsTo($event->team, 'organization') - ->whereBelongsTo($event->user, 'user') - ->firstOrFail(); - $placeholders = Member::query() - ->whereHas('user', function (Builder $query) use ($event): void { - /** @var Builder $query */ - $query->where('is_placeholder', '=', true) - ->where('email', '=', $event->user->email); - }) - ->whereBelongsTo($event->team, 'organization') - ->with(['user']) - ->get(); - - foreach ($placeholders as $placeholder) { - /** @var Member $placeholder */ - $placeholderUser = $placeholder->user; - $memberService->assignOrganizationEntitiesToDifferentMember($event->team, $placeholder, $member); - $placeholder->delete(); - $placeholderUser->delete(); - } - } -} diff --git a/app/Mail/OrganizationInvitationMail.php b/app/Mail/OrganizationInvitationMail.php index 8a8dfa8da..211505005 100644 --- a/app/Mail/OrganizationInvitationMail.php +++ b/app/Mail/OrganizationInvitationMail.php @@ -8,6 +8,7 @@ use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Carbon; use Illuminate\Support\Facades\URL; class OrganizationInvitationMail extends Mailable @@ -32,9 +33,12 @@ public function __construct(OrganizationInvitation $invitation) public function build(): self { return $this->markdown('emails.organization-invitation', [ - 'acceptUrl' => URL::signedRoute('team-invitations.accept', [ - 'invitation' => $this->invitation, - ]), + 'acceptUrl' => URL::to(URL::signedRoute( + 'organization-invitations.accept', + ['invitation' => $this->invitation->getKey()], + Carbon::now()->addDays(90), + false + )), ])->subject(__('Organization Invitation')); } } diff --git a/app/Mail/VerifyUpdatedEmailMail.php b/app/Mail/VerifyUpdatedEmailMail.php new file mode 100644 index 000000000..76552a194 --- /dev/null +++ b/app/Mail/VerifyUpdatedEmailMail.php @@ -0,0 +1,48 @@ +user = $user; + $this->email = Str::lower($email); + } + + /** + * Build the message. + */ + public function build(): self + { + $verificationUrl = URL::temporarySignedRoute( + 'users.verify-email-change', + Carbon::now()->addMinutes((int) config('auth.verification.expire', 60)), + [ + 'user' => $this->user->getKey(), + 'email' => $this->email, + ], + false + ); + + return $this->markdown('emails.verify-updated-email', [ + 'verificationUrl' => URL::to($verificationUrl), + ])->subject(__('Verify Email Address')); + } +} diff --git a/app/Models/Member.php b/app/Models/Member.php index 4bca11255..e8af33e44 100644 --- a/app/Models/Member.php +++ b/app/Models/Member.php @@ -9,10 +9,11 @@ use Database\Factories\MemberFactory; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\Pivot; use Illuminate\Support\Carbon; -use Laravel\Jetstream\Membership as JetstreamMembership; use OwenIt\Auditing\Contracts\Auditable as AuditableContract; /** @@ -30,7 +31,7 @@ * * @method static MemberFactory factory() */ -class Member extends JetstreamMembership implements AuditableContract +class Member extends Pivot implements AuditableContract { use CustomAuditable; diff --git a/app/Models/Organization.php b/app/Models/Organization.php index 3cfab262e..c5250e909 100644 --- a/app/Models/Organization.php +++ b/app/Models/Organization.php @@ -14,6 +14,7 @@ use Database\Factories\OrganizationFactory; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; @@ -21,10 +22,6 @@ use Illuminate\Database\Eloquent\Relations\Pivot; use Illuminate\Support\Carbon; use Illuminate\Support\Str; -use Laravel\Jetstream\Events\TeamCreated; -use Laravel\Jetstream\Events\TeamDeleted; -use Laravel\Jetstream\Events\TeamUpdated; -use Laravel\Jetstream\Team as JetstreamTeam; use OwenIt\Auditing\Contracts\Auditable as AuditableContract; /** @@ -36,12 +33,13 @@ * @property string $user_id * @property bool $employees_can_see_billable_rates * @property bool $employees_can_manage_tasks + * @property bool $prevent_overlapping_time_entries * @property User $owner * @property Carbon|null $created_at * @property Carbon|null $updated_at * @property Collection $users * @property Collection $realUsers - * @property-read Collection $teamInvitations + * @property-read Collection $organizationInvitations * @property Member $membership * @property NumberFormat $number_format * @property CurrencyFormat $currency_format @@ -49,10 +47,9 @@ * @property IntervalFormat $interval_format * @property TimeFormat $time_format * - * @method HasMany teamInvitations() * @method static OrganizationFactory factory() */ -class Organization extends JetstreamTeam implements AuditableContract +class Organization extends Model implements AuditableContract { use CustomAuditable; @@ -90,17 +87,6 @@ class Organization extends JetstreamTeam implements AuditableContract 'personal_team', ]; - /** - * The event map for the model. - * - * @var array - */ - protected $dispatchesEvents = [ - 'created' => TeamCreated::class, - 'updated' => TeamUpdated::class, - 'deleted' => TeamDeleted::class, - ]; - /** * The model's default values for attributes. * @@ -109,23 +95,6 @@ class Organization extends JetstreamTeam implements AuditableContract protected $attributes = [ ]; - /** - * Get all the non-placeholder users of the organization including its owner. - * - * @return Collection - */ - public function allRealUsers(): Collection - { - return $this->realUsers->merge([$this->owner]); - } - - public function hasRealUserWithEmail(string $email): bool - { - return $this->allRealUsers()->contains(function (User $user) use ($email): bool { - return $user->email === $email; - }); - } - /** * Get all the users that belong to the team. * @@ -171,12 +140,21 @@ public function realUsers(): BelongsToMany } /** - * This method prevents an unhandled exception when the ID is not a UUID. - * Normally this can be fixed with a route pattern, but Jetstream does not use route model binding. + * @return HasMany + */ + public function organizationInvitations(): HasMany + { + return $this->hasMany(OrganizationInvitation::class, 'organization_id'); + } + + /** + * Find a model by its primary key or throw an exception. + * + * @param array $columns * - * @param array $columns + * @throws ModelNotFoundException */ - public function findOrFail(string $id, array $columns = ['*']): \Laravel\Jetstream\Team + public static function findOrFail(string $id, array $columns = ['*']): Model { if (! Str::isUuid($id)) { throw (new ModelNotFoundException)->setModel( diff --git a/app/Models/OrganizationInvitation.php b/app/Models/OrganizationInvitation.php index 75e99bdfc..2b72882e2 100644 --- a/app/Models/OrganizationInvitation.php +++ b/app/Models/OrganizationInvitation.php @@ -8,9 +8,9 @@ use App\Models\Concerns\HasUuids; use Database\Factories\OrganizationInvitationFactory; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Carbon; -use Laravel\Jetstream\TeamInvitation as JetstreamTeamInvitation; use OwenIt\Auditing\Contracts\Auditable as AuditableContract; /** @@ -18,13 +18,14 @@ * @property string $email * @property string $role * @property string $organization_id + * @property Carbon|null $accepted_at * @property Carbon|null $updated_at * @property Carbon|null $created_at * @property-read Organization $organization * * @method static OrganizationInvitationFactory factory() */ -class OrganizationInvitation extends JetstreamTeamInvitation implements AuditableContract +class OrganizationInvitation extends Model implements AuditableContract { use CustomAuditable; @@ -41,14 +42,16 @@ class OrganizationInvitation extends JetstreamTeamInvitation implements Auditabl protected $table = 'organization_invitations'; /** - * The attributes that are mass assignable. + * Get the attributes that should be cast. * - * @var array + * @return array */ - protected $fillable = [ - 'email', - 'role', - ]; + public function casts(): array + { + return [ + 'accepted_at' => 'datetime', + ]; + } /** * Get the organization that the invitation belongs to. diff --git a/app/Models/User.php b/app/Models/User.php index 76c5115d1..9fcea6ff2 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -4,6 +4,7 @@ namespace App\Models; +use App\Enums\Role; use App\Enums\Weekday; use App\Models\Concerns\CustomAuditable; use App\Models\Concerns\HasUuids; @@ -25,8 +26,6 @@ use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Storage; use Laravel\Fortify\TwoFactorAuthenticatable; -use Laravel\Jetstream\HasProfilePhoto; -use Laravel\Jetstream\HasTeams; use Laravel\Passport\AuthCode; use Laravel\Passport\Contracts\OAuthenticatable; use Laravel\Passport\HasApiTokens; @@ -36,6 +35,7 @@ * @property string $id * @property string $name * @property string $email + * @property string|null $pending_email * @property Carbon|null $email_verified_at * @property string|null $password * @property string|null $two_factor_secret @@ -44,13 +44,13 @@ * @property Weekday $week_start * @property string|null $profile_photo_path * @property-read Organization|null $currentOrganization - * @property-read Organization|null $currentTeam * @property-read string $profile_photo_url * @property-read Collection $tokens * @property Carbon|null $created_at * @property Carbon|null $updated_at * @property string|null $current_team_id * @property Collection $organizations + * @property Collection $ownedOrganizations * @property Collection $timeEntries * @property Member $membership * @@ -68,8 +68,6 @@ class User extends Authenticatable implements AuditableContract, FilamentUser, M /** @use HasFactory */ use HasFactory; - use HasProfilePhoto; - use HasTeams; use HasUuids; use Notifiable; use TwoFactorAuthenticatable; @@ -105,6 +103,7 @@ class User extends Authenticatable implements AuditableContract, FilamentUser, M protected $casts = [ 'name' => 'string', 'email' => 'string', + 'pending_email' => 'string', 'email_verified_at' => 'datetime', 'is_admin' => 'boolean', 'is_placeholder' => 'boolean', @@ -129,16 +128,39 @@ protected function profilePhotoUrl(): Attribute { return Attribute::get(function (): string { return $this->profile_photo_path - ? Storage::disk($this->profilePhotoDisk())->url($this->profile_photo_path) + ? Storage::disk(config('filesystems.public'))->url($this->profile_photo_path) : $this->defaultProfilePhotoUrl(); }); } + /** + * Get the default profile photo URL if no profile photo has been uploaded. + */ + protected function defaultProfilePhotoUrl(): string + { + $name = trim(collect(explode(' ', $this->name))->map(function ($segment) { + return mb_substr($segment, 0, 1); + })->join(' ')); + + return 'https://ui-avatars.com/api/?name='.urlencode($name).'&color=7F9CF5&background=EBF4FF'; + } + public function canAccessPanel(Panel $panel): bool { return in_array($this->email, config('auth.super_admins', []), true) && $this->hasVerifiedEmail(); } + public function isMemberOfOrganization(Organization $organization): bool + { + if ($this->relationLoaded('organizations')) { + return $this->organizations->contains(function (Organization $o) use ($organization): bool { + return $o->getKey() === $organization->getKey(); + }); + } + + return $this->organizations()->whereKey($organization->getKey())->exists(); + } + public function canBeImpersonated(): bool { return $this->is_placeholder === false; @@ -159,6 +181,14 @@ public function organizations(): BelongsToMany ->as('membership'); } + /** + * @return BelongsToMany + */ + public function ownedOrganizations(): BelongsToMany + { + return $this->organizations()->wherePivot('role', Role::Owner->value); + } + /** * @return HasMany */ @@ -213,12 +243,8 @@ public function scopeActive(Builder $builder): void */ public function scopeBelongsToOrganization(Builder $builder, Organization $organization): Builder { - return $builder->where(function (Builder $builder) use ($organization): Builder { - return $builder->whereHas('organizations', function (Builder $query) use ($organization): void { - $query->whereKey($organization->getKey()); - })->orWhereHas('ownedTeams', function (Builder $query) use ($organization): void { - $query->whereKey($organization->getKey()); - }); + return $builder->whereHas('organizations', function (Builder $query) use ($organization): void { + $query->whereKey($organization->getKey()); }); } } diff --git a/app/Policies/OrganizationPolicy.php b/app/Policies/OrganizationPolicy.php deleted file mode 100644 index c0c1bc62f..000000000 --- a/app/Policies/OrganizationPolicy.php +++ /dev/null @@ -1,114 +0,0 @@ -belongsToTeam($organization); - } - - /** - * Determine whether the user can create models. - */ - public function create(User $user): bool - { - if (Filament::isServing()) { - return true; - } - - return true; - } - - /** - * Determine whether the user can update the model. - */ - public function update(User $user, Organization $organization): bool - { - if (Filament::isServing()) { - return true; - } - - return app(PermissionStore::class)->userHas($organization, $user, 'organizations:update'); - } - - /** - * Determine whether the user can add team members. - */ - public function addTeamMember(User $user, Organization $organization): bool - { - if (Filament::isServing()) { - return true; - } - - return true; - } - - /** - * Determine whether the user can update team member permissions. - */ - public function updateTeamMember(User $user, Organization $organization): bool - { - if (Filament::isServing()) { - return true; - } - - // Note: since this policy is only used for jetstream endpoints, we can return false here - return false; - } - - /** - * Determine whether the user can remove team members. - */ - public function removeTeamMember(User $user, Organization $organization): bool - { - if (Filament::isServing()) { - return true; - } - - // Note: since this policy is only used for jetstream endpoints that are no longer in use, we can return false here - return false; - } - - /** - * Determine whether the user can delete the model. - */ - public function delete(User $user, Organization $organization): bool - { - if (Filament::isServing()) { - return true; - } - - return $user->ownsTeam($organization); - } -} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index f524f92d5..cb15494ce 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -4,14 +4,11 @@ namespace App\Providers; -use App\Models\Organization; use App\Models\Passport\AuthCode; use App\Models\Passport\Client; use App\Models\Passport\RefreshToken; use App\Models\Passport\Token; -use App\Policies\OrganizationPolicy; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; -use Laravel\Jetstream\Jetstream; use Laravel\Passport\Passport; class AuthServiceProvider extends ServiceProvider @@ -22,7 +19,6 @@ class AuthServiceProvider extends ServiceProvider * @var array */ protected $policies = [ - Organization::class => OrganizationPolicy::class, ]; /** @@ -56,11 +52,5 @@ public function boot(): void // Passport::tokensExpireIn(now()->addDays(15)); // Passport::refreshTokensExpireIn(now()->addDays(30)); Passport::personalAccessTokensExpireIn(now()->addMonths(12)); - - // same as passport default above - Jetstream::defaultApiTokenPermissions(['read']); - - // use passport scopes for jetstream token permissions - Jetstream::permissions(Passport::scopeIds()); } } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 4dc848b55..8ad1695f2 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -4,11 +4,9 @@ namespace App\Providers; -use App\Listeners\RemovePlaceholder; use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; -use Laravel\Jetstream\Events\TeamMemberAdded; class EventServiceProvider extends ServiceProvider { @@ -21,9 +19,6 @@ class EventServiceProvider extends ServiceProvider Registered::class => [ SendEmailVerificationNotification::class, ], - TeamMemberAdded::class => [ - RemovePlaceholder::class, - ], ]; /** diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php index 2006f4528..270a1571b 100644 --- a/app/Providers/FortifyServiceProvider.php +++ b/app/Providers/FortifyServiceProvider.php @@ -15,11 +15,13 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\RateLimiter; +use Illuminate\Support\Facades\Route; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Str; +use Inertia\Inertia; +use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract; use Laravel\Fortify\Contracts\TwoFactorLoginResponse; use Laravel\Fortify\Fortify; -use Laravel\Fortify\Http\Responses\LoginResponse; class FortifyServiceProvider extends ServiceProvider { @@ -41,6 +43,48 @@ public function boot(): void Fortify::updateUserPasswordsUsing(UpdateUserPassword::class); Fortify::resetUserPasswordsUsing(ResetUserPassword::class); + Fortify::registerView(function () { + return Inertia::render('Auth/Register', [ + 'terms_url' => config('auth.terms_url'), + 'privacy_policy_url' => config('auth.privacy_policy_url'), + 'newsletter_consent' => config('auth.newsletter_consent'), + ]); + }); + + Fortify::loginView(function () { + return Inertia::render('Auth/Login', [ + 'canResetPassword' => Route::has('password.request'), + 'status' => session('status'), + ]); + }); + + Fortify::requestPasswordResetLinkView(function () { + return Inertia::render('Auth/ForgotPassword', [ + 'status' => session('status'), + ]); + }); + + Fortify::resetPasswordView(function (Request $request) { + return Inertia::render('Auth/ResetPassword', [ + 'email' => $request->input('email'), + 'token' => $request->route('token'), + ]); + }); + + Fortify::verifyEmailView(function () { + return Inertia::render('Auth/VerifyEmail', [ + 'status' => session('status'), + ]); + }); + + Fortify::twoFactorChallengeView(function () { + return Inertia::render('Auth/TwoFactorChallenge'); + }); + + Fortify::confirmPasswordView(function () { + return Inertia::render('Auth/ConfirmPassword'); + }); + Fortify::authenticateUsing(function (Request $request): ?User { /** @var User|null $user */ $user = User::query() @@ -65,7 +109,7 @@ public function boot(): void return Limit::perMinute(5)->by($request->session()->get('login.id')); }); - $this->app->instance(LoginResponse::class, new CustomLoginResponse); + $this->app->instance(LoginResponseContract::class, new CustomLoginResponse); $this->app->instance(TwoFactorLoginResponse::class, new CustomTwoFactorLoginResponse); } } diff --git a/app/Providers/JetstreamServiceProvider.php b/app/Providers/JetstreamServiceProvider.php deleted file mode 100644 index cc8c3c968..000000000 --- a/app/Providers/JetstreamServiceProvider.php +++ /dev/null @@ -1,317 +0,0 @@ -configurePermissions(); - - Jetstream::createTeamsUsing(CreateOrganization::class); - Jetstream::updateTeamNamesUsing(UpdateOrganization::class); - Jetstream::addTeamMembersUsing(AddOrganizationMember::class); - Jetstream::inviteTeamMembersUsing(InviteOrganizationMember::class); - Jetstream::removeTeamMembersUsing(RemoveOrganizationMember::class); - Jetstream::deleteTeamsUsing(DeleteOrganization::class); - Jetstream::deleteUsersUsing(DeleteUser::class); - Jetstream::useTeamModel(Organization::class); - Jetstream::useMembershipModel(Member::class); - Jetstream::useTeamInvitationModel(OrganizationInvitation::class); - app()->singleton(UpdateTeamMemberRole::class, UpdateMemberRole::class); - app()->singleton(ValidateTeamDeletion::class, ValidateOrganizationDeletion::class); - Fortify::registerView(function () { - return Inertia::render('Auth/Register', [ - 'terms_url' => config('auth.terms_url'), - 'privacy_policy_url' => config('auth.privacy_policy_url'), - 'newsletter_consent' => config('auth.newsletter_consent'), - ]); - }); - Gate::define('removeTeamMember', function (User $user, Organization $team) { - return false; - }); - } - - /** - * Configure the roles and permissions that are available within the application. - */ - protected function configurePermissions(): void - { - Jetstream::defaultApiTokenPermissions([]); - - Jetstream::role(Role::Owner->value, 'Owner', [ - 'charts:view:own', - 'charts:view:all', - 'projects:view', - 'projects:view:all', - 'projects:create', - 'projects:update', - 'projects:delete', - 'project-members:view', - 'project-members:create', - 'project-members:update', - 'project-members:delete', - 'tasks:view', - 'tasks:view:all', - 'tasks:create', - 'tasks:create:all', - 'tasks:update', - 'tasks:update:all', - 'tasks:delete', - 'tasks:delete:all', - 'time-entries:view:all', - 'time-entries:create:all', - 'time-entries:update:all', - 'time-entries:delete:all', - 'time-entries:view:own', - 'time-entries:create:own', - 'time-entries:update:own', - 'time-entries:delete:own', - 'tags:view', - 'tags:create', - 'tags:update', - 'tags:delete', - 'clients:view', - 'clients:view:all', - 'clients:create', - 'clients:update', - 'clients:delete', - 'organizations:view', - 'organizations:update', - 'organizations:delete', - 'import', - 'export', - 'invitations:view', - 'invitations:create', - 'invitations:resend', - 'invitations:remove', - 'members:view', - 'members:invite-placeholder', - 'members:change-ownership', - 'members:make-placeholder', - 'members:merge-into', - 'members:update', - 'members:delete', - 'billing', - 'reports:view', - 'reports:create', - 'reports:update', - 'reports:delete', - 'invoices:view', - 'invoices:create', - 'invoices:update', - 'invoices:download', - 'invoices:delete', - 'invoice-settings:view', - 'invoice-settings:update', - ])->description('Owner users can perform any action. There is only one owner per organization.'); - - Jetstream::role(Role::Admin->value, 'Administrator', [ - 'charts:view:own', - 'charts:view:all', - 'projects:view', - 'projects:view:all', - 'projects:create', - 'projects:update', - 'projects:delete', - 'project-members:view', - 'project-members:create', - 'project-members:update', - 'project-members:delete', - 'tasks:view', - 'tasks:view:all', - 'tasks:create', - 'tasks:create:all', - 'tasks:update', - 'tasks:update:all', - 'tasks:delete', - 'tasks:delete:all', - 'time-entries:view:all', - 'time-entries:create:all', - 'time-entries:update:all', - 'time-entries:delete:all', - 'time-entries:view:own', - 'time-entries:create:own', - 'time-entries:update:own', - 'time-entries:delete:own', - 'tags:view', - 'tags:create', - 'tags:update', - 'tags:delete', - 'clients:view', - 'clients:view:all', - 'clients:create', - 'clients:update', - 'clients:delete', - 'organizations:view', - 'organizations:update', - 'import', - 'export', - 'invitations:view', - 'invitations:create', - 'invitations:resend', - 'invitations:remove', - 'members:view', - 'members:invite-placeholder', - 'members:make-placeholder', - 'members:merge-into', - 'members:delete', - 'members:update', - 'reports:view', - 'reports:create', - 'reports:update', - 'reports:delete', - 'invoices:view', - 'invoices:create', - 'invoices:update', - 'invoices:download', - 'invoices:delete', - 'invoice-settings:view', - 'invoice-settings:update', - ])->description('Administrator users can perform any action, except accessing the billing dashboard.'); - - Jetstream::role(Role::Manager->value, 'Manager', [ - 'charts:view:own', - 'charts:view:all', - 'projects:view', - 'projects:view:all', - 'projects:create', - 'projects:update', - 'projects:delete', - 'project-members:view', - 'project-members:create', - 'project-members:update', - 'project-members:delete', - 'tasks:view', - 'tasks:view:all', - 'tasks:create', - 'tasks:create:all', - 'tasks:update', - 'tasks:update:all', - 'tasks:delete', - 'tasks:delete:all', - 'time-entries:view:all', - 'time-entries:create:all', - 'time-entries:update:all', - 'time-entries:delete:all', - 'time-entries:view:own', - 'time-entries:create:own', - 'time-entries:update:own', - 'time-entries:delete:own', - 'tags:view', - 'tags:create', - 'tags:update', - 'tags:delete', - 'clients:view', - 'clients:view:all', - 'clients:create', - 'clients:update', - 'clients:delete', - 'organizations:view', - 'invitations:view', - 'members:view', - 'reports:view', - 'reports:create', - 'reports:update', - 'reports:delete', - 'invoices:view', - 'invoices:create', - 'invoices:update', - 'invoices:download', - 'invoices:delete', - 'invoice-settings:view', - 'invoice-settings:update', - ])->description('Managers have full access to all projects, time entries, ect. but cannot manage the organization (add/remove member, edit the organization, ect.).'); - - Jetstream::role(Role::Employee->value, 'Employee', [ - 'charts:view:own', - 'projects:view', - 'tags:view', - 'tasks:view', - 'clients:view', - 'time-entries:view:own', - 'time-entries:create:own', - 'time-entries:update:own', - 'time-entries:delete:own', - 'organizations:view', - ])->description('Employees have the ability to read, create, and update their own time entries, they can see the projects that they are members of and the clients they are assigned to.'); - - Jetstream::role(Role::Placeholder->value, 'Placeholder', [ - ])->description('Placeholders are used for importing data. They cannot log in and have no permissions.'); - - Jetstream::inertia() - ->whenRendering( - 'Profile/Show', - function (Request $request, array $data): array { - return array_merge($data, [ - 'timezones' => $this->app->get(TimezoneService::class)->getSelectOptions(), - 'weekdays' => Weekday::toSelectArray(), - ]); - } - ) - ->whenRendering( - 'Teams/Show', - function (Request $request, array $data): array { - /** @var Organization $teamModel */ - $teamModel = $data['team']; - $owner = $teamModel->owner; - - return array_merge($data, [ - 'team' => [ - 'id' => $teamModel->getKey(), - 'name' => $teamModel->name, - 'currency' => $teamModel->currency, - 'owner' => [ - 'id' => $owner->getKey(), - 'name' => $owner->name, - 'profile_photo_url' => $owner->profile_photo_url, - ], - ], - 'currencies' => array_map(function (Currency $currency): string { - return $currency->getName(); - }, ISOCurrencyProvider::getInstance()->getAvailableCurrencies()), - ]); - } - ); - } -} diff --git a/app/Rules/Base64ImageRule.php b/app/Rules/Base64ImageRule.php new file mode 100644 index 000000000..d60ff9b0c --- /dev/null +++ b/app/Rules/Base64ImageRule.php @@ -0,0 +1,45 @@ + 'jpg, png'])); + + return; + } + + if (strlen($file['data']) > self::MAX_BYTES) { + $fail(__('validation.max.file', ['max' => (string) (self::MAX_BYTES / 1024)])); + } + } +} diff --git a/app/Service/DeletionService.php b/app/Service/DeletionService.php index 1ebefaf57..2cee272fe 100644 --- a/app/Service/DeletionService.php +++ b/app/Service/DeletionService.php @@ -173,7 +173,7 @@ public function deleteUser(User $user, bool $inTransaction = true): void $user->authCodes()->delete(); // Note: Since the deletion of the profile photo is not reversible via a database rollback this needs to be done last - $user->deleteProfilePhoto(); + $this->userService->deleteProfilePhoto($user); $user->delete(); diff --git a/app/Service/Dto/UserAgentDto.php b/app/Service/Dto/UserAgentDto.php new file mode 100644 index 000000000..66156b132 --- /dev/null +++ b/app/Service/Dto/UserAgentDto.php @@ -0,0 +1,179 @@ + + */ + protected static array $additionalOperatingSystems = [ + 'Windows' => 'Windows', + 'Windows NT' => 'Windows NT', + 'OS X' => 'Mac OS X', + 'Debian' => 'Debian', + 'Ubuntu' => 'Ubuntu', + 'Macintosh' => 'PPC', + 'OpenBSD' => 'OpenBSD', + 'Linux' => 'Linux', + 'ChromeOS' => 'CrOS', + ]; + + /** + * List of additional browsers. + * + * @var array + */ + protected static array $additionalBrowsers = [ + 'Opera Mini' => 'Opera Mini', + 'Opera' => 'Opera|OPR', + 'Edge' => 'Edge|Edg', + 'Coc Coc' => 'coc_coc_browser', + 'UCBrowser' => 'UCBrowser', + 'Vivaldi' => 'Vivaldi', + 'Chrome' => 'Chrome', + 'Firefox' => 'Firefox', + 'Safari' => 'Safari', + 'IE' => 'MSIE|IEMobile|MSIEMobile|Trident/[.0-9]+', + 'Netscape' => 'Netscape', + 'Mozilla' => 'Mozilla', + 'WeChat' => 'MicroMessenger', + ]; + + /** + * Key value store for resolved strings. + * + * @var array + */ + protected array $store = []; + + /** + * Get the platform name from the User Agent. + */ + public function platform(): ?string + { + return $this->retrieveUsingCacheOrResolve('platform', function () { + return $this->findDetectionRulesAgainstUserAgent( + $this->mergeRules(MobileDetect::getOperatingSystems(), static::$additionalOperatingSystems) + ); + }); + } + + /** + * Get the browser name from the User Agent. + */ + public function browser(): ?string + { + return $this->retrieveUsingCacheOrResolve('browser', function (): ?string { + return $this->findDetectionRulesAgainstUserAgent( + $this->mergeRules(static::$additionalBrowsers, MobileDetect::getBrowsers()) + ); + }); + } + + /** + * Determine if the device is a desktop computer. + */ + public function isDesktop(): bool + { + return $this->retrieveUsingCacheOrResolve('desktop', function (): bool { + // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront' + if ( + $this->getUserAgent() === static::$cloudFrontUA + && $this->getHttpHeader('HTTP_CLOUDFRONT_IS_DESKTOP_VIEWER') === 'true' + ) { + return true; + } + + return ! $this->isMobile() && ! $this->isTablet(); + }); + } + + /** + * Match a detection rule and return the matched key. + * + * @param array> $rules + */ + protected function findDetectionRulesAgainstUserAgent(array $rules): ?string + { + $userAgent = $this->getUserAgent(); + + foreach ($rules as $key => $regex) { + if (is_array($regex)) { + $regex = implode('|', $regex); + } + + if (empty($regex)) { + continue; + } + + if ($this->match($regex, $userAgent)) { + if ($key !== '') { + return $key; + } + + $match = reset($this->matchesArray); + + return is_string($match) ? $match : null; + } + } + + return null; + } + + /** + * Retrieve from the given key from the cache or resolve the value. + * + * @template TReturn of string|bool|null + * + * @param Closure():TReturn $callback + * @return TReturn + */ + protected function retrieveUsingCacheOrResolve(string $key, Closure $callback): string|bool|null + { + $cacheKey = $this->createCacheKey($key); + + if (! is_null($cacheItem = $this->store[$cacheKey] ?? null)) { + return $cacheItem; + } + + return tap(call_user_func($callback), function ($result) use ($cacheKey): void { + $this->store[$cacheKey] = $result; + }); + } + + /** + * Merge multiple rules into one array. + * + * @param array> ...$all + * @return array + */ + protected function mergeRules(array ...$all): array + { + $merged = []; + + foreach ($all as $rules) { + foreach ($rules as $key => $value) { + $value = is_array($value) ? implode('|', $value) : $value; + + if (empty($merged[$key])) { + $merged[$key] = $value; + } else { + $merged[$key] .= '|'.$value; + } + } + } + + return $merged; + } +} diff --git a/app/Service/InvitationService.php b/app/Service/InvitationService.php index 4fc92c7aa..345933a77 100644 --- a/app/Service/InvitationService.php +++ b/app/Service/InvitationService.php @@ -5,27 +5,25 @@ namespace App\Service; use App\Enums\Role; +use App\Events\OrganizationInvitationAdding; use App\Exceptions\Api\InvitationForTheEmailAlreadyExistsApiException; use App\Exceptions\Api\UserIsAlreadyMemberOfOrganizationApiException; use App\Mail\OrganizationInvitationMail; -use App\Models\Member; use App\Models\Organization; use App\Models\OrganizationInvitation; +use App\Models\User; +use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Mail; -use Laravel\Jetstream\Events\InvitingTeamMember; class InvitationService { /** * @throws UserIsAlreadyMemberOfOrganizationApiException|InvitationForTheEmailAlreadyExistsApiException */ - public function inviteUser(Organization $organization, string $email, Role $role): OrganizationInvitation + public function inviteUser(Organization $organization, string $email, Role $role, User $inviter): OrganizationInvitation { - if (Member::query() - ->whereBelongsTo($organization, 'organization') - ->whereRelation('user', 'email', '=', $email) - ->where('role', '!=', Role::Placeholder->value) - ->exists()) { + if (app(MemberService::class)->isEmailAlreadyMember($organization, $email)) { throw new UserIsAlreadyMemberOfOrganizationApiException; } @@ -36,7 +34,7 @@ public function inviteUser(Organization $organization, string $email, Role $role throw new InvitationForTheEmailAlreadyExistsApiException; } - InvitingTeamMember::dispatch($organization, $email, $role->value); + OrganizationInvitationAdding::dispatch($organization, $email, $role, $inviter); $invitation = new OrganizationInvitation; $invitation->email = $email; @@ -48,4 +46,37 @@ public function inviteUser(Organization $organization, string $email, Role $role return $invitation; } + + /** + * @return Collection + */ + public function processAcceptedInvitations(User $user): Collection + { + $organizations = new Collection; + + $invitations = OrganizationInvitation::query() + ->where('email', $user->email) + ->whereNotNull('accepted_at') + ->get(); + + foreach ($invitations as $invitation) { + $organization = $invitation->organization; + $role = Role::tryFrom($invitation->role); + if ($role === null) { + Log::error('Invalid role in invitation', [ + 'invitation' => $invitation->getKey(), + 'role' => $invitation->role, + ]); + + continue; + } + app(MemberService::class)->addMember($user, $organization, $role); + + $invitation->delete(); + + $organizations->push($organization); + } + + return $organizations; + } } diff --git a/app/Service/MemberService.php b/app/Service/MemberService.php index 5c0c22678..68e2a516e 100644 --- a/app/Service/MemberService.php +++ b/app/Service/MemberService.php @@ -5,6 +5,8 @@ namespace App\Service; use App\Enums\Role; +use App\Events\MemberAdded; +use App\Events\MemberAdding; use App\Events\MemberRemoved; use App\Exceptions\Api\CanNotRemoveOwnerFromOrganization; use App\Exceptions\Api\ChangingRoleOfPlaceholderIsNotAllowed; @@ -21,8 +23,6 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\DB; use InvalidArgumentException; -use Laravel\Jetstream\Events\AddingTeamMember; -use Laravel\Jetstream\Events\TeamMemberAdded; class MemberService { @@ -36,7 +36,7 @@ public function __construct(UserService $userService) public function addMember(User $user, Organization $organization, Role $role, bool $asSuperAdmin = false): Member { if (! $asSuperAdmin) { - AddingTeamMember::dispatch($organization, $user); + MemberAdding::dispatch($user, $organization, $role); } $member = new Member; @@ -49,14 +49,36 @@ public function addMember(User $user, Organization $organization, Role $role, bo $user->currentOrganization()->associate($organization); $user->save(); }); + $this->mergePlaceholderMembersIntoExistingMember($member, $organization, $user); if (! $asSuperAdmin) { - TeamMemberAdded::dispatch($organization, $user); + MemberAdded::dispatch($member, $organization, $user); } return $member; } + private function mergePlaceholderMembersIntoExistingMember(Member $member, Organization $organization, User $user): void + { + $placeholders = Member::query() + ->whereHas('user', function (Builder $query) use ($user): void { + /** @var Builder $query */ + $query->where('is_placeholder', '=', true) + ->where('email', '=', $user->email); + }) + ->whereBelongsTo($organization, 'organization') + ->with(['user']) + ->get(); + + foreach ($placeholders as $placeholder) { + /** @var Member $placeholder */ + $placeholderUser = $placeholder->user; + $this->assignOrganizationEntitiesToDifferentMember($organization, $placeholder, $member); + $placeholder->delete(); + $placeholderUser->delete(); + } + } + /** * @throws CanNotRemoveOwnerFromOrganization * @throws EntityStillInUseApiException @@ -71,7 +93,7 @@ public function removeMember(Member $member, Organization $organization, bool $w $isPlaceholder = $user->is_placeholder; if (! $isPlaceholder && $user->current_team_id === $member->organization_id) { - $user->currentTeam()->disassociate(); + $user->currentOrganization()->disassociate(); $user->save(); } @@ -190,7 +212,7 @@ public function makeMemberToPlaceholder(Member $member, bool $makeSureUserHasAtL { $user = $member->user; if ($user->current_team_id === $member->organization_id) { - $user->currentTeam()->disassociate(); + $user->currentOrganization()->disassociate(); $user->save(); } @@ -209,4 +231,13 @@ public function makeMemberToPlaceholder(Member $member, bool $makeSureUserHasAtL $this->userService->makeSureUserHasCurrentOrganization($user); } } + + public function isEmailAlreadyMember(Organization $organization, string $email): bool + { + return Member::query() + ->whereBelongsTo($organization, 'organization') + ->whereRelation('user', 'email', '=', $email) + ->where('role', '!=', Role::Placeholder->value) + ->exists(); + } } diff --git a/app/Service/PermissionStore.php b/app/Service/PermissionStore.php index d346691c5..32072868e 100644 --- a/app/Service/PermissionStore.php +++ b/app/Service/PermissionStore.php @@ -4,14 +4,238 @@ namespace App\Service; +use App\Enums\Role; use App\Models\Organization; use App\Models\User; use Illuminate\Support\Facades\Auth; -use Laravel\Jetstream\Jetstream; -use Laravel\Jetstream\Role; class PermissionStore { + /** + * @var array, description: string}> + */ + private const array ROLE_DEFINITIONS = [ + 'owner' => [ + 'name' => 'Owner', + 'permissions' => [ + 'charts:view:own', + 'charts:view:all', + 'projects:view', + 'projects:view:all', + 'projects:create', + 'projects:update', + 'projects:delete', + 'project-members:view', + 'project-members:create', + 'project-members:update', + 'project-members:delete', + 'tasks:view', + 'tasks:view:all', + 'tasks:create', + 'tasks:create:all', + 'tasks:update', + 'tasks:update:all', + 'tasks:delete', + 'tasks:delete:all', + 'time-entries:view:all', + 'time-entries:create:all', + 'time-entries:update:all', + 'time-entries:delete:all', + 'time-entries:view:own', + 'time-entries:create:own', + 'time-entries:update:own', + 'time-entries:delete:own', + 'tags:view', + 'tags:create', + 'tags:update', + 'tags:delete', + 'clients:view', + 'clients:view:all', + 'clients:create', + 'clients:update', + 'clients:delete', + 'organizations:view', + 'organizations:update', + 'organizations:delete', + 'import', + 'export', + 'invitations:view', + 'invitations:create', + 'invitations:resend', + 'invitations:remove', + 'members:view', + 'members:invite-placeholder', + 'members:change-ownership', + 'members:make-placeholder', + 'members:merge-into', + 'members:update', + 'members:delete', + 'billing', + 'reports:view', + 'reports:create', + 'reports:update', + 'reports:delete', + 'invoices:view', + 'invoices:create', + 'invoices:update', + 'invoices:download', + 'invoices:delete', + 'invoice-settings:view', + 'invoice-settings:update', + ], + 'description' => 'Owner users can perform any action. There is only one owner per organization.', + ], + 'admin' => [ + 'name' => 'Administrator', + 'permissions' => [ + 'charts:view:own', + 'charts:view:all', + 'projects:view', + 'projects:view:all', + 'projects:create', + 'projects:update', + 'projects:delete', + 'project-members:view', + 'project-members:create', + 'project-members:update', + 'project-members:delete', + 'tasks:view', + 'tasks:view:all', + 'tasks:create', + 'tasks:create:all', + 'tasks:update', + 'tasks:update:all', + 'tasks:delete', + 'tasks:delete:all', + 'time-entries:view:all', + 'time-entries:create:all', + 'time-entries:update:all', + 'time-entries:delete:all', + 'time-entries:view:own', + 'time-entries:create:own', + 'time-entries:update:own', + 'time-entries:delete:own', + 'tags:view', + 'tags:create', + 'tags:update', + 'tags:delete', + 'clients:view', + 'clients:view:all', + 'clients:create', + 'clients:update', + 'clients:delete', + 'organizations:view', + 'organizations:update', + 'import', + 'export', + 'invitations:view', + 'invitations:create', + 'invitations:resend', + 'invitations:remove', + 'members:view', + 'members:invite-placeholder', + 'members:make-placeholder', + 'members:merge-into', + 'members:delete', + 'members:update', + 'reports:view', + 'reports:create', + 'reports:update', + 'reports:delete', + 'invoices:view', + 'invoices:create', + 'invoices:update', + 'invoices:download', + 'invoices:delete', + 'invoice-settings:view', + 'invoice-settings:update', + ], + 'description' => 'Administrator users can perform any action, except accessing the billing dashboard.', + ], + 'manager' => [ + 'name' => 'Manager', + 'permissions' => [ + 'charts:view:own', + 'charts:view:all', + 'projects:view', + 'projects:view:all', + 'projects:create', + 'projects:update', + 'projects:delete', + 'project-members:view', + 'project-members:create', + 'project-members:update', + 'project-members:delete', + 'tasks:view', + 'tasks:view:all', + 'tasks:create', + 'tasks:create:all', + 'tasks:update', + 'tasks:update:all', + 'tasks:delete', + 'tasks:delete:all', + 'time-entries:view:all', + 'time-entries:create:all', + 'time-entries:update:all', + 'time-entries:delete:all', + 'time-entries:view:own', + 'time-entries:create:own', + 'time-entries:update:own', + 'time-entries:delete:own', + 'tags:view', + 'tags:create', + 'tags:update', + 'tags:delete', + 'clients:view', + 'clients:view:all', + 'clients:create', + 'clients:update', + 'clients:delete', + 'organizations:view', + 'invitations:view', + 'members:view', + 'reports:view', + 'reports:create', + 'reports:update', + 'reports:delete', + 'invoices:view', + 'invoices:create', + 'invoices:update', + 'invoices:download', + 'invoices:delete', + 'invoice-settings:view', + 'invoice-settings:update', + ], + 'description' => 'Managers have full access to all projects, time entries, ect. but cannot manage the organization (add/remove member, edit the organization, ect.).', + ], + 'employee' => [ + 'name' => 'Employee', + 'permissions' => [ + 'charts:view:own', + 'projects:view', + 'tags:view', + 'tasks:view', + 'clients:view', + 'time-entries:view:own', + 'time-entries:create:own', + 'time-entries:update:own', + 'time-entries:delete:own', + 'organizations:view', + ], + 'description' => 'Employees have the ability to read, create, and update their own time entries, they can see the projects that they are members of and the clients they are assigned to.', + ], + 'placeholder' => [ + 'name' => 'Placeholder', + 'permissions' => [], + 'description' => 'Placeholders are used for importing data. They cannot log in and have no permissions.', + ], + ]; + + /** + * @var array> + */ + private static array $customRolePermissions = []; + /** * @var array> */ @@ -22,6 +246,37 @@ public function clear(): void $this->permissionCache = []; } + /** + * @return array, description: string}> + */ + public static function roleDefinitions(): array + { + return self::ROLE_DEFINITIONS; + } + + /** + * @param array $permissions + */ + public static function registerCustomRole(string $role, array $permissions): void + { + self::$customRolePermissions[$role] = $permissions; + } + + public static function resetCustomRoles(): void + { + self::$customRolePermissions = []; + } + + /** + * @return array + */ + public static function permissionsForRole(string $role): array + { + return self::$customRolePermissions[$role] + ?? self::ROLE_DEFINITIONS[$role]['permissions'] + ?? []; + } + public function has(Organization $organization, string $permission): bool { /** @var User|null $user */ @@ -36,7 +291,7 @@ public function has(Organization $organization, string $permission): bool public function userHas(Organization $organization, User $user, string $permission): bool { if (! isset($this->permissionCache[$user->getKey().'|'.$organization->getKey()])) { - if (! $user->belongsToTeam($organization)) { + if (! $user->isMemberOfOrganization($organization)) { return false; } @@ -54,7 +309,7 @@ public function userHas(Organization $organization, User $user, string $permissi */ private function getPermissionsByUser(Organization $organization, User $user): array { - if (! $user->belongsToTeam($organization)) { + if (! $user->isMemberOfOrganization($organization)) { return []; } @@ -68,14 +323,11 @@ private function getPermissionsByUser(Organization $organization, User $user): a return []; } - /** @var Role|null $roleObj */ - $roleObj = Jetstream::findRole($role); - - $permissions = $roleObj->permissions ?? []; + $permissions = self::permissionsForRole($role); // If the organization allows employees to manage tasks and the user is an employee, // add the task management permissions for accessible projects - if ($role === \App\Enums\Role::Employee->value && $organization->employees_can_manage_tasks) { + if ($role === Role::Employee->value && $organization->employees_can_manage_tasks) { $permissions = array_merge($permissions, [ 'tasks:create', 'tasks:update', diff --git a/app/Service/ReportExport/CsvExport.php b/app/Service/ReportExport/CsvExport.php index 8708cb3c2..850d96f7e 100644 --- a/app/Service/ReportExport/CsvExport.php +++ b/app/Service/ReportExport/CsvExport.php @@ -10,6 +10,9 @@ use Illuminate\Http\File; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Storage; +use League\Csv\CannotInsertRecord; +use League\Csv\Exception; +use League\Csv\UnavailableStream; use League\Csv\Writer; use Spatie\TemporaryDirectory\TemporaryDirectory; @@ -58,9 +61,9 @@ public function __construct(string $disk, string $folderPath, string $filename, abstract public function mapRow(Model $model): array; /** - * @throws \League\Csv\CannotInsertRecord - * @throws \League\Csv\Exception - * @throws \League\Csv\UnavailableStream + * @throws CannotInsertRecord + * @throws Exception + * @throws UnavailableStream */ public function export(): void { @@ -72,6 +75,7 @@ public function export(): void $writer->insertOne(static::HEADER); $this->builder->chunk($this->chunk, function (Collection $models) use ($writer): void { + /** @var T $model */ foreach ($models as $model) { $data = $this->mapRow($model); $row = $this->convertRow($data); diff --git a/app/Service/UserService.php b/app/Service/UserService.php index 1cae3307d..5cefb62f8 100644 --- a/app/Service/UserService.php +++ b/app/Service/UserService.php @@ -19,6 +19,7 @@ use App\Models\User; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Facades\Storage; class UserService { @@ -38,7 +39,7 @@ public function createUser( ): User { $user = new User; $user->name = $name; - $user->email = $email; + $user->email = strtolower($email); $user->password = Hash::make($password); $user->timezone = $timezone; $user->week_start = $weekStart; @@ -47,19 +48,22 @@ public function createUser( } $user->save(); - $organization = app(OrganizationService::class)->createOrganization( - $this->getOrganizationNameForUserName($user->name), - $user, - true, - $currency, - $numberFormat, - $currencyFormat, - $dateFormat, - $intervalFormat, - $timeFormat, - ); - - $user->ownedTeams()->save($organization); + $organizations = app(InvitationService::class)->processAcceptedInvitations($user); + + if ($organizations->isEmpty()) { + $organization = app(OrganizationService::class)->createOrganization( + $this->getOrganizationNameForUserName($user->name), + $user, + true, + $currency, + $numberFormat, + $currencyFormat, + $dateFormat, + $intervalFormat, + $timeFormat, + ); + $this->switchCurrentOrganization($user, $organization); + } return $user; } @@ -100,13 +104,17 @@ public function makeSureUserHasAtLeastOneOrganization(User $user): void true ); - // Set the organization as the user's current organization - $user->currentOrganization()->associate($organization); - $user->save(); + $this->switchCurrentOrganization($user, $organization); AfterCreateOrganization::dispatch($organization); } + public function switchCurrentOrganization(User $user, Organization $organization): void + { + $user->currentOrganization()->associate($organization); + $user->save(); + } + public function getOrganizationNameForUserName(string $username): string { return explode(' ', $username, 2)[0]."'s Organization"; @@ -154,4 +162,16 @@ public function changeOwnership(Organization $organization, User $newOwner): voi $oldOwner->save(); } } + + public function deleteProfilePhoto(User $user): void + { + if ($user->profile_photo_path === null) { + return; + } + + Storage::disk(config('filesystems.public'))->delete($user->profile_photo_path); + + $user->profile_photo_path = null; + $user->save(); + } } diff --git a/app/Support/Base64File.php b/app/Support/Base64File.php new file mode 100644 index 000000000..5a94422b3 --- /dev/null +++ b/app/Support/Base64File.php @@ -0,0 +1,45 @@ +buffer($decoded); + if ($mimeType === false) { + return null; + } + + return [ + 'data' => $decoded, + 'mime_type' => $mimeType, + ]; + } + + public static function extension(string $mimeType): ?string + { + return MimeTypes::getDefault()->getExtensions($mimeType)[0] ?? null; + } +} diff --git a/bootstrap/app.php b/bootstrap/app.php index 08d677b8f..4b2989c99 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -1,6 +1,10 @@ singleton( Illuminate\Contracts\Http\Kernel::class, - App\Http\Kernel::class + Kernel::class ); $app->singleton( @@ -39,8 +43,8 @@ ); $app->singleton( - Illuminate\Contracts\Debug\ExceptionHandler::class, - App\Exceptions\Handler::class + ExceptionHandler::class, + Handler::class ); /* diff --git a/composer.json b/composer.json index 53c40842b..357a47b72 100644 --- a/composer.json +++ b/composer.json @@ -18,8 +18,8 @@ "korridor/laravel-computed-attributes": "^3.1", "korridor/laravel-has-many-sync": "^3.1", "korridor/laravel-model-validation-rules": "^3.0", + "laravel/fortify": "^1.37", "laravel/framework": "^12.19.3", - "laravel/jetstream": "^5.0", "laravel/octane": "^2.3", "laravel/passport": "^13.0.5", "laravel/tinker": "^2.8", @@ -27,6 +27,7 @@ "league/flysystem-aws-s3-v3": "^3.0", "league/iso3166": "^4.3", "maatwebsite/excel": "^3.1", + "mobiledetect/mobiledetectlib": "^4.11", "novadaemon/filament-pretty-json": "^2.2", "nwidart/laravel-modules": "^12.0.4", "owen-it/laravel-auditing": "^14.0.0", @@ -131,7 +132,8 @@ "pestphp/pest-plugin": true, "php-http/discovery": true, "wikimedia/composer-merge-plugin": true - } + }, + "process-timeout": 900 }, "minimum-stability": "stable", "prefer-stable": true diff --git a/composer.lock b/composer.lock index 208b6d1e9..60efe66e6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,33 +4,32 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4c728f01d2beb426b2d157143618fdae", + "content-hash": "897ca7bc13f827db641f7affa54a8523", "packages": [ { "name": "anourvalar/eloquent-serialize", - "version": "1.3.5", + "version": "1.3.8", "source": { "type": "git", "url": "https://github.com/AnourValar/eloquent-serialize.git", - "reference": "1a7dead8d532657e5358f8f27c0349373517681e" + "reference": "6bf2d5b336e78c99cdb9e1252eb78d004451841b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/AnourValar/eloquent-serialize/zipball/1a7dead8d532657e5358f8f27c0349373517681e", - "reference": "1a7dead8d532657e5358f8f27c0349373517681e", + "url": "https://api.github.com/repos/AnourValar/eloquent-serialize/zipball/6bf2d5b336e78c99cdb9e1252eb78d004451841b", + "reference": "6bf2d5b336e78c99cdb9e1252eb78d004451841b", "shasum": "" }, "require": { - "laravel/framework": "^8.0|^9.0|^10.0|^11.0|^12.0", - "php": "^7.4|^8.0" + "laravel/framework": "^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", + "php": "^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.26", "laravel/legacy-factories": "^1.1", - "orchestra/testbench": "^6.0|^7.0|^8.0|^9.0|^10.0", + "orchestra/testbench": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", "phpstan/phpstan": "^2.0", "phpunit/phpunit": "^9.5|^10.5|^11.0", - "psalm/plugin-laravel": "^2.8|^3.0", "squizlabs/php_codesniffer": "^3.7" }, "type": "library", @@ -68,9 +67,9 @@ ], "support": { "issues": "https://github.com/AnourValar/eloquent-serialize/issues", - "source": "https://github.com/AnourValar/eloquent-serialize/tree/1.3.5" + "source": "https://github.com/AnourValar/eloquent-serialize/tree/1.3.8" }, - "time": "2025-12-04T13:38:21+00:00" + "time": "2026-05-04T09:18:12+00:00" }, { "name": "aws/aws-crt-php", @@ -128,16 +127,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.371.3", + "version": "3.381.6", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "d300ec1c861e52dc8f17ca3d75dc754da949f065" + "reference": "9be3422631494111ec76bec677f1ae2dec650573" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/d300ec1c861e52dc8f17ca3d75dc754da949f065", - "reference": "d300ec1c861e52dc8f17ca3d75dc754da949f065", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/9be3422631494111ec76bec677f1ae2dec650573", + "reference": "9be3422631494111ec76bec677f1ae2dec650573", "shasum": "" }, "require": { @@ -158,12 +157,12 @@ "aws/aws-php-sns-message-validator": "~1.0", "behat/behat": "~3.0", "composer/composer": "^2.7.8", - "dms/phpunit-arraysubset-asserts": "^0.4.0", + "dms/phpunit-arraysubset-asserts": "^v0.5.0", "doctrine/cache": "~1.4", "ext-dom": "*", "ext-openssl": "*", "ext-sockets": "*", - "phpunit/phpunit": "^9.6", + "phpunit/phpunit": "^10.0", "psr/cache": "^2.0 || ^3.0", "psr/simple-cache": "^2.0 || ^3.0", "sebastian/comparator": "^1.2.3 || ^4.0 || ^5.0", @@ -219,22 +218,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.371.3" + "source": "https://github.com/aws/aws-sdk-php/tree/3.381.6" }, - "time": "2026-02-27T19:05:40+00:00" + "time": "2026-05-21T20:14:47+00:00" }, { "name": "bacon/bacon-qr-code", - "version": "v3.0.1", + "version": "v3.1.1", "source": { "type": "git", "url": "https://github.com/Bacon/BaconQrCode.git", - "reference": "f9cc1f52b5a463062251d666761178dbdb6b544f" + "reference": "4da2233e72eeecd9be3b62e0dc2cc9ed8e2e31c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/f9cc1f52b5a463062251d666761178dbdb6b544f", - "reference": "f9cc1f52b5a463062251d666761178dbdb6b544f", + "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/4da2233e72eeecd9be3b62e0dc2cc9ed8e2e31c2", + "reference": "4da2233e72eeecd9be3b62e0dc2cc9ed8e2e31c2", "shasum": "" }, "require": { @@ -244,8 +243,9 @@ }, "require-dev": { "phly/keep-a-changelog": "^2.12", - "phpunit/phpunit": "^10.5.11 || 11.0.4", + "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": { @@ -273,32 +273,32 @@ "homepage": "https://github.com/Bacon/BaconQrCode", "support": { "issues": "https://github.com/Bacon/BaconQrCode/issues", - "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.1" + "source": "https://github.com/Bacon/BaconQrCode/tree/v3.1.1" }, - "time": "2024-10-01T13:55:55+00:00" + "time": "2026-04-05T21:06:35+00:00" }, { "name": "blade-ui-kit/blade-heroicons", - "version": "2.6.0", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/driesvints/blade-heroicons.git", - "reference": "4553b2a1f6c76f0ac7f3bc0de4c0cfa06a097d19" + "reference": "66fa8ba09dba12e0cdb410b8cb94f3b890eca440" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/driesvints/blade-heroicons/zipball/4553b2a1f6c76f0ac7f3bc0de4c0cfa06a097d19", - "reference": "4553b2a1f6c76f0ac7f3bc0de4c0cfa06a097d19", + "url": "https://api.github.com/repos/driesvints/blade-heroicons/zipball/66fa8ba09dba12e0cdb410b8cb94f3b890eca440", + "reference": "66fa8ba09dba12e0cdb410b8cb94f3b890eca440", "shasum": "" }, "require": { "blade-ui-kit/blade-icons": "^1.6", - "illuminate/support": "^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^9.0|^10.0|^11.0|^12.0|^13.0", "php": "^8.0" }, "require-dev": { - "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", - "phpunit/phpunit": "^9.0|^10.5|^11.0" + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0|^11.0", + "phpunit/phpunit": "^9.0|^10.5|^11.0|^12.0" }, "type": "library", "extra": { @@ -324,7 +324,7 @@ } ], "description": "A package to easily make use of Heroicons in your Laravel Blade views.", - "homepage": "https://github.com/blade-ui-kit/blade-heroicons", + "homepage": "https://github.com/driesvints/blade-heroicons", "keywords": [ "Heroicons", "blade", @@ -332,7 +332,7 @@ ], "support": { "issues": "https://github.com/driesvints/blade-heroicons/issues", - "source": "https://github.com/driesvints/blade-heroicons/tree/2.6.0" + "source": "https://github.com/driesvints/blade-heroicons/tree/2.7.0" }, "funding": [ { @@ -344,20 +344,20 @@ "type": "paypal" } ], - "time": "2025-02-13T20:53:33+00:00" + "time": "2026-03-16T13:00:23+00:00" }, { "name": "blade-ui-kit/blade-icons", - "version": "1.9.0", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/driesvints/blade-icons.git", - "reference": "caa92fde675d7a651c38bf73ca582ddada56f318" + "reference": "74189a80bbaa4966aebaee54fec3a3c2ef0a5f3a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/driesvints/blade-icons/zipball/caa92fde675d7a651c38bf73ca582ddada56f318", - "reference": "caa92fde675d7a651c38bf73ca582ddada56f318", + "url": "https://api.github.com/repos/driesvints/blade-icons/zipball/74189a80bbaa4966aebaee54fec3a3c2ef0a5f3a", + "reference": "74189a80bbaa4966aebaee54fec3a3c2ef0a5f3a", "shasum": "" }, "require": { @@ -425,29 +425,29 @@ "type": "paypal" } ], - "time": "2026-02-23T10:42:23+00:00" + "time": "2026-04-23T19:03:45+00:00" }, { "name": "brick/math", - "version": "0.13.1", + "version": "0.14.8", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" + "reference": "63422359a44b7f06cae63c3b429b59e8efcc0629" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", - "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", + "url": "https://api.github.com/repos/brick/math/zipball/63422359a44b7f06cae63c3b429b59e8efcc0629", + "reference": "63422359a44b7f06cae63c3b429b59e8efcc0629", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^8.2" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^10.1", - "vimeo/psalm": "6.8.8" + "phpstan/phpstan": "2.1.22", + "phpunit/phpunit": "^11.5" }, "type": "library", "autoload": { @@ -477,7 +477,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.13.1" + "source": "https://github.com/brick/math/tree/0.14.8" }, "funding": [ { @@ -485,24 +485,24 @@ "type": "github" } ], - "time": "2025-03-29T13:50:30+00:00" + "time": "2026-02-10T14:33:43+00:00" }, { "name": "brick/money", - "version": "0.10.1", + "version": "0.10.3", "source": { "type": "git", "url": "https://github.com/brick/money.git", - "reference": "779c1d3b708e4dd37fe8a32a189b9f241b52f194" + "reference": "b1b0bb6035d26a58f29b1c06b1265c01a0b5c9c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/money/zipball/779c1d3b708e4dd37fe8a32a189b9f241b52f194", - "reference": "779c1d3b708e4dd37fe8a32a189b9f241b52f194", + "url": "https://api.github.com/repos/brick/money/zipball/b1b0bb6035d26a58f29b1c06b1265c01a0b5c9c3", + "reference": "b1b0bb6035d26a58f29b1c06b1265c01a0b5c9c3", "shasum": "" }, "require": { - "brick/math": "~0.12.0|~0.13.0", + "brick/math": "~0.12.0|~0.13.0|~0.14.0", "php": "^8.1" }, "require-dev": { @@ -534,7 +534,7 @@ ], "support": { "issues": "https://github.com/brick/money/issues", - "source": "https://github.com/brick/money/tree/0.10.1" + "source": "https://github.com/brick/money/tree/0.10.3" }, "funding": [ { @@ -542,7 +542,7 @@ "type": "github" } ], - "time": "2025-03-05T13:00:01+00:00" + "time": "2025-09-03T09:55:48+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -615,16 +615,16 @@ }, { "name": "composer/ca-bundle", - "version": "1.5.10", + "version": "1.5.12", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "961a5e4056dd2e4a2eedcac7576075947c28bf63" + "reference": "00a2f4201641d5c53f7fc0195e6c8d9fcc321a78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/961a5e4056dd2e4a2eedcac7576075947c28bf63", - "reference": "961a5e4056dd2e4a2eedcac7576075947c28bf63", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/00a2f4201641d5c53f7fc0195e6c8d9fcc321a78", + "reference": "00a2f4201641d5c53f7fc0195e6c8d9fcc321a78", "shasum": "" }, "require": { @@ -671,7 +671,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.5.10" + "source": "https://github.com/composer/ca-bundle/tree/1.5.12" }, "funding": [ { @@ -683,20 +683,20 @@ "type": "github" } ], - "time": "2025-12-08T15:06:51+00:00" + "time": "2026-05-19T11:26:22+00:00" }, { "name": "composer/class-map-generator", - "version": "1.7.1", + "version": "1.7.3", "source": { "type": "git", "url": "https://github.com/composer/class-map-generator.git", - "reference": "8f5fa3cc214230e71f54924bd0197a3bcc705eb1" + "reference": "86d8208fc3c649a3a999daf1a63c25201be2990f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/class-map-generator/zipball/8f5fa3cc214230e71f54924bd0197a3bcc705eb1", - "reference": "8f5fa3cc214230e71f54924bd0197a3bcc705eb1", + "url": "https://api.github.com/repos/composer/class-map-generator/zipball/86d8208fc3c649a3a999daf1a63c25201be2990f", + "reference": "86d8208fc3c649a3a999daf1a63c25201be2990f", "shasum": "" }, "require": { @@ -740,7 +740,7 @@ ], "support": { "issues": "https://github.com/composer/class-map-generator/issues", - "source": "https://github.com/composer/class-map-generator/tree/1.7.1" + "source": "https://github.com/composer/class-map-generator/tree/1.7.3" }, "funding": [ { @@ -752,20 +752,20 @@ "type": "github" } ], - "time": "2025-12-29T13:15:25+00:00" + "time": "2026-05-05T09:17:07+00:00" }, { "name": "composer/composer", - "version": "2.9.5", + "version": "2.9.8", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "72a8f8e653710e18d83e5dd531eb5a71fc3223e6" + "reference": "39ee8baff8e97a1b657bbfcd6a236ff93a5efbb2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/72a8f8e653710e18d83e5dd531eb5a71fc3223e6", - "reference": "72a8f8e653710e18d83e5dd531eb5a71fc3223e6", + "url": "https://api.github.com/repos/composer/composer/zipball/39ee8baff8e97a1b657bbfcd6a236ff93a5efbb2", + "reference": "39ee8baff8e97a1b657bbfcd6a236ff93a5efbb2", "shasum": "" }, "require": { @@ -853,7 +853,7 @@ "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/composer/issues", "security": "https://github.com/composer/composer/security/policy", - "source": "https://github.com/composer/composer/tree/2.9.5" + "source": "https://github.com/composer/composer/tree/2.9.8" }, "funding": [ { @@ -865,7 +865,7 @@ "type": "github" } ], - "time": "2026-01-29T10:40:53+00:00" + "time": "2026-05-13T07:28:38+00:00" }, { "name": "composer/metadata-minifier", @@ -1094,24 +1094,24 @@ }, { "name": "composer/spdx-licenses", - "version": "1.5.9", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/composer/spdx-licenses.git", - "reference": "edf364cefe8c43501e21e88110aac10b284c3c9f" + "reference": "5ecd0cb4177696f9fd48f1605dda81db3dee7889" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/edf364cefe8c43501e21e88110aac10b284c3c9f", - "reference": "edf364cefe8c43501e21e88110aac10b284c3c9f", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/5ecd0cb4177696f9fd48f1605dda81db3dee7889", + "reference": "5ecd0cb4177696f9fd48f1605dda81db3dee7889", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" + "php": "^7.2 || ^8.0" }, "require-dev": { "phpstan/phpstan": "^1.11", - "symfony/phpunit-bridge": "^3 || ^7" + "symfony/phpunit-bridge": "^6.4.25 || ^7.3.3 || ^8.0" }, "type": "library", "extra": { @@ -1154,7 +1154,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/spdx-licenses/issues", - "source": "https://github.com/composer/spdx-licenses/tree/1.5.9" + "source": "https://github.com/composer/spdx-licenses/tree/1.6.0" }, "funding": [ { @@ -1164,13 +1164,9 @@ { "url": "https://github.com/composer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2025-05-12T21:07:07+00:00" + "time": "2026-04-08T20:18:39+00:00" }, { "name": "composer/xdebug-handler", @@ -1291,27 +1287,27 @@ }, { "name": "danharrin/livewire-rate-limiting", - "version": "v2.1.0", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/danharrin/livewire-rate-limiting.git", - "reference": "14dde653a9ae8f38af07a0ba4921dc046235e1a0" + "reference": "c03e649220089f6e5a52d422e24e3f98c73e456d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/danharrin/livewire-rate-limiting/zipball/14dde653a9ae8f38af07a0ba4921dc046235e1a0", - "reference": "14dde653a9ae8f38af07a0ba4921dc046235e1a0", + "url": "https://api.github.com/repos/danharrin/livewire-rate-limiting/zipball/c03e649220089f6e5a52d422e24e3f98c73e456d", + "reference": "c03e649220089f6e5a52d422e24e3f98c73e456d", "shasum": "" }, "require": { - "illuminate/support": "^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^9.0|^10.0|^11.0|^12.0|^13.0", "php": "^8.0" }, "require-dev": { "livewire/livewire": "^3.0", "livewire/volt": "^1.3", - "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", - "phpunit/phpunit": "^9.0|^10.0|^11.5.3" + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0|^11.0", + "phpunit/phpunit": "^9.0|^10.0|^11.5.3|^12.5.12" }, "type": "library", "autoload": { @@ -1341,20 +1337,20 @@ "type": "github" } ], - "time": "2025-02-21T08:52:11+00:00" + "time": "2026-03-16T11:29:23+00:00" }, { "name": "dasprid/enum", - "version": "1.0.6", + "version": "1.0.7", "source": { "type": "git", "url": "https://github.com/DASPRiD/Enum.git", - "reference": "8dfd07c6d2cf31c8da90c53b83c026c7696dda90" + "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8dfd07c6d2cf31c8da90c53b83c026c7696dda90", - "reference": "8dfd07c6d2cf31c8da90c53b83c026c7696dda90", + "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/b5874fa9ed0043116c72162ec7f4fb50e02e7cce", + "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce", "shasum": "" }, "require": { @@ -1389,22 +1385,22 @@ ], "support": { "issues": "https://github.com/DASPRiD/Enum/issues", - "source": "https://github.com/DASPRiD/Enum/tree/1.0.6" + "source": "https://github.com/DASPRiD/Enum/tree/1.0.7" }, - "time": "2024-08-09T14:30:48+00:00" + "time": "2025-09-16T12:23:56+00:00" }, { "name": "datomatic/enum-helper", - "version": "v2.0.1", + "version": "v2.1.1", "source": { "type": "git", "url": "https://github.com/datomatic/enum-helper.git", - "reference": "90f1986d755c7d7cc5c716ca9b2cfb1b58adf3d0" + "reference": "b110466a42aa6cb17bc90dd68f13b8598154f972" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/datomatic/enum-helper/zipball/90f1986d755c7d7cc5c716ca9b2cfb1b58adf3d0", - "reference": "90f1986d755c7d7cc5c716ca9b2cfb1b58adf3d0", + "url": "https://api.github.com/repos/datomatic/enum-helper/zipball/b110466a42aa6cb17bc90dd68f13b8598154f972", + "reference": "b110466a42aa6cb17bc90dd68f13b8598154f972", "shasum": "" }, "require": { @@ -1437,29 +1433,29 @@ "description": "Simple opinionated framework agnostic PHP 8.1 enum helper", "support": { "issues": "https://github.com/datomatic/enum-helper/issues", - "source": "https://github.com/datomatic/enum-helper/tree/v2.0.1" + "source": "https://github.com/datomatic/enum-helper/tree/v2.1.1" }, - "time": "2025-02-22T09:51:21+00:00" + "time": "2025-12-29T08:59:22+00:00" }, { "name": "datomatic/laravel-enum-helper", - "version": "v2.1.1", + "version": "v2.1.4", "source": { "type": "git", "url": "https://github.com/datomatic/laravel-enum-helper.git", - "reference": "5ee2d7b30c547b55fb518e266ca491ecbf5d7393" + "reference": "e31b3c13831557276a888eac68d0278e6211335a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/datomatic/laravel-enum-helper/zipball/5ee2d7b30c547b55fb518e266ca491ecbf5d7393", - "reference": "5ee2d7b30c547b55fb518e266ca491ecbf5d7393", + "url": "https://api.github.com/repos/datomatic/laravel-enum-helper/zipball/e31b3c13831557276a888eac68d0278e6211335a", + "reference": "e31b3c13831557276a888eac68d0278e6211335a", "shasum": "" }, "require": { "composer/class-map-generator": "^1.0", "datomatic/enum-helper": "^2.0", - "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/translation": "^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", + "illuminate/translation": "^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", "jawira/case-converter": "^3.5", "laminas/laminas-code": "^4.0", "php": "^8.1" @@ -1467,10 +1463,10 @@ "require-dev": { "friendsofphp/php-cs-fixer": "^3.8", "laravel/pint": "^1.18", - "nunomaduro/larastan": "^2.0", - "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0|^10.0", - "pestphp/pest": "^1.0|^2.0|^3.0", - "pestphp/pest-plugin-laravel": "^1.0|^2.0|^3.0", + "nunomaduro/larastan": "^2.0|^3.0", + "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0|^10.0|^11.0", + "pestphp/pest": "^1.0|^2.0|^3.0|^4.4", + "pestphp/pest-plugin-laravel": "^1.0|^2.0|^3.0|^4.1", "phpstan/phpstan": "^1.7|^2.1" }, "type": "library", @@ -1499,22 +1495,22 @@ "description": "Simple opinionated framework agnostic PHP 8.1 enum helper for Laravel", "support": { "issues": "https://github.com/datomatic/laravel-enum-helper/issues", - "source": "https://github.com/datomatic/laravel-enum-helper/tree/v2.1.1" + "source": "https://github.com/datomatic/laravel-enum-helper/tree/v2.1.4" }, - "time": "2025-03-08T08:26:26+00:00" + "time": "2026-03-17T07:09:51+00:00" }, { "name": "dedoc/scramble", - "version": "v0.12.23", + "version": "v0.12.36", "source": { "type": "git", "url": "https://github.com/dedoc/scramble.git", - "reference": "5b650167c81c59138e844c2ae550c14dc1a249d0" + "reference": "e2741add99b5f9360a7a58a58ce97781569e4cc6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dedoc/scramble/zipball/5b650167c81c59138e844c2ae550c14dc1a249d0", - "reference": "5b650167c81c59138e844c2ae550c14dc1a249d0", + "url": "https://api.github.com/repos/dedoc/scramble/zipball/e2741add99b5f9360a7a58a58ce97781569e4cc6", + "reference": "e2741add99b5f9360a7a58a58ce97781569e4cc6", "shasum": "" }, "require": { @@ -1573,7 +1569,7 @@ ], "support": { "issues": "https://github.com/dedoc/scramble/issues", - "source": "https://github.com/dedoc/scramble/tree/v0.12.23" + "source": "https://github.com/dedoc/scramble/tree/v0.12.36" }, "funding": [ { @@ -1581,7 +1577,7 @@ "type": "github" } ], - "time": "2025-06-15T09:04:49+00:00" + "time": "2025-10-20T08:06:09+00:00" }, { "name": "defuse/php-encryption", @@ -1727,16 +1723,16 @@ }, { "name": "doctrine/dbal", - "version": "4.4.1", + "version": "4.4.3", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "3d544473fb93f5c25b483ea4f4ce99f8c4d9d44c" + "reference": "61e730f1658814821a85f2402c945f3883407dec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/3d544473fb93f5c25b483ea4f4ce99f8c4d9d44c", - "reference": "3d544473fb93f5c25b483ea4f4ce99f8c4d9d44c", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/61e730f1658814821a85f2402c945f3883407dec", + "reference": "61e730f1658814821a85f2402c945f3883407dec", "shasum": "" }, "require": { @@ -1752,9 +1748,9 @@ "phpstan/phpstan": "2.1.30", "phpstan/phpstan-phpunit": "2.0.7", "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "11.5.23", - "slevomat/coding-standard": "8.24.0", - "squizlabs/php_codesniffer": "4.0.0", + "phpunit/phpunit": "11.5.50", + "slevomat/coding-standard": "8.27.1", + "squizlabs/php_codesniffer": "4.0.1", "symfony/cache": "^6.3.8|^7.0|^8.0", "symfony/console": "^5.4|^6.3|^7.0|^8.0" }, @@ -1813,7 +1809,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/4.4.1" + "source": "https://github.com/doctrine/dbal/tree/4.4.3" }, "funding": [ { @@ -1829,7 +1825,7 @@ "type": "tidelift" } ], - "time": "2025-12-04T10:11:03+00:00" + "time": "2026-03-20T08:52:12+00:00" }, { "name": "doctrine/deprecations", @@ -2179,20 +2175,20 @@ }, { "name": "ezyang/htmlpurifier", - "version": "v4.18.0", + "version": "v4.19.0", "source": { "type": "git", "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "cb56001e54359df7ae76dc522d08845dc741621b" + "reference": "b287d2a16aceffbf6e0295559b39662612b77fcf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b", - "reference": "cb56001e54359df7ae76dc522d08845dc741621b", + "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" + "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", @@ -2234,13 +2230,13 @@ ], "support": { "issues": "https://github.com/ezyang/htmlpurifier/issues", - "source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0" + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.19.0" }, - "time": "2024-11-01T03:51:45+00:00" + "time": "2025-10-17T16:34:55+00:00" }, { "name": "filament/actions", - "version": "v3.3.49", + "version": "v3.3.52", "source": { "type": "git", "url": "https://github.com/filamentphp/actions.git", @@ -2293,16 +2289,16 @@ }, { "name": "filament/filament", - "version": "v3.3.49", + "version": "v3.3.52", "source": { "type": "git", "url": "https://github.com/filamentphp/panels.git", - "reference": "6098e568b4257dc438ff68aced0a260f06ba6d52" + "reference": "073e41c0abe78bc2cfcde3a186a40cbed328a6a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/panels/zipball/6098e568b4257dc438ff68aced0a260f06ba6d52", - "reference": "6098e568b4257dc438ff68aced0a260f06ba6d52", + "url": "https://api.github.com/repos/filamentphp/panels/zipball/073e41c0abe78bc2cfcde3a186a40cbed328a6a7", + "reference": "073e41c0abe78bc2cfcde3a186a40cbed328a6a7", "shasum": "" }, "require": { @@ -2354,20 +2350,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2026-02-07T21:52:21+00:00" + "time": "2026-05-21T17:50:14+00:00" }, { "name": "filament/forms", - "version": "v3.3.49", + "version": "v3.3.52", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", - "reference": "c64bf142f808d292b0c6c21fdd3c75cbef9e9d30" + "reference": "67b6dc4cef99d2a9eda916a4202f63985b54ccf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/forms/zipball/c64bf142f808d292b0c6c21fdd3c75cbef9e9d30", - "reference": "c64bf142f808d292b0c6c21fdd3c75cbef9e9d30", + "url": "https://api.github.com/repos/filamentphp/forms/zipball/67b6dc4cef99d2a9eda916a4202f63985b54ccf2", + "reference": "67b6dc4cef99d2a9eda916a4202f63985b54ccf2", "shasum": "" }, "require": { @@ -2410,11 +2406,11 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2026-02-19T23:07:33+00:00" + "time": "2026-05-21T17:51:59+00:00" }, { "name": "filament/infolists", - "version": "v3.3.49", + "version": "v3.3.52", "source": { "type": "git", "url": "https://github.com/filamentphp/infolists.git", @@ -2465,7 +2461,7 @@ }, { "name": "filament/notifications", - "version": "v3.3.49", + "version": "v3.3.52", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", @@ -2517,7 +2513,7 @@ }, { "name": "filament/support", - "version": "v3.3.49", + "version": "v3.3.52", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", @@ -2576,16 +2572,16 @@ }, { "name": "filament/tables", - "version": "v3.3.49", + "version": "v3.3.52", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "fb0ab986950dc8129725f676bdb310851b18403f" + "reference": "6665aa5cc1bfaccd6c1de31b9c64a6f5ee54d937" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/fb0ab986950dc8129725f676bdb310851b18403f", - "reference": "fb0ab986950dc8129725f676bdb310851b18403f", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/6665aa5cc1bfaccd6c1de31b9c64a6f5ee54d937", + "reference": "6665aa5cc1bfaccd6c1de31b9c64a6f5ee54d937", "shasum": "" }, "require": { @@ -2624,11 +2620,11 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2026-02-07T21:52:06+00:00" + "time": "2026-05-20T15:37:01+00:00" }, { "name": "filament/widgets", - "version": "v3.3.49", + "version": "v3.3.52", "source": { "type": "git", "url": "https://github.com/filamentphp/widgets.git", @@ -2672,16 +2668,16 @@ }, { "name": "firebase/php-jwt", - "version": "v6.11.1", + "version": "v7.0.5", "source": { "type": "git", - "url": "https://github.com/firebase/php-jwt.git", - "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66" + "url": "https://github.com/googleapis/php-jwt.git", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/d1e91ecf8c598d073d0995afa8cd5c75c6e19e66", - "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66", + "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/47ad26bab5e7c70ae8a6f08ed25ff83631121380", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380", "shasum": "" }, "require": { @@ -2689,6 +2685,7 @@ }, "require-dev": { "guzzlehttp/guzzle": "^7.4", + "phpfastcache/phpfastcache": "^9.2", "phpspec/prophecy-phpunit": "^2.0", "phpunit/phpunit": "^9.5", "psr/cache": "^2.0||^3.0", @@ -2728,10 +2725,10 @@ "php" ], "support": { - "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.11.1" + "issues": "https://github.com/googleapis/php-jwt/issues", + "source": "https://github.com/googleapis/php-jwt/tree/v7.0.5" }, - "time": "2025-04-09T20:32:01+00:00" + "time": "2026-04-01T20:38:03+00:00" }, { "name": "flowframe/laravel-trend", @@ -2880,32 +2877,32 @@ }, { "name": "gotenberg/gotenberg-php", - "version": "v2.14.0", + "version": "v2.21.0", "source": { "type": "git", "url": "https://github.com/gotenberg/gotenberg-php.git", - "reference": "748efe0a981b3e8eb676593246a75925448324ad" + "reference": "991a618b019d066c84e73b0aadf083887d62549f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/gotenberg/gotenberg-php/zipball/748efe0a981b3e8eb676593246a75925448324ad", - "reference": "748efe0a981b3e8eb676593246a75925448324ad", + "url": "https://api.github.com/repos/gotenberg/gotenberg-php/zipball/991a618b019d066c84e73b0aadf083887d62549f", + "reference": "991a618b019d066c84e73b0aadf083887d62549f", "shasum": "" }, "require": { "ext-json": "*", "ext-mbstring": "*", "guzzlehttp/psr7": "^1 || ^2.1", - "php": "^8.1|^8.2|^8.3|^8.4", + "php": "^8.1|^8.2|^8.3|^8.4|^8.5", "php-http/discovery": "^1.14", "psr/http-client": "^1.0", "psr/http-message": "^1.0|^2.0" }, "require-dev": { - "doctrine/coding-standard": "^12.0", - "pestphp/pest": "^2.28", + "doctrine/coding-standard": "^14.0", "phpstan/phpstan": "^1.12", - "squizlabs/php_codesniffer": "^3.10" + "phpunit/phpunit": "^10.5", + "squizlabs/php_codesniffer": "^4.0" }, "type": "library", "autoload": { @@ -2949,7 +2946,7 @@ ], "support": { "issues": "https://github.com/gotenberg/gotenberg-php/issues", - "source": "https://github.com/gotenberg/gotenberg-php/tree/v2.14.0" + "source": "https://github.com/gotenberg/gotenberg-php/tree/v2.21.0" }, "funding": [ { @@ -2957,7 +2954,7 @@ "type": "github" } ], - "time": "2025-05-20T10:00:34+00:00" + "time": "2026-04-17T13:26:28+00:00" }, { "name": "graham-campbell/result-type", @@ -3023,16 +3020,16 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.10.0", + "version": "7.10.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" + "reference": "47ba23c7a55247e2e1b7407aca90e9bbed0d9d86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", - "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/47ba23c7a55247e2e1b7407aca90e9bbed0d9d86", + "reference": "47ba23c7a55247e2e1b7407aca90e9bbed0d9d86", "shasum": "" }, "require": { @@ -3050,8 +3047,9 @@ "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", "guzzle/client-integration-tests": "3.0.2", + "guzzlehttp/test-server": "^0.3.2", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "phpunit/phpunit": "^8.5.52 || ^9.6.34", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -3129,7 +3127,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.10.3" }, "funding": [ { @@ -3145,20 +3143,20 @@ "type": "tidelift" } ], - "time": "2025-08-23T22:36:01+00:00" + "time": "2026-05-20T22:59:19+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.3.0", + "version": "2.4.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "481557b130ef3790cf82b713667b43030dc9c957" + "reference": "09e8a212562fb1fb6a512c4156ed71525969d6c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", - "reference": "481557b130ef3790cf82b713667b43030dc9c957", + "url": "https://api.github.com/repos/guzzle/promises/zipball/09e8a212562fb1fb6a512c4156ed71525969d6c2", + "reference": "09e8a212562fb1fb6a512c4156ed71525969d6c2", "shasum": "" }, "require": { @@ -3166,7 +3164,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.44 || ^9.6.25" + "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "type": "library", "extra": { @@ -3212,7 +3210,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.4.1" }, "funding": [ { @@ -3228,20 +3226,20 @@ "type": "tidelift" } ], - "time": "2025-08-22T14:34:08+00:00" + "time": "2026-05-20T22:57:30+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.8.0", + "version": "2.10.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "21dc724a0583619cd1652f673303492272778051" + "reference": "73ab136360b5dfd858006eae9795e8fe43c80361" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", - "reference": "21dc724a0583619cd1652f673303492272778051", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/73ab136360b5dfd858006eae9795e8fe43c80361", + "reference": "73ab136360b5dfd858006eae9795e8fe43c80361", "shasum": "" }, "require": { @@ -3256,8 +3254,9 @@ }, "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" + "http-interop/http-factory-tests": "1.1.0", + "jshttp/mime-db": "1.54.0.1", + "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -3328,7 +3327,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.10.1" }, "funding": [ { @@ -3344,7 +3343,7 @@ "type": "tidelift" } ], - "time": "2025-08-23T21:21:41+00:00" + "time": "2026-05-20T09:27:36+00:00" }, { "name": "guzzlehttp/uri-template", @@ -3434,29 +3433,34 @@ }, { "name": "inertiajs/inertia-laravel", - "version": "v2.0.3", + "version": "v2.0.24", "source": { "type": "git", "url": "https://github.com/inertiajs/inertia-laravel.git", - "reference": "b732a5cc33423b2c2366fea38b17dc637d2a0b4f" + "reference": "ea345adad12f110edbbc4bef03b69c2374a535d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/b732a5cc33423b2c2366fea38b17dc637d2a0b4f", - "reference": "b732a5cc33423b2c2366fea38b17dc637d2a0b4f", + "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/ea345adad12f110edbbc4bef03b69c2374a535d4", + "reference": "ea345adad12f110edbbc4bef03b69c2374a535d4", "shasum": "" }, "require": { "ext-json": "*", - "laravel/framework": "^10.0|^11.0|^12.0", + "laravel/framework": "^10.0|^11.0|^12.0|^13.0", "php": "^8.1.0", - "symfony/console": "^6.2|^7.0" + "symfony/console": "^6.2|^7.0|^8.0" + }, + "conflict": { + "laravel/boost": "<2.2.0" }, "require-dev": { + "guzzlehttp/guzzle": "^7.2", + "larastan/larastan": "^3.0", "laravel/pint": "^1.16", "mockery/mockery": "^1.3.3", - "orchestra/testbench": "^8.0|^9.2|^10.0", - "phpunit/phpunit": "^10.4|^11.5", + "orchestra/testbench": "^8.0|^9.2|^10.0|^11.0", + "phpunit/phpunit": "^10.4|^11.5|^12.0", "roave/security-advisories": "dev-master" }, "suggest": { @@ -3496,9 +3500,9 @@ ], "support": { "issues": "https://github.com/inertiajs/inertia-laravel/issues", - "source": "https://github.com/inertiajs/inertia-laravel/tree/v2.0.3" + "source": "https://github.com/inertiajs/inertia-laravel/tree/v2.0.24" }, - "time": "2025-06-20T07:38:21+00:00" + "time": "2026-04-10T14:36:44+00:00" }, { "name": "jawira/case-converter", @@ -3568,16 +3572,16 @@ }, { "name": "justinrainbow/json-schema", - "version": "v6.7.2", + "version": "6.8.2", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "6fea66c7204683af437864e7c4e7abf383d14bc0" + "reference": "2c89ebb95ca9cedc9347f780333f7b25792dcb76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/6fea66c7204683af437864e7c4e7abf383d14bc0", - "reference": "6fea66c7204683af437864e7c4e7abf383d14bc0", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/2c89ebb95ca9cedc9347f780333f7b25792dcb76", + "reference": "2c89ebb95ca9cedc9347f780333f7b25792dcb76", "shasum": "" }, "require": { @@ -3587,7 +3591,7 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "3.3.0", - "json-schema/json-schema-test-suite": "^23.2", + "json-schema/json-schema-test-suite": "dev-main", "marc-mabe/php-enum-phpstan": "^2.0", "phpspec/prophecy": "^1.19", "phpstan/phpstan": "^1.12", @@ -3637,34 +3641,34 @@ ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/v6.7.2" + "source": "https://github.com/jsonrainbow/json-schema/tree/6.8.2" }, - "time": "2026-02-15T15:06:22+00:00" + "time": "2026-05-05T05:39:01+00:00" }, { "name": "kirschbaum-development/eloquent-power-joins", - "version": "4.2.11", + "version": "4.3.1", "source": { "type": "git", "url": "https://github.com/kirschbaum-development/eloquent-power-joins.git", - "reference": "0e3e3372992e4bf82391b3c7b84b435c3db73588" + "reference": "3f77b096c1e8b5aa1fc40d7080e55e795f3430ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kirschbaum-development/eloquent-power-joins/zipball/0e3e3372992e4bf82391b3c7b84b435c3db73588", - "reference": "0e3e3372992e4bf82391b3c7b84b435c3db73588", + "url": "https://api.github.com/repos/kirschbaum-development/eloquent-power-joins/zipball/3f77b096c1e8b5aa1fc40d7080e55e795f3430ae", + "reference": "3f77b096c1e8b5aa1fc40d7080e55e795f3430ae", "shasum": "" }, "require": { - "illuminate/database": "^11.42|^12.0", - "illuminate/support": "^11.42|^12.0", + "illuminate/database": "^11.42|^12.0|^13.0", + "illuminate/support": "^11.42|^12.0|^13.0", "php": "^8.2" }, "require-dev": { "friendsofphp/php-cs-fixer": "dev-master", - "laravel/legacy-factories": "^1.0@dev", - "orchestra/testbench": "^9.0|^10.0", - "phpunit/phpunit": "^10.0|^11.0" + "laravel/legacy-factories": "^1.0@dev|dev-master", + "orchestra/testbench": "^9.0|^10.0|^11.0", + "phpunit/phpunit": "^10.0|^11.0|^12.0" }, "type": "library", "extra": { @@ -3700,35 +3704,35 @@ ], "support": { "issues": "https://github.com/kirschbaum-development/eloquent-power-joins/issues", - "source": "https://github.com/kirschbaum-development/eloquent-power-joins/tree/4.2.11" + "source": "https://github.com/kirschbaum-development/eloquent-power-joins/tree/4.3.1" }, - "time": "2025-12-17T00:37:48+00:00" + "time": "2026-03-29T12:05:03+00:00" }, { "name": "korridor/laravel-computed-attributes", - "version": "3.2.0", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/korridor/laravel-computed-attributes.git", - "reference": "1520dd986022d9bc25fa7d1383b8f7c648efc08e" + "reference": "d17908ca6709827f7b2d2e613bf0c5245c015d4d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/korridor/laravel-computed-attributes/zipball/1520dd986022d9bc25fa7d1383b8f7c648efc08e", - "reference": "1520dd986022d9bc25fa7d1383b8f7c648efc08e", + "url": "https://api.github.com/repos/korridor/laravel-computed-attributes/zipball/d17908ca6709827f7b2d2e613bf0c5245c015d4d", + "reference": "d17908ca6709827f7b2d2e613bf0c5245c015d4d", "shasum": "" }, "require": { "composer/composer": "^2", - "illuminate/console": "^10|^11|^12", - "illuminate/database": "^10|^11|^12", - "illuminate/support": "^10|^11|^12", + "illuminate/console": "^10|^11|^12|^13", + "illuminate/database": "^10|^11|^12|^13", + "illuminate/support": "^10|^11|^12|^13", "php": ">=8.1" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", "larastan/larastan": "^2|^3", - "orchestra/testbench": "^8|^9|^10", + "orchestra/testbench": "^8|^9|^10|^11", "phpunit/phpunit": "^10|^11", "squizlabs/php_codesniffer": "^3.5" }, @@ -3769,33 +3773,33 @@ ], "support": { "issues": "https://github.com/korridor/laravel-computed-attributes/issues", - "source": "https://github.com/korridor/laravel-computed-attributes/tree/3.2.0" + "source": "https://github.com/korridor/laravel-computed-attributes/tree/3.3.0" }, - "time": "2025-03-03T22:51:11+00:00" + "time": "2026-05-11T20:22:44+00:00" }, { "name": "korridor/laravel-has-many-sync", - "version": "3.1.0", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/korridor/laravel-has-many-sync.git", - "reference": "32344956730d306d9753f5d3c455650ed828fd4e" + "reference": "a4d170b708d0142b713f8dc5029b3d1195fe624b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/korridor/laravel-has-many-sync/zipball/32344956730d306d9753f5d3c455650ed828fd4e", - "reference": "32344956730d306d9753f5d3c455650ed828fd4e", + "url": "https://api.github.com/repos/korridor/laravel-has-many-sync/zipball/a4d170b708d0142b713f8dc5029b3d1195fe624b", + "reference": "a4d170b708d0142b713f8dc5029b3d1195fe624b", "shasum": "" }, "require": { - "illuminate/database": "^10|^11|^12", - "illuminate/support": "^10|^11|^12", + "illuminate/database": "^10|^11|^12|^13", + "illuminate/support": "^10|^11|^12|^13", "php": ">=8.1" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", - "larastan/larastan": "^2|^3.0", - "orchestra/testbench": "^8|^9|^10", + "larastan/larastan": "^2|^3", + "orchestra/testbench": "^8|^9|^10|^11", "phpunit/phpunit": "^10.0|^11.5", "squizlabs/php_codesniffer": "^3.5" }, @@ -3836,31 +3840,32 @@ "sync" ], "support": { - "source": "https://github.com/korridor/laravel-has-many-sync/tree/3.1.0" + "source": "https://github.com/korridor/laravel-has-many-sync/tree/3.2.0" }, - "time": "2025-03-03T20:58:17+00:00" + "time": "2026-04-16T18:01:53+00:00" }, { "name": "korridor/laravel-model-validation-rules", - "version": "3.3.0", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/korridor/laravel-model-validation-rules.git", - "reference": "3f79b11c447cf11c28f586fc3740e1a650900294" + "reference": "e0043fd4ad6e336fb6137935e72fc23a094876ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/korridor/laravel-model-validation-rules/zipball/3f79b11c447cf11c28f586fc3740e1a650900294", - "reference": "3f79b11c447cf11c28f586fc3740e1a650900294", + "url": "https://api.github.com/repos/korridor/laravel-model-validation-rules/zipball/e0043fd4ad6e336fb6137935e72fc23a094876ca", + "reference": "e0043fd4ad6e336fb6137935e72fc23a094876ca", "shasum": "" }, "require": { - "illuminate/database": "^10|^11|^12.0", - "illuminate/support": "^10|^11|^12.0", + "illuminate/database": "^10|^11|^12|^13", + "illuminate/support": "^10|^11|^12|^13", "php": ">=8.1" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.6", + "larastan/larastan": "^3.0", "orchestra/testbench": "^8.0|^9.0|^10.0", "phpunit/phpunit": "^10|^11.5.3", "squizlabs/php_codesniffer": "^3.5" @@ -3900,31 +3905,31 @@ ], "support": { "issues": "https://github.com/korridor/laravel-model-validation-rules/issues", - "source": "https://github.com/korridor/laravel-model-validation-rules/tree/3.3.0" + "source": "https://github.com/korridor/laravel-model-validation-rules/tree/3.4.0" }, - "time": "2025-02-27T16:07:12+00:00" + "time": "2026-04-16T11:39:22+00:00" }, { "name": "lab404/laravel-impersonate", - "version": "1.7.7", + "version": "1.7.8", "source": { "type": "git", "url": "https://github.com/404labfr/laravel-impersonate.git", - "reference": "5033f3433a55ca8bb2cc3e4a018a39dd8a327a9f" + "reference": "0008a39da8914cc946b6a5ed211230708ee736b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/404labfr/laravel-impersonate/zipball/5033f3433a55ca8bb2cc3e4a018a39dd8a327a9f", - "reference": "5033f3433a55ca8bb2cc3e4a018a39dd8a327a9f", + "url": "https://api.github.com/repos/404labfr/laravel-impersonate/zipball/0008a39da8914cc946b6a5ed211230708ee736b3", + "reference": "0008a39da8914cc946b6a5ed211230708ee736b3", "shasum": "" }, "require": { - "laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0", + "laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0 | ^13.0", "php": "^7.2 | ^8.0" }, "require-dev": { "mockery/mockery": "^1.3.3", - "orchestra/testbench": "^4.0 | ^5.0 | ^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0", + "orchestra/testbench": "^4.0 | ^5.0 | ^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0", "phpunit/phpunit": "^7.5 | ^8.0 | ^9.0 | ^10.0 | ^11.0" }, "type": "library", @@ -3967,33 +3972,33 @@ ], "support": { "issues": "https://github.com/404labfr/laravel-impersonate/issues", - "source": "https://github.com/404labfr/laravel-impersonate/tree/1.7.7" + "source": "https://github.com/404labfr/laravel-impersonate/tree/1.7.8" }, - "time": "2025-02-24T16:18:38+00:00" + "time": "2026-03-17T15:24:14+00:00" }, { "name": "laminas/laminas-code", - "version": "4.16.0", + "version": "4.17.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-code.git", - "reference": "1793e78dad4108b594084d05d1fb818b85b110af" + "reference": "40d61e2899ec17c5d08bbc0a2d586b3ca17ab9bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-code/zipball/1793e78dad4108b594084d05d1fb818b85b110af", - "reference": "1793e78dad4108b594084d05d1fb818b85b110af", + "url": "https://api.github.com/repos/laminas/laminas-code/zipball/40d61e2899ec17c5d08bbc0a2d586b3ca17ab9bd", + "reference": "40d61e2899ec17c5d08bbc0a2d586b3ca17ab9bd", "shasum": "" }, "require": { - "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { "doctrine/annotations": "^2.0.1", "ext-phar": "*", "laminas/laminas-coding-standard": "^3.0.0", "laminas/laminas-stdlib": "^3.18.0", - "phpunit/phpunit": "^10.5.37", + "phpunit/phpunit": "^10.5.58", "psalm/plugin-phpunit": "^0.19.0", "vimeo/psalm": "^5.15.0" }, @@ -4032,24 +4037,24 @@ "type": "community_bridge" } ], - "time": "2024-11-20T13:15:13+00:00" + "time": "2025-11-01T09:38:14+00:00" }, { "name": "laminas/laminas-diactoros", - "version": "3.6.0", + "version": "3.8.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-diactoros.git", - "reference": "b068eac123f21c0e592de41deeb7403b88e0a89f" + "reference": "60c182916b2749480895601649563970f3f12ec4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/b068eac123f21c0e592de41deeb7403b88e0a89f", - "reference": "b068eac123f21c0e592de41deeb7403b88e0a89f", + "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/60c182916b2749480895601649563970f3f12ec4", + "reference": "60c182916b2749480895601649563970f3f12ec4", "shasum": "" }, "require": { - "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", "psr/http-factory": "^1.1", "psr/http-message": "^1.1 || ^2.0" }, @@ -4066,11 +4071,11 @@ "ext-gd": "*", "ext-libxml": "*", "http-interop/http-factory-tests": "^2.2.0", - "laminas/laminas-coding-standard": "~3.0.0", + "laminas/laminas-coding-standard": "~3.1.0", "php-http/psr7-integration-tests": "^1.4.0", "phpunit/phpunit": "^10.5.36", - "psalm/plugin-phpunit": "^0.19.0", - "vimeo/psalm": "^5.26.1" + "psalm/plugin-phpunit": "^0.19.5", + "vimeo/psalm": "^6.13" }, "type": "library", "extra": { @@ -4120,35 +4125,34 @@ "type": "community_bridge" } ], - "time": "2025-05-05T16:03:34+00:00" + "time": "2025-10-12T15:31:36+00:00" }, { "name": "laravel/fortify", - "version": "v1.27.0", + "version": "v1.37.2", "source": { "type": "git", "url": "https://github.com/laravel/fortify.git", - "reference": "0fb2ec99dfee77ed66884668fc06683acca91ebd" + "reference": "5d4b6a53527edd19ecc4f13e8e74ec91bdefab0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/fortify/zipball/0fb2ec99dfee77ed66884668fc06683acca91ebd", - "reference": "0fb2ec99dfee77ed66884668fc06683acca91ebd", + "url": "https://api.github.com/repos/laravel/fortify/zipball/5d4b6a53527edd19ecc4f13e8e74ec91bdefab0c", + "reference": "5d4b6a53527edd19ecc4f13e8e74ec91bdefab0c", "shasum": "" }, "require": { "bacon/bacon-qr-code": "^3.0", "ext-json": "*", - "illuminate/support": "^10.0|^11.0|^12.0", - "php": "^8.1", - "pragmarx/google2fa": "^8.0", - "symfony/console": "^6.0|^7.0" + "illuminate/console": "^11.0|^12.0|^13.0", + "illuminate/support": "^11.0|^12.0|^13.0", + "laravel/passkeys": "^0.2.0", + "php": "^8.2", + "pragmarx/google2fa": "^9.0" }, "require-dev": { - "mockery/mockery": "^1.0", - "orchestra/testbench": "^8.16|^9.0|^10.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.4|^11.3" + "orchestra/testbench": "^9.15|^10.8|^11.0", + "phpstan/phpstan": "^1.10" }, "type": "library", "extra": { @@ -4185,20 +4189,20 @@ "issues": "https://github.com/laravel/fortify/issues", "source": "https://github.com/laravel/fortify" }, - "time": "2025-06-11T14:30:52+00:00" + "time": "2026-05-15T22:59:10+00:00" }, { "name": "laravel/framework", - "version": "v12.52.0", + "version": "v12.60.2", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "d5511fa74f4608dbb99864198b1954042aa8d5a7" + "reference": "b8b55ce32175cc00f834a56eeb6316f18ed6ea39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/d5511fa74f4608dbb99864198b1954042aa8d5a7", - "reference": "d5511fa74f4608dbb99864198b1954042aa8d5a7", + "url": "https://api.github.com/repos/laravel/framework/zipball/b8b55ce32175cc00f834a56eeb6316f18ed6ea39", + "reference": "b8b55ce32175cc00f834a56eeb6316f18ed6ea39", "shasum": "" }, "require": { @@ -4219,7 +4223,7 @@ "guzzlehttp/uri-template": "^1.0", "laravel/prompts": "^0.3.0", "laravel/serializable-closure": "^1.3|^2.0", - "league/commonmark": "^2.7", + "league/commonmark": "^2.8.1", "league/flysystem": "^3.25.1", "league/flysystem-local": "^3.25.1", "league/uri": "^7.5.1", @@ -4239,8 +4243,8 @@ "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-php84": "^1.34", + "symfony/polyfill-php85": "^1.34", "symfony/process": "^7.2.0", "symfony/routing": "^7.2.0", "symfony/uid": "^7.2.0", @@ -4314,7 +4318,7 @@ "orchestra/testbench-core": "^10.9.0", "pda/pheanstalk": "^5.0.6|^7.0.0", "php-http/discovery": "^1.15", - "phpstan/phpstan": "^2.0", + "phpstan/phpstan": "^2.1.41", "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", @@ -4407,98 +4411,31 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2026-02-17T17:07:04+00:00" - }, - { - "name": "laravel/jetstream", - "version": "v5.3.7", - "source": { - "type": "git", - "url": "https://github.com/laravel/jetstream.git", - "reference": "b606c21daeaa38547f853789212e3802b0f6ff08" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/jetstream/zipball/b606c21daeaa38547f853789212e3802b0f6ff08", - "reference": "b606c21daeaa38547f853789212e3802b0f6ff08", - "shasum": "" - }, - "require": { - "ext-json": "*", - "illuminate/console": "^11.0|^12.0", - "illuminate/support": "^11.0|^12.0", - "laravel/fortify": "^1.20", - "mobiledetect/mobiledetectlib": "^4.8.08", - "php": "^8.2.0", - "symfony/console": "^7.0" - }, - "require-dev": { - "inertiajs/inertia-laravel": "^2.0", - "laravel/sanctum": "^4.0", - "livewire/livewire": "^3.3", - "mockery/mockery": "^1.0", - "orchestra/testbench": "^9.0|^10.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Laravel\\Jetstream\\JetstreamServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Laravel\\Jetstream\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Tailwind scaffolding for the Laravel framework.", - "keywords": [ - "auth", - "laravel", - "tailwind" - ], - "support": { - "issues": "https://github.com/laravel/jetstream/issues", - "source": "https://github.com/laravel/jetstream" - }, - "time": "2025-06-16T13:27:00+00:00" + "time": "2026-05-20T11:48:19+00:00" }, { "name": "laravel/octane", - "version": "v2.11.0", + "version": "v2.17.4", "source": { "type": "git", "url": "https://github.com/laravel/octane.git", - "reference": "00e4d40047a24c267c9d3d0abfb47a6e27a7dc7f" + "reference": "ffeac11324accc6edf8df426ba4541f3171d494e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/octane/zipball/00e4d40047a24c267c9d3d0abfb47a6e27a7dc7f", - "reference": "00e4d40047a24c267c9d3d0abfb47a6e27a7dc7f", + "url": "https://api.github.com/repos/laravel/octane/zipball/ffeac11324accc6edf8df426ba4541f3171d494e", + "reference": "ffeac11324accc6edf8df426ba4541f3171d494e", "shasum": "" }, "require": { "laminas/laminas-diactoros": "^3.0", - "laravel/framework": "^10.10.1|^11.0|^12.0", + "laravel/framework": "^10.10.1|^11.0|^12.0|^13.0", "laravel/prompts": "^0.1.24|^0.2.0|^0.3.0", "laravel/serializable-closure": "^1.3|^2.0", "nesbot/carbon": "^2.66.0|^3.0", "php": "^8.1.0", - "symfony/console": "^6.0|^7.0", - "symfony/psr-http-message-bridge": "^2.2.0|^6.4|^7.0" + "symfony/console": "^6.0|^7.0|^8.0", + "symfony/psr-http-message-bridge": "^2.2.0|^6.4|^7.0|^8.0" }, "conflict": { "spiral/roadrunner": "<2023.1.0", @@ -4511,11 +4448,10 @@ "laravel/scout": "^10.2.1", "laravel/socialite": "^5.6.1", "livewire/livewire": "^2.12.3|^3.0", - "mockery/mockery": "^1.5.1", "nunomaduro/collision": "^6.4.0|^7.5.2|^8.0", - "orchestra/testbench": "^8.21|^9.0|^10.0", + "orchestra/testbench": "^8.21|^9.0|^10.0|^11.0", "phpstan/phpstan": "^2.1.7", - "phpunit/phpunit": "^10.4|^11.5", + "phpunit/phpunit": "^10.4|^11.5|^12.0|^13.0", "spiral/roadrunner-cli": "^2.6.0", "spiral/roadrunner-http": "^3.3.0" }, @@ -4564,48 +4500,114 @@ "issues": "https://github.com/laravel/octane/issues", "source": "https://github.com/laravel/octane" }, - "time": "2025-06-28T17:28:13+00:00" + "time": "2026-05-22T11:30:06+00:00" + }, + { + "name": "laravel/passkeys", + "version": "v0.2.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/passkeys-server.git", + "reference": "a76656ada41b2b4a591f075eddae5ddc67e8ab9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/passkeys-server/zipball/a76656ada41b2b4a591f075eddae5ddc67e8ab9c", + "reference": "a76656ada41b2b4a591f075eddae5ddc67e8ab9c", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^11.0|^12.0|^13.0", + "illuminate/database": "^11.0|^12.0|^13.0", + "illuminate/http": "^11.0|^12.0|^13.0", + "illuminate/routing": "^11.0|^12.0|^13.0", + "illuminate/support": "^11.0|^12.0|^13.0", + "php": "^8.2", + "web-auth/webauthn-lib": "5.3.x" + }, + "require-dev": { + "laravel/pint": "^1.28.0", + "orchestra/testbench": "^9.0|^10.0|^11.0", + "pestphp/pest": "^3.0|^4.0", + "phpstan/phpstan": "^2.0", + "rector/rector": "^2.3" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Passkeys\\PasskeysServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Passkeys\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Passwordless authentication using WebAuthn/passkeys for Laravel", + "homepage": "https://github.com/laravel/passkeys-server", + "keywords": [ + "Authentication", + "Passwordless", + "laravel", + "passkeys", + "webauthn" + ], + "support": { + "issues": "https://github.com/laravel/passkeys-server/issues", + "source": "https://github.com/laravel/passkeys-server" + }, + "time": "2026-05-18T16:26:00+00:00" }, { "name": "laravel/passport", - "version": "v13.0.5", + "version": "v13.7.5", "source": { "type": "git", "url": "https://github.com/laravel/passport.git", - "reference": "9a3b47bc784dc9334aad67f690b13230b0434960" + "reference": "90053dc4ba681c076855779250109bb624f961f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/passport/zipball/9a3b47bc784dc9334aad67f690b13230b0434960", - "reference": "9a3b47bc784dc9334aad67f690b13230b0434960", + "url": "https://api.github.com/repos/laravel/passport/zipball/90053dc4ba681c076855779250109bb624f961f6", + "reference": "90053dc4ba681c076855779250109bb624f961f6", "shasum": "" }, "require": { "ext-json": "*", "ext-openssl": "*", - "firebase/php-jwt": "^6.4", - "illuminate/auth": "^11.35|^12.0", - "illuminate/console": "^11.35|^12.0", - "illuminate/container": "^11.35|^12.0", - "illuminate/contracts": "^11.35|^12.0", - "illuminate/cookie": "^11.35|^12.0", - "illuminate/database": "^11.35|^12.0", - "illuminate/encryption": "^11.35|^12.0", - "illuminate/http": "^11.35|^12.0", - "illuminate/support": "^11.35|^12.0", + "firebase/php-jwt": "^6.4|^7.0", + "illuminate/auth": "^11.35|^12.0|^13.0", + "illuminate/console": "^11.35|^12.0|^13.0", + "illuminate/container": "^11.35|^12.0|^13.0", + "illuminate/contracts": "^11.35|^12.0|^13.0", + "illuminate/cookie": "^11.35|^12.0|^13.0", + "illuminate/database": "^11.35|^12.0|^13.0", + "illuminate/encryption": "^11.35|^12.0|^13.0", + "illuminate/http": "^11.35|^12.0|^13.0", + "illuminate/support": "^11.35|^12.0|^13.0", "league/oauth2-server": "^9.2", "php": "^8.2", "php-http/discovery": "^1.20", "phpseclib/phpseclib": "^3.0", "psr/http-factory-implementation": "*", - "symfony/console": "^7.1", - "symfony/psr-http-message-bridge": "^7.1" + "symfony/console": "^7.1|^8.0", + "symfony/psr-http-message-bridge": "^7.1|^8.0" }, "require-dev": { - "mockery/mockery": "^1.6", - "orchestra/testbench": "^9.9|^10.0", - "phpstan/phpstan": "^2.0", - "phpunit/phpunit": "^11.5|^12.0" + "orchestra/testbench": "^9.15|^10.8|^11.0", + "phpstan/phpstan": "^2.0" }, "type": "library", "extra": { @@ -4641,20 +4643,20 @@ "issues": "https://github.com/laravel/passport/issues", "source": "https://github.com/laravel/passport" }, - "time": "2025-06-12T15:12:08+00:00" + "time": "2026-04-16T14:00:29+00:00" }, { "name": "laravel/prompts", - "version": "v0.3.13", + "version": "v0.3.18", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "ed8c466571b37e977532fb2fd3c272c784d7050d" + "reference": "a19af51bb144bf87f08397921fa619f85c7d4e72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/ed8c466571b37e977532fb2fd3c272c784d7050d", - "reference": "ed8c466571b37e977532fb2fd3c272c784d7050d", + "url": "https://api.github.com/repos/laravel/prompts/zipball/a19af51bb144bf87f08397921fa619f85c7d4e72", + "reference": "a19af51bb144bf87f08397921fa619f85c7d4e72", "shasum": "" }, "require": { @@ -4698,22 +4700,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.13" + "source": "https://github.com/laravel/prompts/tree/v0.3.18" }, - "time": "2026-02-06T12:17:10+00:00" + "time": "2026-05-19T00:47:18+00:00" }, { "name": "laravel/serializable-closure", - "version": "v2.0.9", + "version": "v2.0.13", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "8f631589ab07b7b52fead814965f5a800459cb3e" + "reference": "b566ee0dd251f3c4078bed003a7ce015f5ea6dce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/8f631589ab07b7b52fead814965f5a800459cb3e", - "reference": "8f631589ab07b7b52fead814965f5a800459cb3e", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b566ee0dd251f3c4078bed003a7ce015f5ea6dce", + "reference": "b566ee0dd251f3c4078bed003a7ce015f5ea6dce", "shasum": "" }, "require": { @@ -4761,20 +4763,20 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2026-02-03T06:55:34+00:00" + "time": "2026-04-16T14:03:50+00:00" }, { "name": "laravel/tinker", - "version": "v2.10.1", + "version": "v2.11.1", "source": { "type": "git", "url": "https://github.com/laravel/tinker.git", - "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3" + "reference": "c9f80cc835649b5c1842898fb043f8cc098dd741" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/tinker/zipball/22177cc71807d38f2810c6204d8f7183d88a57d3", - "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3", + "url": "https://api.github.com/repos/laravel/tinker/zipball/c9f80cc835649b5c1842898fb043f8cc098dd741", + "reference": "c9f80cc835649b5c1842898fb043f8cc098dd741", "shasum": "" }, "require": { @@ -4783,7 +4785,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" + "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0|^8.0" }, "require-dev": { "mockery/mockery": "~1.3.3|^1.4.2", @@ -4825,40 +4827,40 @@ ], "support": { "issues": "https://github.com/laravel/tinker/issues", - "source": "https://github.com/laravel/tinker/tree/v2.10.1" + "source": "https://github.com/laravel/tinker/tree/v2.11.1" }, - "time": "2025-01-27T14:24:01+00:00" + "time": "2026-02-06T14:12:35+00:00" }, { "name": "lcobucci/clock", - "version": "3.3.1", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/lcobucci/clock.git", - "reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b" + "reference": "a3139d9e97d47826f27e6a17bb63f13621f86058" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/db3713a61addfffd615b79bf0bc22f0ccc61b86b", - "reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/a3139d9e97d47826f27e6a17bb63f13621f86058", + "reference": "a3139d9e97d47826f27e6a17bb63f13621f86058", "shasum": "" }, "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0", + "php": "~8.3.0 || ~8.4.0 || ~8.5.0", "psr/clock": "^1.0" }, "provide": { "psr/clock-implementation": "1.0" }, "require-dev": { - "infection/infection": "^0.29", - "lcobucci/coding-standard": "^11.1.0", + "infection/infection": "^0.31", + "lcobucci/coding-standard": "^11.2.0", "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan": "^1.10.25", - "phpstan/phpstan-deprecation-rules": "^1.1.3", - "phpstan/phpstan-phpunit": "^1.3.13", - "phpstan/phpstan-strict-rules": "^1.5.1", - "phpunit/phpunit": "^11.3.6" + "phpstan/phpstan": "^2.0.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0.0", + "phpstan/phpstan-strict-rules": "^2.0.0", + "phpunit/phpunit": "^12.0.0" }, "type": "library", "autoload": { @@ -4879,7 +4881,7 @@ "description": "Yet another clock abstraction", "support": { "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/3.3.1" + "source": "https://github.com/lcobucci/clock/tree/3.5.0" }, "funding": [ { @@ -4891,26 +4893,26 @@ "type": "patreon" } ], - "time": "2024-09-24T20:45:14+00:00" + "time": "2025-10-27T09:03:17+00:00" }, { "name": "lcobucci/jwt", - "version": "5.5.0", + "version": "5.6.0", "source": { "type": "git", "url": "https://github.com/lcobucci/jwt.git", - "reference": "a835af59b030d3f2967725697cf88300f579088e" + "reference": "bb3e9f21e4196e8afc41def81ef649c164bca25e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/jwt/zipball/a835af59b030d3f2967725697cf88300f579088e", - "reference": "a835af59b030d3f2967725697cf88300f579088e", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/bb3e9f21e4196e8afc41def81ef649c164bca25e", + "reference": "bb3e9f21e4196e8afc41def81ef649c164bca25e", "shasum": "" }, "require": { "ext-openssl": "*", "ext-sodium": "*", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", "psr/clock": "^1.0" }, "require-dev": { @@ -4952,7 +4954,7 @@ ], "support": { "issues": "https://github.com/lcobucci/jwt/issues", - "source": "https://github.com/lcobucci/jwt/tree/5.5.0" + "source": "https://github.com/lcobucci/jwt/tree/5.6.0" }, "funding": [ { @@ -4964,20 +4966,20 @@ "type": "patreon" } ], - "time": "2025-01-26T21:29:45+00:00" + "time": "2025-10-17T11:30:53+00:00" }, { "name": "league/commonmark", - "version": "2.8.0", + "version": "2.8.2", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb" + "reference": "59fb075d2101740c337c7216e3f32b36c204218b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4efa10c1e56488e658d10adf7b7b7dcd19940bfb", - "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/59fb075d2101740c337c7216e3f32b36c204218b", + "reference": "59fb075d2101740c337c7216e3f32b36c204218b", "shasum": "" }, "require": { @@ -5002,9 +5004,9 @@ "phpstan/phpstan": "^1.8.2", "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", "scrutinizer/ocular": "^1.8.1", - "symfony/finder": "^5.3 | ^6.0 | ^7.0", - "symfony/process": "^5.4 | ^6.0 | ^7.0", - "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", + "symfony/finder": "^5.3 | ^6.0 | ^7.0 || ^8.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0 || ^8.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0 || ^8.0", "unleashedtech/php-coding-standard": "^3.1.1", "vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0" }, @@ -5071,7 +5073,7 @@ "type": "tidelift" } ], - "time": "2025-11-26T21:48:24+00:00" + "time": "2026-03-19T13:16:38+00:00" }, { "name": "league/config", @@ -5307,16 +5309,16 @@ }, { "name": "league/flysystem", - "version": "3.31.0", + "version": "3.34.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "1717e0b3642b0df65ecb0cc89cdd99fa840672ff" + "reference": "2daaac3b0d4c83ea7ed5d8586e786f5d00f3540e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/1717e0b3642b0df65ecb0cc89cdd99fa840672ff", - "reference": "1717e0b3642b0df65ecb0cc89cdd99fa840672ff", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2daaac3b0d4c83ea7ed5d8586e786f5d00f3540e", + "reference": "2daaac3b0d4c83ea7ed5d8586e786f5d00f3540e", "shasum": "" }, "require": { @@ -5384,26 +5386,26 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.31.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.34.0" }, - "time": "2026-01-23T15:38:47+00:00" + "time": "2026-05-14T10:28:08+00:00" }, { "name": "league/flysystem-aws-s3-v3", - "version": "3.29.0", + "version": "3.34.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9" + "reference": "0c62fdac907791d8649ad3c61cb7a77628344fb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/c6ff6d4606e48249b63f269eba7fabdb584e76a9", - "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/0c62fdac907791d8649ad3c61cb7a77628344fb8", + "reference": "0c62fdac907791d8649ad3c61cb7a77628344fb8", "shasum": "" }, "require": { - "aws/aws-sdk-php": "^3.295.10", + "aws/aws-sdk-php": "^3.371.5", "league/flysystem": "^3.10.0", "league/mime-type-detection": "^1.0.0", "php": "^8.0.2" @@ -5439,9 +5441,9 @@ "storage" ], "support": { - "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.29.0" + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.34.0" }, - "time": "2024-08-17T13:10:48+00:00" + "time": "2026-05-04T08:24:00+00:00" }, { "name": "league/flysystem-local", @@ -5494,16 +5496,16 @@ }, { "name": "league/iso3166", - "version": "4.3.3", + "version": "4.4.0", "source": { "type": "git", "url": "https://github.com/alcohol/iso3166.git", - "reference": "3f692113a1c07859ec69303a0127b43da8a66768" + "reference": "928ac7ecc569db9123a83ef5b1c6efc279e7cb49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/alcohol/iso3166/zipball/3f692113a1c07859ec69303a0127b43da8a66768", - "reference": "3f692113a1c07859ec69303a0127b43da8a66768", + "url": "https://api.github.com/repos/alcohol/iso3166/zipball/928ac7ecc569db9123a83ef5b1c6efc279e7cb49", + "reference": "928ac7ecc569db9123a83ef5b1c6efc279e7cb49", "shasum": "" }, "require": { @@ -5557,7 +5559,7 @@ "type": "github" } ], - "time": "2025-06-05T08:06:30+00:00" + "time": "2026-01-02T09:49:36+00:00" }, { "name": "league/mime-type-detection", @@ -5617,16 +5619,16 @@ }, { "name": "league/oauth2-server", - "version": "9.2.0", + "version": "9.3.0", "source": { "type": "git", "url": "https://github.com/thephpleague/oauth2-server.git", - "reference": "00323013403e1a1e0f424affafca56c28b60c22c" + "reference": "d8e2f39f645a82b207bbac441694d6e6079357cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/00323013403e1a1e0f424affafca56c28b60c22c", - "reference": "00323013403e1a1e0f424affafca56c28b60c22c", + "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/d8e2f39f645a82b207bbac441694d6e6079357cb", + "reference": "d8e2f39f645a82b207bbac441694d6e6079357cb", "shasum": "" }, "require": { @@ -5637,7 +5639,7 @@ "lcobucci/jwt": "^5.0", "league/event": "^3.0", "league/uri": "^7.0", - "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", "psr/http-message": "^2.0", "psr/http-server-middleware": "^1.0" }, @@ -5649,11 +5651,11 @@ "laminas/laminas-diactoros": "^3.5", "php-parallel-lint/php-parallel-lint": "^1.3.2", "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan": "^1.12", - "phpstan/phpstan-deprecation-rules": "^1.1.4", - "phpstan/phpstan-phpunit": "^1.3.15", - "phpstan/phpstan-strict-rules": "^1.5.2", - "phpunit/phpunit": "^9.6.21", + "phpstan/phpstan": "^1.12|^2.0", + "phpstan/phpstan-deprecation-rules": "^1.1.4|^2.0", + "phpstan/phpstan-phpunit": "^1.3.15|^2.0", + "phpstan/phpstan-strict-rules": "^1.5.2|^2.0", + "phpunit/phpunit": "^10.5|^11.5|^12.0", "roave/security-advisories": "dev-master", "slevomat/coding-standard": "^8.14.1", "squizlabs/php_codesniffer": "^3.8" @@ -5701,7 +5703,7 @@ ], "support": { "issues": "https://github.com/thephpleague/oauth2-server/issues", - "source": "https://github.com/thephpleague/oauth2-server/tree/9.2.0" + "source": "https://github.com/thephpleague/oauth2-server/tree/9.3.0" }, "funding": [ { @@ -5709,24 +5711,24 @@ "type": "github" } ], - "time": "2025-02-15T00:49:10+00:00" + "time": "2025-11-25T22:51:15+00:00" }, { "name": "league/uri", - "version": "7.8.0", + "version": "7.8.1", "source": { "type": "git", "url": "https://github.com/thephpleague/uri.git", - "reference": "4436c6ec8d458e4244448b069cc572d088230b76" + "reference": "08cf38e3924d4f56238125547b5720496fac8fd4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76", - "reference": "4436c6ec8d458e4244448b069cc572d088230b76", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/08cf38e3924d4f56238125547b5720496fac8fd4", + "reference": "08cf38e3924d4f56238125547b5720496fac8fd4", "shasum": "" }, "require": { - "league/uri-interfaces": "^7.8", + "league/uri-interfaces": "^7.8.1", "php": "^8.1", "psr/http-factory": "^1" }, @@ -5799,7 +5801,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.8.0" + "source": "https://github.com/thephpleague/uri/tree/7.8.1" }, "funding": [ { @@ -5807,20 +5809,20 @@ "type": "github" } ], - "time": "2026-01-14T17:24:56+00:00" + "time": "2026-03-15T20:22:25+00:00" }, { "name": "league/uri-interfaces", - "version": "7.8.0", + "version": "7.8.1", "source": { "type": "git", "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4" + "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4", - "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/85d5c77c5d6d3af6c54db4a78246364908f3c928", + "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928", "shasum": "" }, "require": { @@ -5883,7 +5885,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.8.0" + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.1" }, "funding": [ { @@ -5891,40 +5893,40 @@ "type": "github" } ], - "time": "2026-01-15T06:54:53+00:00" + "time": "2026-03-08T20:05:35+00:00" }, { "name": "livewire/livewire", - "version": "v3.7.10", + "version": "v3.8.0", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "0dc679eb4c8b4470cb12522b5927ef08ca2358bb" + "reference": "d81d269243c3f18d302663c0ce5672990df08ca1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/0dc679eb4c8b4470cb12522b5927ef08ca2358bb", - "reference": "0dc679eb4c8b4470cb12522b5927ef08ca2358bb", + "url": "https://api.github.com/repos/livewire/livewire/zipball/d81d269243c3f18d302663c0ce5672990df08ca1", + "reference": "d81d269243c3f18d302663c0ce5672990df08ca1", "shasum": "" }, "require": { - "illuminate/database": "^10.0|^11.0|^12.0", - "illuminate/routing": "^10.0|^11.0|^12.0", - "illuminate/support": "^10.0|^11.0|^12.0", - "illuminate/validation": "^10.0|^11.0|^12.0", + "illuminate/database": "^10.0|^11.0|^12.0|^13.0", + "illuminate/routing": "^10.0|^11.0|^12.0|^13.0", + "illuminate/support": "^10.0|^11.0|^12.0|^13.0", + "illuminate/validation": "^10.0|^11.0|^12.0|^13.0", "laravel/prompts": "^0.1.24|^0.2|^0.3", "league/mime-type-detection": "^1.9", "php": "^8.1", - "symfony/console": "^6.0|^7.0", - "symfony/http-kernel": "^6.2|^7.0" + "symfony/console": "^6.0|^7.0|^8.0", + "symfony/http-kernel": "^6.2|^7.0|^8.0" }, "require-dev": { "calebporzio/sushi": "^2.1", - "laravel/framework": "^10.15.0|^11.0|^12.0", + "laravel/framework": "^10.15.0|^11.0|^12.0|^13.0", "mockery/mockery": "^1.3.1", - "orchestra/testbench": "^8.21.0|^9.0|^10.0", - "orchestra/testbench-dusk": "^8.24|^9.1|^10.0", - "phpunit/phpunit": "^10.4|^11.5", + "orchestra/testbench": "^8.21.0|^9.0|^10.0|^11.0", + "orchestra/testbench-dusk": "^8.24|^9.1|^10.0|^11.0", + "phpunit/phpunit": "^10.4|^11.5|^12.5", "psy/psysh": "^0.11.22|^0.12" }, "type": "library", @@ -5959,7 +5961,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v3.7.10" + "source": "https://github.com/livewire/livewire/tree/v3.8.0" }, "funding": [ { @@ -5967,33 +5969,33 @@ "type": "github" } ], - "time": "2026-02-09T22:49:33+00:00" + "time": "2026-04-30T23:56:43+00:00" }, { "name": "maatwebsite/excel", - "version": "3.1.67", + "version": "3.1.69", "source": { "type": "git", "url": "https://github.com/SpartnerNL/Laravel-Excel.git", - "reference": "e508e34a502a3acc3329b464dad257378a7edb4d" + "reference": "ae5d65b7c9a2fac43bff4d44f796ac95d7a8e760" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/e508e34a502a3acc3329b464dad257378a7edb4d", - "reference": "e508e34a502a3acc3329b464dad257378a7edb4d", + "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/ae5d65b7c9a2fac43bff4d44f796ac95d7a8e760", + "reference": "ae5d65b7c9a2fac43bff4d44f796ac95d7a8e760", "shasum": "" }, "require": { "composer/semver": "^3.3", "ext-json": "*", - "illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0||^12.0", + "illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0||^12.0||^13.0", "php": "^7.0||^8.0", - "phpoffice/phpspreadsheet": "^1.30.0", + "phpoffice/phpspreadsheet": "^1.30.4", "psr/simple-cache": "^1.0||^2.0||^3.0" }, "require-dev": { - "laravel/scout": "^7.0||^8.0||^9.0||^10.0", - "orchestra/testbench": "^6.0||^7.0||^8.0||^9.0||^10.0", + "laravel/scout": "^7.0||^8.0||^9.0||^10.0||^11.0", + "orchestra/testbench": "^6.0||^7.0||^8.0||^9.0||^10.0||^11.0", "predis/predis": "^1.1" }, "type": "library", @@ -6036,7 +6038,7 @@ ], "support": { "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues", - "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.67" + "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.69" }, "funding": [ { @@ -6048,35 +6050,35 @@ "type": "github" } ], - "time": "2025-08-26T09:13:16+00:00" + "time": "2026-04-30T20:03:58+00:00" }, { "name": "maennchen/zipstream-php", - "version": "3.1.2", + "version": "3.2.2", "source": { "type": "git", "url": "https://github.com/maennchen/ZipStream-PHP.git", - "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f" + "reference": "77bebeb4c6c340bb3c11c843b2cffd8bbfde4d5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f", - "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/77bebeb4c6c340bb3c11c843b2cffd8bbfde4d5e", + "reference": "77bebeb4c6c340bb3c11c843b2cffd8bbfde4d5e", "shasum": "" }, "require": { "ext-mbstring": "*", "ext-zlib": "*", - "php-64bit": "^8.2" + "php-64bit": "^8.3" }, "require-dev": { "brianium/paratest": "^7.7", "ext-zip": "*", - "friendsofphp/php-cs-fixer": "^3.16", + "friendsofphp/php-cs-fixer": "^3.86", "guzzlehttp/guzzle": "^7.5", "mikey179/vfsstream": "^1.6", "php-coveralls/php-coveralls": "^2.5", - "phpunit/phpunit": "^11.0", + "phpunit/phpunit": "^12.0", "vimeo/psalm": "^6.0" }, "suggest": { @@ -6118,7 +6120,7 @@ ], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2" + "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.2.2" }, "funding": [ { @@ -6126,7 +6128,7 @@ "type": "github" } ], - "time": "2025-01-27T12:07:53+00:00" + "time": "2026-04-11T18:38:28+00:00" }, { "name": "marc-mabe/php-enum", @@ -6377,29 +6379,28 @@ }, { "name": "mobiledetect/mobiledetectlib", - "version": "4.8.09", + "version": "4.11.0", "source": { "type": "git", "url": "https://github.com/serbanghita/Mobile-Detect.git", - "reference": "a06fe2e546a06bb8c2639d6823d5250b2efb3209" + "reference": "ab39168b7556f44c11c80be1222b44b239f5c2e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/a06fe2e546a06bb8c2639d6823d5250b2efb3209", - "reference": "a06fe2e546a06bb8c2639d6823d5250b2efb3209", + "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/ab39168b7556f44c11c80be1222b44b239f5c2e4", + "reference": "ab39168b7556f44c11c80be1222b44b239f5c2e4", "shasum": "" }, "require": { - "php": ">=8.0", - "psr/cache": "^3.0", - "psr/simple-cache": "^3" + "php": ">=8.2", + "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^v3.65.0", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.12.x-dev", - "phpunit/phpunit": "^9.6.18", - "squizlabs/php_codesniffer": "^3.11.1" + "friendsofphp/php-cs-fixer": "3.95.1", + "phpbench/phpbench": "1.6.1", + "phpstan/phpstan": "2.1.47", + "phpunit/phpunit": "9.6.34", + "squizlabs/php_codesniffer": "3.13.5" }, "type": "library", "autoload": { @@ -6430,7 +6431,7 @@ ], "support": { "issues": "https://github.com/serbanghita/Mobile-Detect/issues", - "source": "https://github.com/serbanghita/Mobile-Detect/tree/4.8.09" + "source": "https://github.com/serbanghita/Mobile-Detect/tree/4.11.0" }, "funding": [ { @@ -6438,7 +6439,7 @@ "type": "github" } ], - "time": "2024-12-10T15:32:06+00:00" + "time": "2026-05-24T12:32:40+00:00" }, { "name": "monolog/monolog", @@ -6671,16 +6672,16 @@ }, { "name": "nesbot/carbon", - "version": "3.11.1", + "version": "3.11.4", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "f438fcc98f92babee98381d399c65336f3a3827f" + "reference": "e890471a3494740f7d9326d72ce6a8c559ffee60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/f438fcc98f92babee98381d399c65336f3a3827f", - "reference": "f438fcc98f92babee98381d399c65336f3a3827f", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/e890471a3494740f7d9326d72ce6a8c559ffee60", + "reference": "e890471a3494740f7d9326d72ce6a8c559ffee60", "shasum": "" }, "require": { @@ -6772,7 +6773,7 @@ "type": "tidelift" } ], - "time": "2026-01-29T09:26:29+00:00" + "time": "2026-04-07T09:57:54+00:00" }, { "name": "nette/schema", @@ -6843,16 +6844,16 @@ }, { "name": "nette/utils", - "version": "v4.1.3", + "version": "v4.1.4", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "bb3ea637e3d131d72acc033cfc2746ee893349fe" + "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/bb3ea637e3d131d72acc033cfc2746ee893349fe", - "reference": "bb3ea637e3d131d72acc033cfc2746ee893349fe", + "url": "https://api.github.com/repos/nette/utils/zipball/7da6c396d7ebe142bc857c20479d5e70a5e1aac7", + "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7", "shasum": "" }, "require": { @@ -6928,9 +6929,9 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.1.3" + "source": "https://github.com/nette/utils/tree/v4.1.4" }, - "time": "2026-02-13T03:05:33+00:00" + "time": "2026-05-11T20:49:54+00:00" }, { "name": "nikic/php-parser", @@ -6992,16 +6993,16 @@ }, { "name": "novadaemon/filament-pretty-json", - "version": "v2.5.0", + "version": "v2.7.0", "source": { "type": "git", "url": "https://github.com/novadaemon/filament-pretty-json.git", - "reference": "e1577286c6b26d85ba0deaf95fcd13ee6d09c831" + "reference": "19f0333efd1d142882a0c82d54d88ace465a95dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/novadaemon/filament-pretty-json/zipball/e1577286c6b26d85ba0deaf95fcd13ee6d09c831", - "reference": "e1577286c6b26d85ba0deaf95fcd13ee6d09c831", + "url": "https://api.github.com/repos/novadaemon/filament-pretty-json/zipball/19f0333efd1d142882a0c82d54d88ace465a95dc", + "reference": "19f0333efd1d142882a0c82d54d88ace465a95dc", "shasum": "" }, "require": { @@ -7060,7 +7061,7 @@ "type": "github" } ], - "time": "2025-05-12T12:42:29+00:00" + "time": "2025-08-20T15:45:27+00:00" }, { "name": "nunomaduro/termwind", @@ -7151,16 +7152,16 @@ }, { "name": "nwidart/laravel-modules", - "version": "v12.0.4", + "version": "v12.0.5", "source": { "type": "git", "url": "https://github.com/nWidart/laravel-modules.git", - "reference": "6e1f50de63366206b06ec53bbc823282977ddd06" + "reference": "5fe38e88b66394debeac785278a7e40eb81df51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nWidart/laravel-modules/zipball/6e1f50de63366206b06ec53bbc823282977ddd06", - "reference": "6e1f50de63366206b06ec53bbc823282977ddd06", + "url": "https://api.github.com/repos/nWidart/laravel-modules/zipball/5fe38e88b66394debeac785278a7e40eb81df51a", + "reference": "5fe38e88b66394debeac785278a7e40eb81df51a", "shasum": "" }, "require": { @@ -7224,7 +7225,7 @@ ], "support": { "issues": "https://github.com/nWidart/laravel-modules/issues", - "source": "https://github.com/nWidart/laravel-modules/tree/v12.0.4" + "source": "https://github.com/nWidart/laravel-modules/tree/v12.0.5" }, "funding": [ { @@ -7236,7 +7237,7 @@ "type": "github" } ], - "time": "2025-06-29T09:23:53+00:00" + "time": "2026-03-19T18:16:17+00:00" }, { "name": "openspout/openspout", @@ -7333,29 +7334,29 @@ }, { "name": "owen-it/laravel-auditing", - "version": "v14.0.0", + "version": "v14.0.3", "source": { "type": "git", "url": "https://github.com/owen-it/laravel-auditing.git", - "reference": "f92602d1b3f53df29ddd577290e9d735ea707c53" + "reference": "34e8a21890082a7a353894a4acdeb2d301dbe0d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/owen-it/laravel-auditing/zipball/f92602d1b3f53df29ddd577290e9d735ea707c53", - "reference": "f92602d1b3f53df29ddd577290e9d735ea707c53", + "url": "https://api.github.com/repos/owen-it/laravel-auditing/zipball/34e8a21890082a7a353894a4acdeb2d301dbe0d4", + "reference": "34e8a21890082a7a353894a4acdeb2d301dbe0d4", "shasum": "" }, "require": { "ext-json": "*", - "illuminate/console": "^11.0|^12.0", - "illuminate/database": "^11.0|^12.0", - "illuminate/filesystem": "^11.0|^12.0", + "illuminate/console": "^11.0|^12.0|^13.0", + "illuminate/database": "^11.0|^12.0|^13.0", + "illuminate/filesystem": "^11.0|^12.0|^13.0", "php": "^8.2" }, "require-dev": { "mockery/mockery": "^1.5.1", - "orchestra/testbench": "^9.0|^10.0", - "phpunit/phpunit": "^11.0" + "orchestra/testbench": "^9.0|^10.0|^11.0", + "phpunit/phpunit": "^11.0|^12.5.12" }, "type": "package", "extra": { @@ -7413,28 +7414,30 @@ "issues": "https://github.com/owen-it/laravel-auditing/issues", "source": "https://github.com/owen-it/laravel-auditing" }, - "time": "2025-02-26T16:40:54+00:00" + "time": "2026-03-27T13:27:17+00:00" }, { "name": "paragonie/constant_time_encoding", - "version": "v3.0.0", + "version": "v3.1.3", "source": { "type": "git", "url": "https://github.com/paragonie/constant_time_encoding.git", - "reference": "df1e7fde177501eee2037dd159cf04f5f301a512" + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/df1e7fde177501eee2037dd159cf04f5f301a512", - "reference": "df1e7fde177501eee2037dd159cf04f5f301a512", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", "shasum": "" }, "require": { "php": "^8" }, "require-dev": { - "phpunit/phpunit": "^9", - "vimeo/psalm": "^4|^5" + "infection/infection": "^0", + "nikic/php-fuzzer": "^0", + "phpunit/phpunit": "^9|^10|^11", + "vimeo/psalm": "^4|^5|^6" }, "type": "library", "autoload": { @@ -7480,7 +7483,7 @@ "issues": "https://github.com/paragonie/constant_time_encoding/issues", "source": "https://github.com/paragonie/constant_time_encoding" }, - "time": "2024-05-08T12:36:18+00:00" + "time": "2025-09-24T15:06:41+00:00" }, { "name": "paragonie/random_compat", @@ -7612,66 +7615,31 @@ "time": "2024-10-02T11:20:13+00:00" }, { - "name": "phpoffice/phpspreadsheet", - "version": "1.30.2", + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", "source": { "type": "git", - "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "09cdde5e2f078b9a3358dd217e2c8cb4dac84be2" + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/09cdde5e2f078b9a3358dd217e2c8cb4dac84be2", - "reference": "09cdde5e2f078b9a3358dd217e2c8cb4dac84be2", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", "shasum": "" }, "require": { - "composer/pcre": "^1||^2||^3", - "ext-ctype": "*", - "ext-dom": "*", - "ext-fileinfo": "*", - "ext-gd": "*", - "ext-iconv": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-simplexml": "*", - "ext-xml": "*", - "ext-xmlreader": "*", - "ext-xmlwriter": "*", - "ext-zip": "*", - "ext-zlib": "*", - "ezyang/htmlpurifier": "^4.15", - "maennchen/zipstream-php": "^2.1 || ^3.0", - "markbaker/complex": "^3.0", - "markbaker/matrix": "^3.0", - "php": ">=7.4.0 <8.5.0", - "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" - }, - "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "dev-main", - "doctrine/instantiator": "^1.5", - "dompdf/dompdf": "^1.0 || ^2.0 || ^3.0", - "friendsofphp/php-cs-fixer": "^3.2", - "mitoteam/jpgraph": "^10.3", - "mpdf/mpdf": "^8.1.1", - "phpcompatibility/php-compatibility": "^9.3", - "phpstan/phpstan": "^1.1", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^8.5 || ^9.0", - "squizlabs/php_codesniffer": "^3.7", - "tecnickcom/tcpdf": "^6.5" - }, - "suggest": { - "dompdf/dompdf": "Option for rendering PDF with PDF Writer", - "ext-intl": "PHP Internationalization Functions", - "mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers", - "mpdf/mpdf": "Option for rendering PDF with PDF Writer", - "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer" + "php": "^7.2 || ^8.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, "autoload": { "psr-4": { - "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet" + "phpDocumentor\\Reflection\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -7680,89 +7648,300 @@ ], "authors": [ { - "name": "Maarten Balliauw", - "homepage": "https://blog.maartenballiauw.be" - }, - { - "name": "Mark Baker", - "homepage": "https://markbakeruk.net" - }, - { - "name": "Franck Lefevre", - "homepage": "https://rootslabs.net" - }, - { - "name": "Erik Tilt" - }, - { - "name": "Adrien Crivelli" - }, - { - "name": "Owen Leibman" + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" } ], - "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine", - "homepage": "https://github.com/PHPOffice/PhpSpreadsheet", + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", "keywords": [ - "OpenXML", - "excel", - "gnumeric", - "ods", - "php", - "spreadsheet", - "xls", - "xlsx" + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" ], "support": { - "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.30.2" + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" }, - "time": "2026-01-11T05:58:24+00:00" + "time": "2020-06-27T09:03:43+00:00" }, { - "name": "phpoption/phpoption", - "version": "1.9.5", + "name": "phpdocumentor/reflection-docblock", + "version": "6.0.3", "source": { "type": "git", - "url": "https://github.com/schmittjoh/php-option.git", - "reference": "75365b91986c2405cf5e1e012c5595cd487a98be" + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be", - "reference": "75365b91986c2405cf5e1e012c5595cd487a98be", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/7bae67520aa9f5ecc506d646810bd40d9da54582", + "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582", "shasum": "" }, "require": { - "php": "^7.2.5 || ^8.0" + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^2.0", + "phpstan/phpdoc-parser": "^2.0", + "webmozart/assert": "^1.9.1 || ^2" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34" + "mockery/mockery": "~1.3.5 || ~1.6.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^5.26", + "shipmonk/dead-code-detector": "^0.5.1" }, "type": "library", "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - }, "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "5.x-dev" } }, "autoload": { "psr-4": { - "PhpOption\\": "src/PhpOption/" + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache-2.0" + "MIT" ], "authors": [ { - "name": "Johannes M. Schmitt", - "email": "schmittjoh@gmail.com", + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "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/6.0.3" + }, + "time": "2026-03-18T20:49:53+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/327a05bbee54120d4786a0dc67aad30226ad4cf9", + "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev", + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "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/2.0.0" + }, + "time": "2026-01-06T21:53:42+00:00" + }, + { + "name": "phpoffice/phpspreadsheet", + "version": "1.30.4", + "source": { + "type": "git", + "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", + "reference": "02970383cc12e7bf0bc0707ea6e2e8ed23a7aec9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/02970383cc12e7bf0bc0707ea6e2e8ed23a7aec9", + "reference": "02970383cc12e7bf0bc0707ea6e2e8ed23a7aec9", + "shasum": "" + }, + "require": { + "composer/pcre": "^1||^2||^3", + "ext-ctype": "*", + "ext-dom": "*", + "ext-fileinfo": "*", + "ext-gd": "*", + "ext-iconv": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-xml": "*", + "ext-xmlreader": "*", + "ext-xmlwriter": "*", + "ext-zip": "*", + "ext-zlib": "*", + "ezyang/htmlpurifier": "^4.15", + "maennchen/zipstream-php": "^2.1 || ^3.0", + "markbaker/complex": "^3.0", + "markbaker/matrix": "^3.0", + "php": ">=7.4.0 <8.5.0", + "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-main", + "doctrine/instantiator": "^1.5", + "dompdf/dompdf": "^1.0 || ^2.0 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.2", + "mitoteam/jpgraph": "^10.3", + "mpdf/mpdf": "^8.1.1", + "phpcompatibility/php-compatibility": "^9.3", + "phpstan/phpstan": "^1.1", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^8.5 || ^9.0", + "squizlabs/php_codesniffer": "^3.7", + "tecnickcom/tcpdf": "^6.5" + }, + "suggest": { + "dompdf/dompdf": "Option for rendering PDF with PDF Writer", + "ext-intl": "PHP Internationalization Functions", + "mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers", + "mpdf/mpdf": "Option for rendering PDF with PDF Writer", + "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maarten Balliauw", + "homepage": "https://blog.maartenballiauw.be" + }, + { + "name": "Mark Baker", + "homepage": "https://markbakeruk.net" + }, + { + "name": "Franck Lefevre", + "homepage": "https://rootslabs.net" + }, + { + "name": "Erik Tilt" + }, + { + "name": "Adrien Crivelli" + }, + { + "name": "Owen Leibman" + } + ], + "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine", + "homepage": "https://github.com/PHPOffice/PhpSpreadsheet", + "keywords": [ + "OpenXML", + "excel", + "gnumeric", + "ods", + "php", + "spreadsheet", + "xls", + "xlsx" + ], + "support": { + "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.30.4" + }, + "time": "2026-04-19T06:00:39+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.5", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "75365b91986c2405cf5e1e012c5595cd487a98be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be", + "reference": "75365b91986c2405cf5e1e012c5595cd487a98be", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", "homepage": "https://github.com/schmittjoh" }, { @@ -7796,16 +7975,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.46", + "version": "3.0.52", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6" + "reference": "2adaefc83df2ec548558307690f376dd7d4f4fce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", - "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/2adaefc83df2ec548558307690f376dd7d4f4fce", + "reference": "2adaefc83df2ec548558307690f376dd7d4f4fce", "shasum": "" }, "require": { @@ -7886,7 +8065,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.46" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.52" }, "funding": [ { @@ -7902,20 +8081,20 @@ "type": "tidelift" } ], - "time": "2025-06-26T16:29:55+00:00" + "time": "2026-04-27T07:02:15+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "2.2.0", + "version": "2.3.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8" + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/b9e61a61e39e02dd90944e9115241c7f7e76bfd8", - "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a", + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a", "shasum": "" }, "require": { @@ -7947,22 +8126,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.2.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2" }, - "time": "2025-07-13T07:04:09+00:00" + "time": "2026-01-25T14:56:51+00:00" }, { "name": "pragmarx/google2fa", - "version": "v8.0.3", + "version": "v9.0.0", "source": { "type": "git", "url": "https://github.com/antonioribeiro/google2fa.git", - "reference": "6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad" + "reference": "e6bc62dd6ae83acc475f57912e27466019a1f2cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad", - "reference": "6f8d87ebd5afbf7790bde1ffc7579c7c705e0fad", + "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/e6bc62dd6ae83acc475f57912e27466019a1f2cf", + "reference": "e6bc62dd6ae83acc475f57912e27466019a1f2cf", "shasum": "" }, "require": { @@ -7999,9 +8178,9 @@ ], "support": { "issues": "https://github.com/antonioribeiro/google2fa/issues", - "source": "https://github.com/antonioribeiro/google2fa/tree/v8.0.3" + "source": "https://github.com/antonioribeiro/google2fa/tree/v9.0.0" }, - "time": "2024-09-05T11:56:40+00:00" + "time": "2025-09-19T22:51:08+00:00" }, { "name": "psr/cache", @@ -8579,16 +8758,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.20", + "version": "v0.12.22", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "19678eb6b952a03b8a1d96ecee9edba518bb0373" + "reference": "3be75d5b9244936dd4ac62ade2bfb004d13acf0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/19678eb6b952a03b8a1d96ecee9edba518bb0373", - "reference": "19678eb6b952a03b8a1d96ecee9edba518bb0373", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/3be75d5b9244936dd4ac62ade2bfb004d13acf0f", + "reference": "3be75d5b9244936dd4ac62ade2bfb004d13acf0f", "shasum": "" }, "require": { @@ -8652,26 +8831,26 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.20" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.22" }, - "time": "2026-02-11T15:05:28+00:00" + "time": "2026-03-22T23:03:24+00:00" }, { "name": "pxlrbt/filament-environment-indicator", - "version": "v2.1.0", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/pxlrbt/filament-environment-indicator.git", - "reference": "e55bca20af0c9cff8a90d0a8779b09df5c4bb9d4" + "reference": "4f2cb470df70b6c261020823309e65047713cbdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pxlrbt/filament-environment-indicator/zipball/e55bca20af0c9cff8a90d0a8779b09df5c4bb9d4", - "reference": "e55bca20af0c9cff8a90d0a8779b09df5c4bb9d4", + "url": "https://api.github.com/repos/pxlrbt/filament-environment-indicator/zipball/4f2cb470df70b6c261020823309e65047713cbdd", + "reference": "4f2cb470df70b6c261020823309e65047713cbdd", "shasum": "" }, "require": { - "filament/filament": "^3.0-stable", + "filament/filament": "^3.0", "php": "^8.0" }, "require-dev": { @@ -8708,7 +8887,7 @@ ], "support": { "issues": "https://github.com/pxlrbt/filament-environment-indicator/issues", - "source": "https://github.com/pxlrbt/filament-environment-indicator/tree/v2.1.0" + "source": "https://github.com/pxlrbt/filament-environment-indicator/tree/v2.2.0" }, "funding": [ { @@ -8716,7 +8895,7 @@ "type": "github" } ], - "time": "2024-11-18T13:24:51+00:00" + "time": "2025-07-25T14:36:56+00:00" }, { "name": "ralouphie/getallheaders", @@ -8991,33 +9170,33 @@ }, { "name": "ryangjchandler/blade-capture-directive", - "version": "v1.1.0", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/ryangjchandler/blade-capture-directive.git", - "reference": "bbb1513dfd89eaec87a47fe0c449a7e3d4a1976d" + "reference": "3f9e80b56ff60b78755ef320e3e16d88850101d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ryangjchandler/blade-capture-directive/zipball/bbb1513dfd89eaec87a47fe0c449a7e3d4a1976d", - "reference": "bbb1513dfd89eaec87a47fe0c449a7e3d4a1976d", + "url": "https://api.github.com/repos/ryangjchandler/blade-capture-directive/zipball/3f9e80b56ff60b78755ef320e3e16d88850101d6", + "reference": "3f9e80b56ff60b78755ef320e3e16d88850101d6", "shasum": "" }, "require": { - "illuminate/contracts": "^10.0|^11.0|^12.0", + "illuminate/contracts": "^10.0|^11.0|^12.0|^13.0", "php": "^8.1", "spatie/laravel-package-tools": "^1.9.2" }, "require-dev": { "nunomaduro/collision": "^7.0|^8.0", "nunomaduro/larastan": "^2.0|^3.0", - "orchestra/testbench": "^8.0|^9.0|^10.0", - "pestphp/pest": "^2.0|^3.7", - "pestphp/pest-plugin-laravel": "^2.0|^3.1", + "orchestra/testbench": "^8.0|^9.0|^10.0|^11.0", + "pestphp/pest": "^2.0|^3.7|^4.1", + "pestphp/pest-plugin-laravel": "^2.0|^3.1|^v4.1.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", "phpstan/phpstan-phpunit": "^1.0|^2.0", - "phpunit/phpunit": "^10.0|^11.5.3", + "phpunit/phpunit": "^10.0|^11.5.3|^12.0", "spatie/laravel-ray": "^1.26" }, "type": "library", @@ -9057,7 +9236,7 @@ ], "support": { "issues": "https://github.com/ryangjchandler/blade-capture-directive/issues", - "source": "https://github.com/ryangjchandler/blade-capture-directive/tree/v1.1.0" + "source": "https://github.com/ryangjchandler/blade-capture-directive/tree/v1.1.1" }, "funding": [ { @@ -9065,7 +9244,7 @@ "type": "github" } ], - "time": "2025-02-25T09:09:36+00:00" + "time": "2026-03-19T10:36:26+00:00" }, { "name": "seld/jsonlint", @@ -9360,16 +9539,16 @@ }, { "name": "spatie/laravel-package-tools", - "version": "1.93.0", + "version": "1.93.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-package-tools.git", - "reference": "0d097bce95b2bf6802fb1d83e1e753b0f5a948e7" + "reference": "d5552849801f2642aea710557463234b59ef65eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/0d097bce95b2bf6802fb1d83e1e753b0f5a948e7", - "reference": "0d097bce95b2bf6802fb1d83e1e753b0f5a948e7", + "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/d5552849801f2642aea710557463234b59ef65eb", + "reference": "d5552849801f2642aea710557463234b59ef65eb", "shasum": "" }, "require": { @@ -9409,7 +9588,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-package-tools/issues", - "source": "https://github.com/spatie/laravel-package-tools/tree/1.93.0" + "source": "https://github.com/spatie/laravel-package-tools/tree/1.93.1" }, "funding": [ { @@ -9417,7 +9596,7 @@ "type": "github" } ], - "time": "2026-02-21T12:49:54+00:00" + "time": "2026-05-19T14:06:37+00:00" }, { "name": "spatie/regex", @@ -9484,16 +9663,16 @@ }, { "name": "spatie/temporary-directory", - "version": "2.3.0", + "version": "2.3.1", "source": { "type": "git", "url": "https://github.com/spatie/temporary-directory.git", - "reference": "580eddfe9a0a41a902cac6eeb8f066b42e65a32b" + "reference": "662e481d6ec07ef29fd05010433428851a42cd07" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/580eddfe9a0a41a902cac6eeb8f066b42e65a32b", - "reference": "580eddfe9a0a41a902cac6eeb8f066b42e65a32b", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/662e481d6ec07ef29fd05010433428851a42cd07", + "reference": "662e481d6ec07ef29fd05010433428851a42cd07", "shasum": "" }, "require": { @@ -9529,7 +9708,7 @@ ], "support": { "issues": "https://github.com/spatie/temporary-directory/issues", - "source": "https://github.com/spatie/temporary-directory/tree/2.3.0" + "source": "https://github.com/spatie/temporary-directory/tree/2.3.1" }, "funding": [ { @@ -9541,30 +9720,41 @@ "type": "github" } ], - "time": "2025-01-13T13:04:43+00:00" + "time": "2026-01-12T07:42:22+00:00" }, { - "name": "staudenmeir/eloquent-has-many-deep-contracts", - "version": "v1.3", + "name": "spomky-labs/cbor-php", + "version": "3.2.3", "source": { "type": "git", - "url": "https://github.com/staudenmeir/eloquent-has-many-deep-contracts.git", - "reference": "37ce351e4db919b3af606bc8ca0e62e2e4939cde" + "url": "https://github.com/Spomky-Labs/cbor-php.git", + "reference": "dd6eb84e6d92f7b8bd0da56b4b4dd7235aed0c32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/staudenmeir/eloquent-has-many-deep-contracts/zipball/37ce351e4db919b3af606bc8ca0e62e2e4939cde", - "reference": "37ce351e4db919b3af606bc8ca0e62e2e4939cde", + "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/dd6eb84e6d92f7b8bd0da56b4b4dd7235aed0c32", + "reference": "dd6eb84e6d92f7b8bd0da56b4b4dd7235aed0c32", "shasum": "" }, "require": { - "illuminate/database": "^12.0", - "php": "^8.2" + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17", + "ext-mbstring": "*", + "php": ">=8.0" + }, + "require-dev": { + "ext-json": "*", + "roave/security-advisories": "dev-latest", + "symfony/error-handler": "^6.4|^7.1|^8.0", + "symfony/var-dumper": "^6.4|^7.1|^8.0" + }, + "suggest": { + "ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags", + "ext-gmp": "GMP or BCMath extensions will drastically improve the library performance" }, "type": "library", "autoload": { "psr-4": { - "Staudenmeir\\EloquentHasManyDeepContracts\\": "src/" + "CBOR\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -9573,44 +9763,214 @@ ], "authors": [ { - "name": "Jonas Staudenmeir", - "email": "mail@jonas-staudenmeir.de" + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/Spomky-Labs/cbor-php/contributors" } ], - "description": "Contracts for staudenmeir/eloquent-has-many-deep", + "description": "CBOR Encoder/Decoder for PHP", + "keywords": [ + "Concise Binary Object Representation", + "RFC7049", + "cbor" + ], "support": { - "issues": "https://github.com/staudenmeir/eloquent-has-many-deep-contracts/issues", - "source": "https://github.com/staudenmeir/eloquent-has-many-deep-contracts/tree/v1.3" + "issues": "https://github.com/Spomky-Labs/cbor-php/issues", + "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.2.3" }, - "time": "2025-02-15T17:11:01+00:00" + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2026-04-01T12:15:20+00:00" }, { - "name": "staudenmeir/eloquent-json-relations", - "version": "v1.14.1", + "name": "spomky-labs/pki-framework", + "version": "1.4.2", "source": { "type": "git", - "url": "https://github.com/staudenmeir/eloquent-json-relations.git", - "reference": "48b76d3094e528993abc77dc2414c58f7531f31f" + "url": "https://github.com/Spomky-Labs/pki-framework.git", + "reference": "aa576cbd07128075bef97ac2f8af9854e67513d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/staudenmeir/eloquent-json-relations/zipball/48b76d3094e528993abc77dc2414c58f7531f31f", - "reference": "48b76d3094e528993abc77dc2414c58f7531f31f", + "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/aa576cbd07128075bef97ac2f8af9854e67513d8", + "reference": "aa576cbd07128075bef97ac2f8af9854e67513d8", "shasum": "" }, "require": { - "illuminate/database": "^12.0", - "php": "^8.2", - "staudenmeir/eloquent-has-many-deep-contracts": "^1.3" + "brick/math": "^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17", + "ext-mbstring": "*", + "php": ">=8.1", + "psr/clock": "^1.0" }, "require-dev": { - "barryvdh/laravel-ide-helper": "^3.0", - "larastan/larastan": "^3.0", - "laravel/framework": "^12.0", - "mockery/mockery": "^1.5.1", - "orchestra/testbench-core": "^10.0", - "phpunit/phpunit": "^11.0", - "staudenmeir/eloquent-has-many-deep": "^1.21" + "ekino/phpstan-banned-code": "^1.0|^2.0|^3.0", + "ext-gmp": "*", + "ext-openssl": "*", + "infection/infection": "^0.28|^0.29|^0.31|^0.32", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpstan/extension-installer": "^1.3|^2.0", + "phpstan/phpstan": "^1.8|^2.0", + "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", + "phpstan/phpstan-phpunit": "^1.1|^2.0", + "phpstan/phpstan-strict-rules": "^1.3|^2.0", + "phpunit/phpunit": "^10.1|^11.0|^12.0|^13.0", + "rector/rector": "^1.0|^2.0", + "roave/security-advisories": "dev-latest", + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symplify/easy-coding-standard": "^12.0|^13.0" + }, + "suggest": { + "ext-bcmath": "For better performance (or GMP)", + "ext-gmp": "For better performance (or BCMath)", + "ext-openssl": "For OpenSSL based cyphering" + }, + "type": "library", + "autoload": { + "psr-4": { + "SpomkyLabs\\Pki\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Joni Eskelinen", + "email": "jonieske@gmail.com", + "role": "Original developer" + }, + { + "name": "Florent Morselli", + "email": "florent.morselli@spomky-labs.com", + "role": "Spomky-Labs PKI Framework developer" + } + ], + "description": "A PHP framework for managing Public Key Infrastructures. It comprises X.509 public key certificates, attribute certificates, certification requests and certification path validation.", + "homepage": "https://github.com/spomky-labs/pki-framework", + "keywords": [ + "DER", + "Private Key", + "ac", + "algorithm identifier", + "asn.1", + "asn1", + "attribute certificate", + "certificate", + "certification request", + "cryptography", + "csr", + "decrypt", + "ec", + "encrypt", + "pem", + "pkcs", + "public key", + "rsa", + "sign", + "signature", + "verify", + "x.509", + "x.690", + "x509", + "x690" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/pki-framework/issues", + "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.4.2" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2026-03-23T22:56:56+00:00" + }, + { + "name": "staudenmeir/eloquent-has-many-deep-contracts", + "version": "v1.3", + "source": { + "type": "git", + "url": "https://github.com/staudenmeir/eloquent-has-many-deep-contracts.git", + "reference": "37ce351e4db919b3af606bc8ca0e62e2e4939cde" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staudenmeir/eloquent-has-many-deep-contracts/zipball/37ce351e4db919b3af606bc8ca0e62e2e4939cde", + "reference": "37ce351e4db919b3af606bc8ca0e62e2e4939cde", + "shasum": "" + }, + "require": { + "illuminate/database": "^12.0", + "php": "^8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Staudenmeir\\EloquentHasManyDeepContracts\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonas Staudenmeir", + "email": "mail@jonas-staudenmeir.de" + } + ], + "description": "Contracts for staudenmeir/eloquent-has-many-deep", + "support": { + "issues": "https://github.com/staudenmeir/eloquent-has-many-deep-contracts/issues", + "source": "https://github.com/staudenmeir/eloquent-has-many-deep-contracts/tree/v1.3" + }, + "time": "2025-02-15T17:11:01+00:00" + }, + { + "name": "staudenmeir/eloquent-json-relations", + "version": "v1.14.2", + "source": { + "type": "git", + "url": "https://github.com/staudenmeir/eloquent-json-relations.git", + "reference": "9e39de2270edaec445362a3d20562d863b0b50de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staudenmeir/eloquent-json-relations/zipball/9e39de2270edaec445362a3d20562d863b0b50de", + "reference": "9e39de2270edaec445362a3d20562d863b0b50de", + "shasum": "" + }, + "require": { + "illuminate/database": "^12.0", + "php": "^8.2", + "staudenmeir/eloquent-has-many-deep-contracts": "^1.3" + }, + "require-dev": { + "barryvdh/laravel-ide-helper": "^3.0", + "larastan/larastan": "^3.0", + "laravel/framework": "^12.0", + "mockery/mockery": "^1.5.1", + "orchestra/testbench-core": "^10.0", + "phpunit/phpunit": "^11.0", + "staudenmeir/eloquent-has-many-deep": "^1.21" }, "type": "library", "extra": { @@ -9638,7 +9998,7 @@ "description": "Laravel Eloquent relationships with JSON keys", "support": { "issues": "https://github.com/staudenmeir/eloquent-json-relations/issues", - "source": "https://github.com/staudenmeir/eloquent-json-relations/tree/v1.14.1" + "source": "https://github.com/staudenmeir/eloquent-json-relations/tree/v1.14.2" }, "funding": [ { @@ -9646,7 +10006,7 @@ "type": "custom" } ], - "time": "2025-02-25T21:36:38+00:00" + "time": "2026-03-01T11:12:21+00:00" }, { "name": "stechstudio/filament-impersonate", @@ -9692,16 +10052,16 @@ }, { "name": "symfony/clock", - "version": "v7.4.0", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "9169f24776edde469914c1e7a1442a50f7a4e110" + "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/9169f24776edde469914c1e7a1442a50f7a4e110", - "reference": "9169f24776edde469914c1e7a1442a50f7a4e110", + "url": "https://api.github.com/repos/symfony/clock/zipball/674fa3b98e21531dd040e613479f5f6fa8f32111", + "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111", "shasum": "" }, "require": { @@ -9746,7 +10106,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.4.0" + "source": "https://github.com/symfony/clock/tree/v7.4.8" }, "funding": [ { @@ -9766,20 +10126,20 @@ "type": "tidelift" } ], - "time": "2025-11-12T15:39:26+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/console", - "version": "v7.4.6", + "version": "v7.4.11", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "6d643a93b47398599124022eb24d97c153c12f27" + "reference": "ed0107e43ab452aa77ae99e005b95e56b556e075" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6d643a93b47398599124022eb24d97c153c12f27", - "reference": "6d643a93b47398599124022eb24d97c153c12f27", + "url": "https://api.github.com/repos/symfony/console/zipball/ed0107e43ab452aa77ae99e005b95e56b556e075", + "reference": "ed0107e43ab452aa77ae99e005b95e56b556e075", "shasum": "" }, "require": { @@ -9844,7 +10204,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.6" + "source": "https://github.com/symfony/console/tree/v7.4.11" }, "funding": [ { @@ -9864,20 +10224,20 @@ "type": "tidelift" } ], - "time": "2026-02-25T17:02:47+00:00" + "time": "2026-05-13T12:04:42+00:00" }, { "name": "symfony/css-selector", - "version": "v7.4.0", + "version": "v7.4.9", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "ab862f478513e7ca2fe9ec117a6f01a8da6e1135" + "reference": "b75663ed96cf4756e28e3105476f220f92886cc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/ab862f478513e7ca2fe9ec117a6f01a8da6e1135", - "reference": "ab862f478513e7ca2fe9ec117a6f01a8da6e1135", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/b75663ed96cf4756e28e3105476f220f92886cc4", + "reference": "b75663ed96cf4756e28e3105476f220f92886cc4", "shasum": "" }, "require": { @@ -9913,7 +10273,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.4.0" + "source": "https://github.com/symfony/css-selector/tree/v7.4.9" }, "funding": [ { @@ -9933,20 +10293,20 @@ "type": "tidelift" } ], - "time": "2025-10-30T13:39:42+00:00" + "time": "2026-04-18T13:18:21+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.6.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/50f59d1f3ca46d41ac911f97a78626b6756af35b", + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b", "shasum": "" }, "require": { @@ -9959,7 +10319,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -9984,7 +10344,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.0" }, "funding": [ { @@ -9995,25 +10355,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": "2024-09-25T14:21:43+00:00" + "time": "2026-04-13T15:52:40+00:00" }, { "name": "symfony/error-handler", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "8da531f364ddfee53e36092a7eebbbd0b775f6b8" + "reference": "8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/8da531f364ddfee53e36092a7eebbbd0b775f6b8", - "reference": "8da531f364ddfee53e36092a7eebbbd0b775f6b8", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa", + "reference": "8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa", "shasum": "" }, "require": { @@ -10062,7 +10426,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.4" + "source": "https://github.com/symfony/error-handler/tree/v7.4.8" }, "funding": [ { @@ -10082,20 +10446,20 @@ "type": "tidelift" } ], - "time": "2026-01-20T16:42:42+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.4.4", + "version": "v7.4.9", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "dc2c0eba1af673e736bb851d747d266108aea746" + "reference": "e4a2e29753c7801f7a8340e066cfa788f3bc8101" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/dc2c0eba1af673e736bb851d747d266108aea746", - "reference": "dc2c0eba1af673e736bb851d747d266108aea746", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e4a2e29753c7801f7a8340e066cfa788f3bc8101", + "reference": "e4a2e29753c7801f7a8340e066cfa788f3bc8101", "shasum": "" }, "require": { @@ -10147,7 +10511,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/v7.4.4" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.9" }, "funding": [ { @@ -10167,20 +10531,20 @@ "type": "tidelift" } ], - "time": "2026-01-05T11:45:34+00:00" + "time": "2026-04-18T13:18:21+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.6.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/ccba7060602b7fed0b03c85bf025257f76d9ef32", + "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32", "shasum": "" }, "require": { @@ -10194,7 +10558,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -10227,7 +10591,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.0" }, "funding": [ { @@ -10238,25 +10602,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": "2024-09-25T14:21:43+00:00" + "time": "2026-01-05T13:30:16+00:00" }, { "name": "symfony/filesystem", - "version": "v7.4.6", + "version": "v7.4.11", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e" + "reference": "d721ea61b4a5fba8c5b6e7c1feda19efea144b50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/3ebc794fa5315e59fd122561623c2e2e4280538e", - "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/d721ea61b4a5fba8c5b6e7c1feda19efea144b50", + "reference": "d721ea61b4a5fba8c5b6e7c1feda19efea144b50", "shasum": "" }, "require": { @@ -10293,7 +10661,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.4.6" + "source": "https://github.com/symfony/filesystem/tree/v7.4.11" }, "funding": [ { @@ -10313,20 +10681,20 @@ "type": "tidelift" } ], - "time": "2026-02-25T16:50:00+00:00" + "time": "2026-05-11T16:38:44+00:00" }, { "name": "symfony/finder", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf" + "reference": "e0be088d22278583a82da281886e8c3592fbf149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8655bf1076b7a3a346cb11413ffdabff50c7ffcf", - "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf", + "url": "https://api.github.com/repos/symfony/finder/zipball/e0be088d22278583a82da281886e8c3592fbf149", + "reference": "e0be088d22278583a82da281886e8c3592fbf149", "shasum": "" }, "require": { @@ -10361,7 +10729,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.6" + "source": "https://github.com/symfony/finder/tree/v7.4.8" }, "funding": [ { @@ -10381,20 +10749,20 @@ "type": "tidelift" } ], - "time": "2026-01-29T09:40:50+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/html-sanitizer", - "version": "v7.4.0", + "version": "v7.4.12", "source": { "type": "git", "url": "https://github.com/symfony/html-sanitizer.git", - "reference": "5b0bbcc3600030b535dd0b17a0e8c56243f96d7f" + "reference": "51cb4f68195883f7ac403abb58ecf7adc74e0f9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/html-sanitizer/zipball/5b0bbcc3600030b535dd0b17a0e8c56243f96d7f", - "reference": "5b0bbcc3600030b535dd0b17a0e8c56243f96d7f", + "url": "https://api.github.com/repos/symfony/html-sanitizer/zipball/51cb4f68195883f7ac403abb58ecf7adc74e0f9e", + "reference": "51cb4f68195883f7ac403abb58ecf7adc74e0f9e", "shasum": "" }, "require": { @@ -10435,7 +10803,7 @@ "sanitizer" ], "support": { - "source": "https://github.com/symfony/html-sanitizer/tree/v7.4.0" + "source": "https://github.com/symfony/html-sanitizer/tree/v7.4.12" }, "funding": [ { @@ -10455,20 +10823,20 @@ "type": "tidelift" } ], - "time": "2025-10-30T13:39:42+00:00" + "time": "2026-05-20T07:20:23+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.4.5", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "446d0db2b1f21575f1284b74533e425096abdfb6" + "reference": "9381209597ec66c25be154cbf2289076e64d1eab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/446d0db2b1f21575f1284b74533e425096abdfb6", - "reference": "446d0db2b1f21575f1284b74533e425096abdfb6", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9381209597ec66c25be154cbf2289076e64d1eab", + "reference": "9381209597ec66c25be154cbf2289076e64d1eab", "shasum": "" }, "require": { @@ -10517,7 +10885,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.5" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.8" }, "funding": [ { @@ -10537,20 +10905,20 @@ "type": "tidelift" } ], - "time": "2026-01-27T16:16:02+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.4.5", + "version": "v7.4.12", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "229eda477017f92bd2ce7615d06222ec0c19e82a" + "reference": "7922b53e70d2ba2027af8bb6a59d91eb3541ea4d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/229eda477017f92bd2ce7615d06222ec0c19e82a", - "reference": "229eda477017f92bd2ce7615d06222ec0c19e82a", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/7922b53e70d2ba2027af8bb6a59d91eb3541ea4d", + "reference": "7922b53e70d2ba2027af8bb6a59d91eb3541ea4d", "shasum": "" }, "require": { @@ -10592,7 +10960,7 @@ "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/dependency-injection": "^6.4.1|^7.0.1|^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", @@ -10636,7 +11004,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.5" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.12" }, "funding": [ { @@ -10656,20 +11024,20 @@ "type": "tidelift" } ], - "time": "2026-01-28T10:33:42+00:00" + "time": "2026-05-20T09:27:11+00:00" }, { "name": "symfony/mailer", - "version": "v7.4.4", + "version": "v7.4.12", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "7b750074c40c694ceb34cb926d6dffee231c5cd6" + "reference": "5cefb712a25f320579615ba9e1942abaeade7dff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/7b750074c40c694ceb34cb926d6dffee231c5cd6", - "reference": "7b750074c40c694ceb34cb926d6dffee231c5cd6", + "url": "https://api.github.com/repos/symfony/mailer/zipball/5cefb712a25f320579615ba9e1942abaeade7dff", + "reference": "5cefb712a25f320579615ba9e1942abaeade7dff", "shasum": "" }, "require": { @@ -10720,7 +11088,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.4.4" + "source": "https://github.com/symfony/mailer/tree/v7.4.12" }, "funding": [ { @@ -10740,20 +11108,20 @@ "type": "tidelift" } ], - "time": "2026-01-08T08:25:11+00:00" + "time": "2026-05-20T07:20:23+00:00" }, { "name": "symfony/mime", - "version": "v7.4.5", + "version": "v7.4.12", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "b18c7e6e9eee1e19958138df10412f3c4c316148" + "reference": "b198dd66c211c97119bcaaff7c13431dbbb5e470" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/b18c7e6e9eee1e19958138df10412f3c4c316148", - "reference": "b18c7e6e9eee1e19958138df10412f3c4c316148", + "url": "https://api.github.com/repos/symfony/mime/zipball/b198dd66c211c97119bcaaff7c13431dbbb5e470", + "reference": "b198dd66c211c97119bcaaff7c13431dbbb5e470", "shasum": "" }, "require": { @@ -10764,7 +11132,7 @@ }, "conflict": { "egulias/email-validator": "~3.0.0", - "phpdocumentor/reflection-docblock": "<5.2|>=6", + "phpdocumentor/reflection-docblock": "<5.2|>=7", "phpdocumentor/type-resolver": "<1.5.1", "symfony/mailer": "<6.4", "symfony/serializer": "<6.4.3|>7.0,<7.0.3" @@ -10772,7 +11140,7 @@ "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", - "phpdocumentor/reflection-docblock": "^5.2", + "phpdocumentor/reflection-docblock": "^5.2|^6.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", @@ -10809,7 +11177,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.4.5" + "source": "https://github.com/symfony/mime/tree/v7.4.12" }, "funding": [ { @@ -10829,20 +11197,20 @@ "type": "tidelift" } ], - "time": "2026-01-27T08:59:58+00:00" + "time": "2026-05-20T07:20:23+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", "shasum": "" }, "require": { @@ -10892,7 +11260,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0" }, "funding": [ { @@ -10912,20 +11280,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + "reference": "4864388bfbd3001ce88e234fab652acd91fdc57e" }, "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/4864388bfbd3001ce88e234fab652acd91fdc57e", + "reference": "4864388bfbd3001ce88e234fab652acd91fdc57e", "shasum": "" }, "require": { @@ -10974,7 +11342,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.37.0" }, "funding": [ { @@ -10994,11 +11362,11 @@ "type": "tidelift" } ], - "time": "2025-06-27T09:58:17+00:00" + "time": "2026-04-26T13:13:48+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", @@ -11061,7 +11429,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.37.0" }, "funding": [ { @@ -11085,7 +11453,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -11146,7 +11514,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.37.0" }, "funding": [ { @@ -11170,16 +11538,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6a21eb99c6973357967f6ce3708cd55a6bec6315", + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315", "shasum": "" }, "require": { @@ -11231,7 +11599,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.37.0" }, "funding": [ { @@ -11251,11 +11619,11 @@ "type": "tidelift" } ], - "time": "2024-12-23T08:48:59+00:00" + "time": "2026-04-10T17:25:58+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", @@ -11311,7 +11679,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.37.0" }, "funding": [ { @@ -11335,16 +11703,16 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411", + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411", "shasum": "" }, "require": { @@ -11395,7 +11763,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.37.0" }, "funding": [ { @@ -11415,11 +11783,11 @@ "type": "tidelift" } ], - "time": "2025-01-02T08:10:11+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", @@ -11475,7 +11843,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.37.0" }, "funding": [ { @@ -11499,16 +11867,16 @@ }, { "name": "symfony/polyfill-php83", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" + "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149" }, "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/3600c2cb22399e25bb226e4a135ce91eeb2a6149", + "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149", "shasum": "" }, "require": { @@ -11555,7 +11923,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.37.0" }, "funding": [ { @@ -11575,20 +11943,20 @@ "type": "tidelift" } ], - "time": "2025-07-08T02:45:35+00:00" + "time": "2026-04-10T17:25:58+00:00" }, { "name": "symfony/polyfill-php84", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php84.git", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" + "reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/88486db2c389b290bf87ff1de7ebc1e13e42bb06", + "reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06", "shasum": "" }, "require": { @@ -11635,7 +12003,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php84/tree/v1.37.0" }, "funding": [ { @@ -11655,20 +12023,20 @@ "type": "tidelift" } ], - "time": "2025-06-24T13:30:11+00:00" + "time": "2026-04-10T18:47:49+00:00" }, { "name": "symfony/polyfill-php85", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php85.git", - "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91" + "reference": "fcfa4973a9917cef23f2e38774da74a2b7d115ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", - "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/fcfa4973a9917cef23f2e38774da74a2b7d115ee", + "reference": "fcfa4973a9917cef23f2e38774da74a2b7d115ee", "shasum": "" }, "require": { @@ -11715,7 +12083,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.37.0" }, "funding": [ { @@ -11735,20 +12103,20 @@ "type": "tidelift" } ], - "time": "2025-06-23T16:12:55+00:00" + "time": "2026-04-26T13:10:57+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" + "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", - "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/26dfec253c4cf3e51b541b52ddf7e42cb0908e94", + "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94", "shasum": "" }, "require": { @@ -11798,7 +12166,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.37.0" }, "funding": [ { @@ -11818,20 +12186,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/process", - "version": "v7.4.5", + "version": "v7.4.11", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "608476f4604102976d687c483ac63a79ba18cc97" + "reference": "d9593c9efa40499eb078b81144de42cbc28a31f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/608476f4604102976d687c483ac63a79ba18cc97", - "reference": "608476f4604102976d687c483ac63a79ba18cc97", + "url": "https://api.github.com/repos/symfony/process/zipball/d9593c9efa40499eb078b81144de42cbc28a31f0", + "reference": "d9593c9efa40499eb078b81144de42cbc28a31f0", "shasum": "" }, "require": { @@ -11863,7 +12231,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.4.5" + "source": "https://github.com/symfony/process/tree/v7.4.11" }, "funding": [ { @@ -11883,45 +12251,34 @@ "type": "tidelift" } ], - "time": "2026-01-26T15:07:59+00:00" + "time": "2026-05-11T16:55:21+00:00" }, { - "name": "symfony/psr-http-message-bridge", - "version": "v7.3.0", + "name": "symfony/property-access", + "version": "v7.4.8", "source": { "type": "git", - "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f" + "url": "https://github.com/symfony/property-access.git", + "reference": "b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", + "url": "https://api.github.com/repos/symfony/property-access/zipball/b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc", + "reference": "b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc", "shasum": "" }, "require": { "php": ">=8.2", - "psr/http-message": "^1.0|^2.0", - "symfony/http-foundation": "^6.4|^7.0" - }, - "conflict": { - "php-http/discovery": "<1.15", - "symfony/http-kernel": "<6.4" + "symfony/property-info": "^6.4.32|~7.3.10|^7.4.4|^8.0.4" }, "require-dev": { - "nyholm/psr7": "^1.1", - "php-http/discovery": "^1.15", - "psr/log": "^1.1.4|^2|^3", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0" + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4.1|^7.0.1|^8.0" }, - "type": "symfony-bridge", + "type": "library", "autoload": { "psr-4": { - "Symfony\\Bridge\\PsrHttpMessage\\": "" + "Symfony\\Component\\PropertyAccess\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -11941,16 +12298,21 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "PSR HTTP message bridge", + "description": "Provides functions to read and write from/to an object or array using a simple string notation", "homepage": "https://symfony.com", "keywords": [ - "http", - "http-message", - "psr-17", - "psr-7" + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property-path", + "reflection" ], "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.3.0" + "source": "https://github.com/symfony/property-access/tree/v7.4.8" }, "funding": [ { @@ -11961,48 +12323,55 @@ "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": "2024-09-26T08:57:56+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { - "name": "symfony/routing", - "version": "v7.4.4", + "name": "symfony/property-info", + "version": "v7.4.8", "source": { "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "0798827fe2c79caeed41d70b680c2c3507d10147" + "url": "https://github.com/symfony/property-info.git", + "reference": "ac5e82528b986c4f7cfccbf7764b5d2e824d6175" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/0798827fe2c79caeed41d70b680c2c3507d10147", - "reference": "0798827fe2c79caeed41d70b680c2c3507d10147", + "url": "https://api.github.com/repos/symfony/property-info/zipball/ac5e82528b986c4f7cfccbf7764b5d2e824d6175", + "reference": "ac5e82528b986c4f7cfccbf7764b5d2e824d6175", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/type-info": "^7.4.7|^8.0.7" }, "conflict": { - "symfony/config": "<6.4", + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/cache": "<6.4", "symfony/dependency-injection": "<6.4", - "symfony/yaml": "<6.4" + "symfony/serializer": "<6.4" }, "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", + "phpdocumentor/reflection-docblock": "^5.2|^6.0", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "symfony/cache": "^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/serializer": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Routing\\": "" + "Symfony\\Component\\PropertyInfo\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -12014,24 +12383,26 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Maps an HTTP request to a set of configuration variables", + "description": "Extracts information about PHP class' properties using metadata of popular sources", "homepage": "https://symfony.com", "keywords": [ - "router", - "routing", - "uri", - "url" + "doctrine", + "phpdoc", + "property", + "symfony", + "type", + "validator" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.4.4" + "source": "https://github.com/symfony/property-info/tree/v7.4.8" }, "funding": [ { @@ -12051,46 +12422,49 @@ "type": "tidelift" } ], - "time": "2026-01-12T12:19:02+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { - "name": "symfony/service-contracts", - "version": "v3.6.1", + "name": "symfony/psr-http-message-bridge", + "version": "v7.4.8", "source": { "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" + "url": "https://github.com/symfony/psr-http-message-bridge.git", + "reference": "76f1a57719a4a04c0ea18678a6c9305b5dcb9da8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/76f1a57719a4a04c0ea18678a6c9305b5dcb9da8", + "reference": "76f1a57719a4a04c0ea18678a6c9305b5dcb9da8", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.2", + "psr/http-message": "^1.0|^2.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0" }, "conflict": { - "ext-psr": "<1.1|>=2" + "php-http/discovery": "<1.15", + "symfony/http-kernel": "<6.4" }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } + "require-dev": { + "nyholm/psr7": "^1.1", + "php-http/discovery": "^1.15", + "psr/log": "^1.1.4|^2|^3", + "symfony/browser-kit": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4.13|^7.1.6|^8.0", + "symfony/http-kernel": "^6.4.13|^7.1.6|^8.0", + "symfony/runtime": "^6.4.13|^7.1.6|^8.0" }, + "type": "symfony-bridge", "autoload": { "psr-4": { - "Symfony\\Contracts\\Service\\": "" + "Symfony\\Bridge\\PsrHttpMessage\\": "" }, "exclude-from-classmap": [ - "/Test/" + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -12099,26 +12473,24 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Generic abstractions related to writing services", + "description": "PSR HTTP message bridge", "homepage": "https://symfony.com", "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" + "http", + "http-message", + "psr-17", + "psr-7" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.4.8" }, "funding": [ { @@ -12138,47 +12510,43 @@ "type": "tidelift" } ], - "time": "2025-07-15T11:30:57+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { - "name": "symfony/string", - "version": "v7.4.6", + "name": "symfony/routing", + "version": "v7.4.12", "source": { "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "9f209231affa85aa930a5e46e6eb03381424b30b" + "url": "https://github.com/symfony/routing.git", + "reference": "3b04a5ec4887a8135a12ebf0f4cbc5b8fc8ee204" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/9f209231affa85aa930a5e46e6eb03381424b30b", - "reference": "9f209231affa85aa930a5e46e6eb03381424b30b", + "url": "https://api.github.com/repos/symfony/routing/zipball/3b04a5ec4887a8135a12ebf0f4cbc5b8fc8ee204", + "reference": "3b04a5ec4887a8135a12ebf0f4cbc5b8fc8ee204", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.33", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { - "symfony/translation-contracts": "<2.5" + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" }, "require-dev": { - "symfony/emoji": "^7.1|^8.0", - "symfony/http-client": "^6.4|^7.0|^8.0", - "symfony/intl": "^6.4|^7.0|^8.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0|^8.0" + "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" }, "type": "library", "autoload": { - "files": [ - "Resources/functions.php" - ], "psr-4": { - "Symfony\\Component\\String\\": "" + "Symfony\\Component\\Routing\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -12190,26 +12558,24 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "description": "Maps an HTTP request to a set of configuration variables", "homepage": "https://symfony.com", "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], + "router", + "routing", + "uri", + "url" + ], "support": { - "source": "https://github.com/symfony/string/tree/v7.4.6" + "source": "https://github.com/symfony/routing/tree/v7.4.12" }, "funding": [ { @@ -12229,20 +12595,302 @@ "type": "tidelift" } ], - "time": "2026-02-09T09:33:46+00:00" + "time": "2026-05-20T07:20:23+00:00" + }, + { + "name": "symfony/serializer", + "version": "v7.4.10", + "source": { + "type": "git", + "url": "https://github.com/symfony/serializer.git", + "reference": "268c5aa6c4bd675eddd89348e7ecac292a843ddd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/serializer/zipball/268c5aa6c4bd675eddd89348e7ecac292a843ddd", + "reference": "268c5aa6c4bd675eddd89348e7ecac292a843ddd", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php84": "^1.30" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/dependency-injection": "<6.4", + "symfony/property-access": "<6.4.31|>=7.0,<7.4.2|>=8.0,<8.0.2", + "symfony/property-info": "<6.4", + "symfony/type-info": "<7.2.5", + "symfony/uid": "<6.4", + "symfony/validator": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "phpdocumentor/reflection-docblock": "^5.2|^6.0", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "seld/jsonlint": "^1.10", + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^7.2|^8.0", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/filesystem": "^6.4|^7.0|^8.0", + "symfony/form": "^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/messenger": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/property-access": "^6.4.31|^7.4.2|^8.0.2", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/type-info": "^7.2.5|^8.0", + "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/yaml": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Serializer\\": "" + }, + "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": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/serializer/tree/v7.4.10" + }, + "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": "2026-05-03T13:03:28+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.7.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d25d82433a80eba6aa0e6c24b61d7370d99e444a", + "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "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": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.7.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": "2026-03-28T09:44:51+00:00" + }, + { + "name": "symfony/string", + "version": "v7.4.11", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "965f7306a43383d02c6aca1e3f3bd2f0ea5dee15" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/965f7306a43383d02c6aca1e3f3bd2f0ea5dee15", + "reference": "965f7306a43383d02c6aca1e3f3bd2f0ea5dee15", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.33", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.4.11" + }, + "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": "2026-05-13T12:04:42+00:00" }, { "name": "symfony/translation", - "version": "v7.4.4", + "version": "v7.4.10", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "bfde13711f53f549e73b06d27b35a55207528877" + "reference": "ada7578c30dd5feaa8259cff3e885069ea81ddde" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/bfde13711f53f549e73b06d27b35a55207528877", - "reference": "bfde13711f53f549e73b06d27b35a55207528877", + "url": "https://api.github.com/repos/symfony/translation/zipball/ada7578c30dd5feaa8259cff3e885069ea81ddde", + "reference": "ada7578c30dd5feaa8259cff3e885069ea81ddde", "shasum": "" }, "require": { @@ -12298,18 +12946,100 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v7.4.10" + }, + "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": "2026-05-06T11:19:24+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.7.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/0ab302977a952b42fd51475c4ebac81f8da0a95d", + "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "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": "Provides tools to internationalize your application", + "description": "Generic abstractions related to translation", "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], "support": { - "source": "https://github.com/symfony/translation/tree/v7.4.4" + "source": "https://github.com/symfony/translation-contracts/tree/v3.7.0" }, "funding": [ { @@ -12329,41 +13059,40 @@ "type": "tidelift" } ], - "time": "2026-01-13T10:40:19+00:00" + "time": "2026-01-05T13:30:16+00:00" }, { - "name": "symfony/translation-contracts", - "version": "v3.6.1", + "name": "symfony/type-info", + "version": "v7.4.9", "source": { "type": "git", - "url": "https://github.com/symfony/translation-contracts.git", - "reference": "65a8bc82080447fae78373aa10f8d13b38338977" + "url": "https://github.com/symfony/type-info.git", + "reference": "cafeedbf157b890e94ac5b83eaed85595106d5d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/65a8bc82080447fae78373aa10f8d13b38338977", - "reference": "65a8bc82080447fae78373aa10f8d13b38338977", + "url": "https://api.github.com/repos/symfony/type-info/zipball/cafeedbf157b890e94ac5b83eaed85595106d5d6", + "reference": "cafeedbf157b890e94ac5b83eaed85595106d5d6", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } + "conflict": { + "phpstan/phpdoc-parser": "<1.30" + }, + "require-dev": { + "phpstan/phpdoc-parser": "^1.30|^2.0" }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\Contracts\\Translation\\": "" + "Symfony\\Component\\TypeInfo\\": "" }, "exclude-from-classmap": [ - "/Test/" + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -12372,26 +13101,28 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Mathias Arlaud", + "email": "mathias.arlaud@gmail.com" + }, + { + "name": "Baptiste LEDUC", + "email": "baptiste.leduc@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Generic abstractions related to translation", + "description": "Extracts PHP types information.", "homepage": "https://symfony.com", "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" + "PHPStan", + "phpdoc", + "symfony", + "type" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.6.1" + "source": "https://github.com/symfony/type-info/tree/v7.4.9" }, "funding": [ { @@ -12411,20 +13142,20 @@ "type": "tidelift" } ], - "time": "2025-07-15T13:41:35+00:00" + "time": "2026-04-22T15:21:55+00:00" }, { "name": "symfony/uid", - "version": "v7.4.4", + "version": "v7.4.9", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36" + "reference": "2676b524340abcfe4d6151ec698463cebafee439" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/7719ce8aba76be93dfe249192f1fbfa52c588e36", - "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36", + "url": "https://api.github.com/repos/symfony/uid/zipball/2676b524340abcfe4d6151ec698463cebafee439", + "reference": "2676b524340abcfe4d6151ec698463cebafee439", "shasum": "" }, "require": { @@ -12469,7 +13200,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.4.4" + "source": "https://github.com/symfony/uid/tree/v7.4.9" }, "funding": [ { @@ -12489,20 +13220,20 @@ "type": "tidelift" } ], - "time": "2026-01-03T23:30:35+00:00" + "time": "2026-04-30T15:19:22+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "0e4769b46a0c3c62390d124635ce59f66874b282" + "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/0e4769b46a0c3c62390d124635ce59f66874b282", - "reference": "0e4769b46a0c3c62390d124635ce59f66874b282", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9510c3966f749a1d1ff0059e1eabef6cc621e7fd", + "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd", "shasum": "" }, "require": { @@ -12556,7 +13287,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.4.4" + "source": "https://github.com/symfony/var-dumper/tree/v7.4.8" }, "funding": [ { @@ -12576,20 +13307,20 @@ "type": "tidelift" } ], - "time": "2026-01-01T22:13:48+00:00" + "time": "2026-03-30T13:44:50+00:00" }, { "name": "tightenco/ziggy", - "version": "v2.5.3", + "version": "v2.6.2", "source": { "type": "git", "url": "https://github.com/tighten/ziggy.git", - "reference": "0b3b521d2c55fbdb04b6721532f7f5f49d32f52b" + "reference": "8a0b645921623f77dceaf543d61ecd51a391d96e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tighten/ziggy/zipball/0b3b521d2c55fbdb04b6721532f7f5f49d32f52b", - "reference": "0b3b521d2c55fbdb04b6721532f7f5f49d32f52b", + "url": "https://api.github.com/repos/tighten/ziggy/zipball/8a0b645921623f77dceaf543d61ecd51a391d96e", + "reference": "8a0b645921623f77dceaf543d61ecd51a391d96e", "shasum": "" }, "require": { @@ -12599,9 +13330,9 @@ }, "require-dev": { "laravel/folio": "^1.1", - "orchestra/testbench": "^7.0 || ^8.0 || ^9.0 || ^10.0", - "pestphp/pest": "^2.26|^3.0", - "pestphp/pest-plugin-laravel": "^2.4|^3.0" + "orchestra/testbench": "^8.0 || ^9.0 || ^10.0", + "pestphp/pest": "^2.0 || ^3.0 || ^4.0", + "pestphp/pest-plugin-laravel": "^2.0 || ^3.0 || ^4.0" }, "type": "library", "extra": { @@ -12644,9 +13375,9 @@ ], "support": { "issues": "https://github.com/tighten/ziggy/issues", - "source": "https://github.com/tighten/ziggy/tree/v2.5.3" + "source": "https://github.com/tighten/ziggy/tree/v2.6.2" }, - "time": "2025-05-17T18:15:19+00:00" + "time": "2026-03-05T14:41:19+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -12705,22 +13436,21 @@ }, { "name": "tpetry/laravel-postgresql-enhanced", - "version": "3.0.0", + "version": "3.7.0", "source": { "type": "git", "url": "https://github.com/tpetry/laravel-postgresql-enhanced.git", - "reference": "816f36fc3b3e0a3daf90f61d8d9dd76eb15ec6f4" + "reference": "a3c9df5f29f188f06645aa9e8c11198101873106" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tpetry/laravel-postgresql-enhanced/zipball/816f36fc3b3e0a3daf90f61d8d9dd76eb15ec6f4", - "reference": "816f36fc3b3e0a3daf90f61d8d9dd76eb15ec6f4", + "url": "https://api.github.com/repos/tpetry/laravel-postgresql-enhanced/zipball/a3c9df5f29f188f06645aa9e8c11198101873106", + "reference": "a3c9df5f29f188f06645aa9e8c11198101873106", "shasum": "" }, "require": { "doctrine/dbal": "^2.6|^3.5|^4.0", - "illuminate/database": "^6.0|^7.0|^8.79|^9.0|^10.0|^11.0|^12.0", - "laravel/framework": "*", + "laravel/framework": "^6.0|^7.0|^8.79|^9.0|^10.0|^11.0|^12.0|^13.0", "php": "^8.0", "spatie/regex": "^2.0|^3.0" }, @@ -12729,28 +13459,244 @@ "friendsofphp/php-cs-fixer": "^2.19.3|^3.5.0", "larastan/larastan": "^1.0|^2.1|^3.0", "nesbot/carbon": "^2.7|^3.3", - "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0|^9.0|^10.0", + "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0|^9.15.0|^10.0|^11.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.5|^2.0", "phpunit/phpunit": "^8.5.23|^9.5.13|^10.5|^11.4", - "ramsey/uuid": "^3.9|^4.7" + "ramsey/uuid": "^3.9|^4.7", + "symfony/polyfill-php86": "^1.37" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Tpetry\\PostgresqlEnhanced\\PostgresqlEnhancedServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "phpstan-extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Tpetry\\PostgresqlEnhanced\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "tpetry", + "email": "tobias@tpetry.me" + } + ], + "description": "Support for many missing PostgreSQL specific features", + "homepage": "https://github.com/tpetry/laravel-postgresql-enhanced", + "keywords": [ + "laravel", + "postgresql" + ], + "support": { + "issues": "https://github.com/tpetry/laravel-postgresql-enhanced/issues", + "source": "https://github.com/tpetry/laravel-postgresql-enhanced/tree/3.7.0" + }, + "time": "2026-05-17T10:02:20+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.6.3", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "955e7815d677a3eaa7075231212f2110983adecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc", + "reference": "955e7815d677a3eaa7075231212f2110983adecc", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.1.4", + "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" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-filter": "*", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2025-12-27T19:49:13+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "8e1051fe39379367aecf014f41744ce7539a856f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/8e1051fe39379367aecf014f41744ce7539a856f", + "reference": "8e1051fe39379367aecf014f41744ce7539a856f", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpunit/phpunit": "~8.5 || ~9.6 || ~10.5 || ~11.5" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "https://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.1.1" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2026-04-26T05:33:54+00:00" + }, + { + "name": "web-auth/cose-lib", + "version": "4.5.2", + "source": { + "type": "git", + "url": "https://github.com/web-auth/cose-lib.git", + "reference": "5b38660f90070a8e45f3dbc9528ade3b608dd77d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/5b38660f90070a8e45f3dbc9528ade3b608dd77d", + "reference": "5b38660f90070a8e45f3dbc9528ade3b608dd77d", + "shasum": "" + }, + "require": { + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17", + "ext-json": "*", + "ext-openssl": "*", + "php": ">=8.1", + "spomky-labs/pki-framework": "^1.0" + }, + "require-dev": { + "spomky-labs/cbor-php": "^3.2.2" + }, + "suggest": { + "ext-bcmath": "For better performance, please install either GMP (recommended) or BCMath extension", + "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension", + "spomky-labs/cbor-php": "For COSE Signature support" }, "type": "library", - "extra": { - "laravel": { - "providers": [ - "Tpetry\\PostgresqlEnhanced\\PostgresqlEnhancedServiceProvider" - ] - }, - "phpstan": { - "includes": [ - "phpstan-extension.neon" - ] - } - }, "autoload": { "psr-4": { - "Tpetry\\PostgresqlEnhanced\\": "src" + "Cose\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -12759,133 +13705,160 @@ ], "authors": [ { - "name": "tpetry", - "email": "tobias@tpetry.me" + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/web-auth/cose/contributors" } ], - "description": "Support for many missing PostgreSQL specific features", - "homepage": "https://github.com/tpetry/laravel-postgresql-enhanced", + "description": "CBOR Object Signing and Encryption (COSE) For PHP", + "homepage": "https://github.com/web-auth", "keywords": [ - "laravel", - "postgresql" + "COSE", + "RFC8152" ], "support": { - "issues": "https://github.com/tpetry/laravel-postgresql-enhanced/issues", - "source": "https://github.com/tpetry/laravel-postgresql-enhanced/tree/3.0.0" + "issues": "https://github.com/web-auth/cose-lib/issues", + "source": "https://github.com/web-auth/cose-lib/tree/4.5.2" }, - "time": "2025-04-23T10:19:01+00:00" + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2026-05-03T09:49:50+00:00" }, { - "name": "vlucas/phpdotenv", - "version": "v5.6.3", + "name": "web-auth/webauthn-lib", + "version": "5.3.5", "source": { "type": "git", - "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "955e7815d677a3eaa7075231212f2110983adecc" + "url": "https://github.com/web-auth/webauthn-lib.git", + "reference": "9e0986d999f4102e24ac8a598d3a80d98b56c19f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc", - "reference": "955e7815d677a3eaa7075231212f2110983adecc", + "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/9e0986d999f4102e24ac8a598d3a80d98b56c19f", + "reference": "9e0986d999f4102e24ac8a598d3a80d98b56c19f", "shasum": "" }, "require": { - "ext-pcre": "*", - "graham-campbell/result-type": "^1.1.4", - "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" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "ext-filter": "*", - "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + "ext-json": "*", + "ext-openssl": "*", + "paragonie/constant_time_encoding": "^2.6|^3.0", + "php": ">=8.2", + "phpdocumentor/reflection-docblock": "^5.3|^6.0", + "psr/clock": "^1.0", + "psr/event-dispatcher": "^1.0", + "psr/log": "^1.0|^2.0|^3.0", + "spomky-labs/cbor-php": "^3.0", + "spomky-labs/pki-framework": "^1.0", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/deprecation-contracts": "^3.2", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", + "web-auth/cose-lib": "^4.2.3" }, "suggest": { - "ext-filter": "Required to use the boolean validator." + "psr/log-implementation": "Recommended to receive logs from the library", + "symfony/event-dispatcher": "Recommended to use dispatched events", + "web-token/jwt-library": "Mandatory for fetching Metadata Statement from distant sources" }, "type": "library", "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - }, - "branch-alias": { - "dev-master": "5.6-dev" + "thanks": { + "url": "https://github.com/web-auth/webauthn-framework", + "name": "web-auth/webauthn-framework" } }, "autoload": { "psr-4": { - "Dotenv\\": "src/" + "Webauthn\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" }, { - "name": "Vance Lucas", - "email": "vance@vancelucas.com", - "homepage": "https://github.com/vlucas" + "name": "All contributors", + "homepage": "https://github.com/web-auth/webauthn-library/contributors" } ], - "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "description": "FIDO2/Webauthn Support For PHP", + "homepage": "https://github.com/web-auth", "keywords": [ - "dotenv", - "env", - "environment" + "FIDO2", + "fido", + "webauthn" ], "support": { - "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.3" + "source": "https://github.com/web-auth/webauthn-lib/tree/5.3.5" }, "funding": [ { - "url": "https://github.com/GrahamCampbell", + "url": "https://github.com/Spomky", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", - "type": "tidelift" + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" } ], - "time": "2025-12-27T19:49:13+00:00" + "time": "2026-05-31T15:00:08+00:00" }, { - "name": "voku/portable-ascii", - "version": "2.0.3", + "name": "webmozart/assert", + "version": "2.4.0", "source": { "type": "git", - "url": "https://github.com/voku/portable-ascii.git", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + "url": "https://github.com/webmozarts/assert.git", + "reference": "9007ea6f45ecf352a9422b36644e4bfc039b9155" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/9007ea6f45ecf352a9422b36644e4bfc039b9155", + "reference": "9007ea6f45ecf352a9422b36644e4bfc039b9155", "shasum": "" }, "require": { - "php": ">=7.0.0" - }, - "require-dev": { - "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + "ext-ctype": "*", + "ext-date": "*", + "ext-filter": "*", + "php": "^8.2" }, "suggest": { - "ext-intl": "Use Intl for transliterator_transliterate() support" + "ext-intl": "", + "ext-simplexml": "", + "ext-spl": "" }, "type": "library", + "extra": { + "psalm": { + "pluginClass": "Webmozart\\Assert\\PsalmPlugin" + }, + "branch-alias": { + "dev-master": "2.0-dev", + "dev-feature/2-0": "2.0-dev" + } + }, "autoload": { "psr-4": { - "voku\\": "src/voku/" + "Webmozart\\Assert\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -12894,44 +13867,25 @@ ], "authors": [ { - "name": "Lars Moelleken", - "homepage": "https://www.moelleken.org/" + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Woody Gilk", + "email": "woody.gilk@gmail.com" } ], - "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", - "homepage": "https://github.com/voku/portable-ascii", + "description": "Assertions to validate method input/output with nice error messages.", "keywords": [ - "ascii", - "clean", - "php" + "assert", + "check", + "validate" ], "support": { - "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/2.4.0" }, - "funding": [ - { - "url": "https://www.paypal.me/moelleken", - "type": "custom" - }, - { - "url": "https://github.com/voku", - "type": "github" - }, - { - "url": "https://opencollective.com/portable-ascii", - "type": "open_collective" - }, - { - "url": "https://www.patreon.com/voku", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", - "type": "tidelift" - } - ], - "time": "2024-11-21T01:49:47+00:00" + "time": "2026-05-20T13:07:01+00:00" }, { "name": "wikimedia/composer-merge-plugin", @@ -12993,38 +13947,39 @@ "packages-dev": [ { "name": "barryvdh/laravel-ide-helper", - "version": "v3.5.5", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "8d441ec99f8612b942b55f5183151d91591b618a" + "reference": "ad7e37676f1ff985d55ef1b6b96a0c0a40f2609a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/8d441ec99f8612b942b55f5183151d91591b618a", - "reference": "8d441ec99f8612b942b55f5183151d91591b618a", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/ad7e37676f1ff985d55ef1b6b96a0c0a40f2609a", + "reference": "ad7e37676f1ff985d55ef1b6b96a0c0a40f2609a", "shasum": "" }, "require": { - "barryvdh/reflection-docblock": "^2.3", + "barryvdh/reflection-docblock": "^2.4", "composer/class-map-generator": "^1.0", "ext-json": "*", - "illuminate/console": "^11.15 || ^12", - "illuminate/database": "^11.15 || ^12", - "illuminate/filesystem": "^11.15 || ^12", - "illuminate/support": "^11.15 || ^12", + "illuminate/console": "^11.15 || ^12 || ^13.0", + "illuminate/database": "^11.15 || ^12 || ^13.0", + "illuminate/filesystem": "^11.15 || ^12 || ^13.0", + "illuminate/support": "^11.15 || ^12 || ^13.0", "php": "^8.2" }, "require-dev": { "ext-pdo_sqlite": "*", "friendsofphp/php-cs-fixer": "^3", - "illuminate/config": "^11.15 || ^12", - "illuminate/view": "^11.15 || ^12", + "illuminate/config": "^11.15 || ^12 || ^13.0", + "illuminate/view": "^11.15 || ^12 || ^13.0", + "larastan/larastan": "^3.1", "mockery/mockery": "^1.4", - "orchestra/testbench": "^9.2 || ^10", - "phpunit/phpunit": "^10.5 || ^11.5.3", + "orchestra/testbench": "^9.2 || ^10 || ^11.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5 || ^11.5.3 || ^12.5.12", "spatie/phpunit-snapshot-assertions": "^4 || ^5", - "vimeo/psalm": "^5.4", "vlucas/phpdotenv": "^5" }, "suggest": { @@ -13038,7 +13993,7 @@ ] }, "branch-alias": { - "dev-master": "3.5-dev" + "dev-master": "3.6-dev" } }, "autoload": { @@ -13071,7 +14026,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-ide-helper/issues", - "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.5.5" + "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.7.0" }, "funding": [ { @@ -13083,20 +14038,20 @@ "type": "github" } ], - "time": "2025-02-11T13:59:46+00:00" + "time": "2026-03-17T14:12:51+00:00" }, { "name": "barryvdh/reflection-docblock", - "version": "v2.3.1", + "version": "v2.4.1", "source": { "type": "git", "url": "https://github.com/barryvdh/ReflectionDocBlock.git", - "reference": "b6ff9f93603561f50e53b64310495d20b8dff5d8" + "reference": "4f5ba70c30c81f2ce03a16a9965832cfcc31ed3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/b6ff9f93603561f50e53b64310495d20b8dff5d8", - "reference": "b6ff9f93603561f50e53b64310495d20b8dff5d8", + "url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/4f5ba70c30c81f2ce03a16a9965832cfcc31ed3b", + "reference": "4f5ba70c30c81f2ce03a16a9965832cfcc31ed3b", "shasum": "" }, "require": { @@ -13133,22 +14088,22 @@ } ], "support": { - "source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.3.1" + "source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.4.1" }, - "time": "2025-01-18T19:26:32+00:00" + "time": "2026-03-05T20:09:01+00:00" }, { "name": "brianium/paratest", - "version": "v7.10.3", + "version": "v7.20.0", "source": { "type": "git", "url": "https://github.com/paratestphp/paratest.git", - "reference": "cfee22cc949d170e61e7111c89ea9fc86aa02ffb" + "reference": "81c80677c9ec0ed4ef16b246167f11dec81a6e3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/cfee22cc949d170e61e7111c89ea9fc86aa02ffb", - "reference": "cfee22cc949d170e61e7111c89ea9fc86aa02ffb", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/81c80677c9ec0ed4ef16b246167f11dec81a6e3d", + "reference": "81c80677c9ec0ed4ef16b246167f11dec81a6e3d", "shasum": "" }, "require": { @@ -13156,28 +14111,27 @@ "ext-pcre": "*", "ext-reflection": "*", "ext-simplexml": "*", - "fidry/cpu-core-counter": "^1.2.0", + "fidry/cpu-core-counter": "^1.3.0", "jean85/pretty-package-versions": "^2.1.1", - "php": "~8.3.0 || ~8.4.0", - "phpunit/php-code-coverage": "^12.3.1", - "phpunit/php-file-iterator": "^6", - "phpunit/php-timer": "^8", - "phpunit/phpunit": "^12.2.3", - "sebastian/environment": "^8.0.2", - "symfony/console": "^6.4.20 || ^7.3.0", - "symfony/process": "^6.4.20 || ^7.3.0" + "php": "~8.3.0 || ~8.4.0 || ~8.5.0", + "phpunit/php-code-coverage": "^12.5.3 || ^13.0.1", + "phpunit/php-file-iterator": "^6.0.1 || ^7", + "phpunit/php-timer": "^8 || ^9", + "phpunit/phpunit": "^12.5.14 || ^13.0.5", + "sebastian/environment": "^8.0.3 || ^9", + "symfony/console": "^7.4.7 || ^8.0.7", + "symfony/process": "^7.4.5 || ^8.0.5" }, "require-dev": { - "doctrine/coding-standard": "^13.0.1", + "doctrine/coding-standard": "^14.0.0", "ext-pcntl": "*", "ext-pcov": "*", "ext-posix": "*", - "phpstan/phpstan": "^2.1.17", - "phpstan/phpstan-deprecation-rules": "^2.0.3", - "phpstan/phpstan-phpunit": "^2.0.6", - "phpstan/phpstan-strict-rules": "^2.0.4", - "squizlabs/php_codesniffer": "^3.13.2", - "symfony/filesystem": "^6.4.13 || ^7.3.0" + "phpstan/phpstan": "^2.1.44", + "phpstan/phpstan-deprecation-rules": "^2.0.4", + "phpstan/phpstan-phpunit": "^2.0.16", + "phpstan/phpstan-strict-rules": "^2.0.10", + "symfony/filesystem": "^7.4.6 || ^8.0.6" }, "bin": [ "bin/paratest", @@ -13217,7 +14171,7 @@ ], "support": { "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v7.10.3" + "source": "https://github.com/paratestphp/paratest/tree/v7.20.0" }, "funding": [ { @@ -13229,7 +14183,7 @@ "type": "paypal" } ], - "time": "2025-06-22T16:27:15+00:00" + "time": "2026-03-29T15:46:14+00:00" }, { "name": "fakerphp/faker", @@ -13296,16 +14250,16 @@ }, { "name": "fidry/cpu-core-counter", - "version": "1.2.0", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "8520451a140d3f46ac33042715115e290cf5785f" + "reference": "db9508f7b1474469d9d3c53b86f817e344732678" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", - "reference": "8520451a140d3f46ac33042715115e290cf5785f", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678", "shasum": "" }, "require": { @@ -13315,10 +14269,10 @@ "fidry/makefile": "^0.2.0", "fidry/php-cs-fixer-config": "^1.1.2", "phpstan/extension-installer": "^1.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", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", "phpunit/phpunit": "^8.5.31 || ^9.5.26", "webmozarts/strict-phpunit": "^7.5" }, @@ -13345,7 +14299,7 @@ ], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" }, "funding": [ { @@ -13353,20 +14307,20 @@ "type": "github" } ], - "time": "2024-08-06T10:04:20+00:00" + "time": "2025-08-14T07:29:31+00:00" }, { "name": "filp/whoops", - "version": "2.18.3", + "version": "2.18.4", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "59a123a3d459c5a23055802237cb317f609867e5" + "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/59a123a3d459c5a23055802237cb317f609867e5", - "reference": "59a123a3d459c5a23055802237cb317f609867e5", + "url": "https://api.github.com/repos/filp/whoops/zipball/d2102955e48b9fd9ab24280a7ad12ed552752c4d", + "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d", "shasum": "" }, "require": { @@ -13416,7 +14370,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.18.3" + "source": "https://github.com/filp/whoops/tree/2.18.4" }, "funding": [ { @@ -13424,26 +14378,27 @@ "type": "github" } ], - "time": "2025-06-16T00:02:10+00:00" + "time": "2025-08-08T12:00:00+00:00" }, { "name": "fumeapp/modeltyper", - "version": "v3.3.0", + "version": "v3.10.0", "source": { "type": "git", "url": "https://github.com/fumeapp/modeltyper.git", - "reference": "03556593e6332b25aaed188b2891ffe9f900fb84" + "reference": "421f809db4c244253002385a93ff7d94e3264244" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fumeapp/modeltyper/zipball/03556593e6332b25aaed188b2891ffe9f900fb84", - "reference": "03556593e6332b25aaed188b2891ffe9f900fb84", + "url": "https://api.github.com/repos/fumeapp/modeltyper/zipball/421f809db4c244253002385a93ff7d94e3264244", + "reference": "421f809db4c244253002385a93ff7d94e3264244", "shasum": "" }, "require": { - "illuminate/console": "^11.33.0|^12.0", - "illuminate/database": "^11.33.0|^12.0", - "illuminate/support": "^11.33.0|^12.0", + "composer/class-map-generator": "^1.6", + "illuminate/console": "^11.33.0|^12.0|^13.0", + "illuminate/database": "^11.33.0|^12.0|^13.0", + "illuminate/support": "^11.33.0|^12.0|^13.0", "php": "^8.2" }, "conflict": { @@ -13454,9 +14409,9 @@ "consolidation/robo": "^5.1.0", "larastan/larastan": "^3.0.2", "laravel/pint": "^1.18.3", - "orchestra/testbench": "^9.6.1|^10.0", + "orchestra/testbench": "^9.6.1|^10.0|^11.0", "phpstan/phpstan-deprecation-rules": "^2.0.1", - "phpunit/phpunit": "^11.4.4", + "phpunit/phpunit": "^11.4.4|^12.5.12", "totten/lurkerlite": "^1.3" }, "type": "library", @@ -13485,9 +14440,9 @@ "description": "Generate TypeScript interfaces from Laravel Models", "support": { "issues": "https://github.com/fumeapp/modeltyper/issues", - "source": "https://github.com/fumeapp/modeltyper/tree/v3.3.0" + "source": "https://github.com/fumeapp/modeltyper/tree/v3.10.0" }, - "time": "2025-06-18T14:16:32+00:00" + "time": "2026-03-27T15:48:22+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -13542,16 +14497,16 @@ }, { "name": "iamcal/sql-parser", - "version": "v0.6", + "version": "v0.7", "source": { "type": "git", "url": "https://github.com/iamcal/SQLParser.git", - "reference": "947083e2dca211a6f12fb1beb67a01e387de9b62" + "reference": "610392f38de49a44dab08dc1659960a29874c4b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/iamcal/SQLParser/zipball/947083e2dca211a6f12fb1beb67a01e387de9b62", - "reference": "947083e2dca211a6f12fb1beb67a01e387de9b62", + "url": "https://api.github.com/repos/iamcal/SQLParser/zipball/610392f38de49a44dab08dc1659960a29874c4b8", + "reference": "610392f38de49a44dab08dc1659960a29874c4b8", "shasum": "" }, "require-dev": { @@ -13577,9 +14532,9 @@ "description": "MySQL schema parser", "support": { "issues": "https://github.com/iamcal/SQLParser/issues", - "source": "https://github.com/iamcal/SQLParser/tree/v0.6" + "source": "https://github.com/iamcal/SQLParser/tree/v0.7" }, - "time": "2025-03-17T16:59:46+00:00" + "time": "2026-01-28T22:20:33+00:00" }, { "name": "jean85/pretty-package-versions", @@ -13643,43 +14598,44 @@ }, { "name": "larastan/larastan", - "version": "v3.5.0", + "version": "v3.9.6", "source": { "type": "git", "url": "https://github.com/larastan/larastan.git", - "reference": "e8ccd73008487ba91da9877b373f8c447743f1ce" + "reference": "9ad17e83e96b63536cb6ac39c3d40d29ff9cf636" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/e8ccd73008487ba91da9877b373f8c447743f1ce", - "reference": "e8ccd73008487ba91da9877b373f8c447743f1ce", + "url": "https://api.github.com/repos/larastan/larastan/zipball/9ad17e83e96b63536cb6ac39c3d40d29ff9cf636", + "reference": "9ad17e83e96b63536cb6ac39c3d40d29ff9cf636", "shasum": "" }, "require": { "ext-json": "*", - "iamcal/sql-parser": "^0.6.0", - "illuminate/console": "^11.44.2 || ^12.4.1", - "illuminate/container": "^11.44.2 || ^12.4.1", - "illuminate/contracts": "^11.44.2 || ^12.4.1", - "illuminate/database": "^11.44.2 || ^12.4.1", - "illuminate/http": "^11.44.2 || ^12.4.1", - "illuminate/pipeline": "^11.44.2 || ^12.4.1", - "illuminate/support": "^11.44.2 || ^12.4.1", + "iamcal/sql-parser": "^0.7.0", + "illuminate/console": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/container": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/contracts": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/database": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/http": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/pipeline": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/support": "^11.44.2 || ^12.4.1 || ^13", "php": "^8.2", - "phpstan/phpstan": "^2.1.11" + "phpstan/phpstan": "^2.1.44" }, "require-dev": { "doctrine/coding-standard": "^13", - "laravel/framework": "^11.44.2 || ^12.7.2", + "laravel/framework": "^11.44.2 || ^12.7.2 || ^13", "mockery/mockery": "^1.6.12", "nikic/php-parser": "^5.4", - "orchestra/canvas": "^v9.2.2 || ^10.0.1", - "orchestra/testbench-core": "^9.12.0 || ^10.1", + "orchestra/canvas": "^v9.2.2 || ^10.0.1 || ^11", + "orchestra/testbench-core": "^9.12.0 || ^10.1 || ^11", "phpstan/phpstan-deprecation-rules": "^2.0.1", - "phpunit/phpunit": "^10.5.35 || ^11.5.15" + "phpunit/phpunit": "^10.5.35 || ^11.5.15 || ^12.5.8" }, "suggest": { - "orchestra/testbench": "Using Larastan for analysing a package needs Testbench" + "orchestra/testbench": "Using Larastan for analysing a package needs Testbench", + "phpmyadmin/sql-parser": "Install to enable Larastan's optional phpMyAdmin-based SQL parser automatically" }, "type": "phpstan-extension", "extra": { @@ -13720,7 +14676,7 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v3.5.0" + "source": "https://github.com/larastan/larastan/tree/v3.9.6" }, "funding": [ { @@ -13728,20 +14684,20 @@ "type": "github" } ], - "time": "2025-06-19T22:41:50+00:00" + "time": "2026-04-16T10:02:43+00:00" }, { "name": "laravel/pint", - "version": "v1.24.0", + "version": "v1.29.1", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a" + "reference": "0770e9b7fafd50d4586881d456d6eb41c9247a80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/0345f3b05f136801af8c339f9d16ef29e6b4df8a", - "reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a", + "url": "https://api.github.com/repos/laravel/pint/zipball/0770e9b7fafd50d4586881d456d6eb41c9247a80", + "reference": "0770e9b7fafd50d4586881d456d6eb41c9247a80", "shasum": "" }, "require": { @@ -13752,22 +14708,20 @@ "php": "^8.2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.82.2", - "illuminate/view": "^11.45.1", - "larastan/larastan": "^3.5.0", - "laravel-zero/framework": "^11.45.0", + "friendsofphp/php-cs-fixer": "^3.95.1", + "illuminate/view": "^12.56.0", + "larastan/larastan": "^3.9.6", + "laravel-zero/framework": "^12.1.0", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^2.3.1", - "pestphp/pest": "^2.36.0" + "nunomaduro/termwind": "^2.4.0", + "pestphp/pest": "^3.8.6", + "shipfastlabs/agent-detector": "^1.1.3" }, "bin": [ "builds/pint" ], "type": "project", "autoload": { - "files": [ - "overrides/Runner/Parallel/ProcessFactory.php" - ], "psr-4": { "App\\": "app/", "Database\\Seeders\\": "database/seeders/", @@ -13787,6 +14741,7 @@ "description": "An opinionated code formatter for PHP.", "homepage": "https://laravel.com", "keywords": [ + "dev", "format", "formatter", "lint", @@ -13797,33 +14752,33 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2025-07-10T18:09:32+00:00" + "time": "2026-04-20T15:26:14+00:00" }, { "name": "laravel/sail", - "version": "v1.43.1", + "version": "v1.60.0", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "3e7d899232a8c5e3ea4fc6dee7525ad583887e72" + "reference": "2a1538ed22eed4210ac1e17904235032571bd89c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/3e7d899232a8c5e3ea4fc6dee7525ad583887e72", - "reference": "3e7d899232a8c5e3ea4fc6dee7525ad583887e72", + "url": "https://api.github.com/repos/laravel/sail/zipball/2a1538ed22eed4210ac1e17904235032571bd89c", + "reference": "2a1538ed22eed4210ac1e17904235032571bd89c", "shasum": "" }, "require": { - "illuminate/console": "^9.52.16|^10.0|^11.0|^12.0", - "illuminate/contracts": "^9.52.16|^10.0|^11.0|^12.0", - "illuminate/support": "^9.52.16|^10.0|^11.0|^12.0", + "illuminate/console": "^9.52.16|^10.0|^11.0|^12.0|^13.0", + "illuminate/contracts": "^9.52.16|^10.0|^11.0|^12.0|^13.0", + "illuminate/support": "^9.52.16|^10.0|^11.0|^12.0|^13.0", "php": "^8.0", - "symfony/console": "^6.0|^7.0", - "symfony/yaml": "^6.0|^7.0" + "symfony/console": "^6.0|^7.0|^8.0", + "symfony/yaml": "^6.0|^7.0|^8.0" }, "require-dev": { - "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", - "phpstan/phpstan": "^1.10" + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0|^11.0", + "phpstan/phpstan": "^2.0" }, "bin": [ "bin/sail" @@ -13860,36 +14815,92 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2025-05-19T13:19:21+00:00" + "time": "2026-05-14T17:29:51+00:00" + }, + { + "name": "laravel/sentinel", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/sentinel.git", + "reference": "972d9885d9d14312a118e9565c4e6ecc5e751ea1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sentinel/zipball/972d9885d9d14312a118e9565c4e6ecc5e751ea1", + "reference": "972d9885d9d14312a118e9565c4e6ecc5e751ea1", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/container": "^8.37|^9.0|^10.0|^11.0|^12.0|^13.0", + "php": "^8.0" + }, + "require-dev": { + "laravel/pint": "^1.27", + "orchestra/testbench": "^6.47.1|^7.56|^8.37|^9.16|^10.9|^11.0", + "phpstan/phpstan": "^2.1.33" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Sentinel\\SentinelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sentinel\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Mior Muhammad Zaki", + "email": "mior@laravel.com" + } + ], + "support": { + "source": "https://github.com/laravel/sentinel/tree/v1.1.0" + }, + "time": "2026-03-24T14:03:38+00:00" }, { "name": "laravel/telescope", - "version": "v5.10.0", + "version": "v5.20.0", "source": { "type": "git", "url": "https://github.com/laravel/telescope.git", - "reference": "fc0a8662682c0375b534033873debb780c003486" + "reference": "38ec6e6006a67e05e0c476c5f8ef3550b72e43d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/telescope/zipball/fc0a8662682c0375b534033873debb780c003486", - "reference": "fc0a8662682c0375b534033873debb780c003486", + "url": "https://api.github.com/repos/laravel/telescope/zipball/38ec6e6006a67e05e0c476c5f8ef3550b72e43d8", + "reference": "38ec6e6006a67e05e0c476c5f8ef3550b72e43d8", "shasum": "" }, "require": { "ext-json": "*", - "laravel/framework": "^8.37|^9.0|^10.0|^11.0|^12.0", + "laravel/framework": "^8.37|^9.0|^10.0|^11.0|^12.0|^13.0", + "laravel/sentinel": "^1.0", "php": "^8.0", - "symfony/console": "^5.3|^6.0|^7.0", - "symfony/var-dumper": "^5.0|^6.0|^7.0" + "symfony/console": "^5.3|^6.0|^7.0|^8.0", + "symfony/var-dumper": "^5.0|^6.0|^7.0|^8.0" }, "require-dev": { "ext-gd": "*", "guzzlehttp/guzzle": "^6.0|^7.0", - "laravel/octane": "^1.4|^2.0|dev-develop", - "orchestra/testbench": "^6.40|^7.37|^8.17|^9.0|^10.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.0|^10.5|^11.5" + "laravel/octane": "^1.4|^2.0", + "orchestra/testbench": "^6.47.1|^7.55|^8.36|^9.15|^10.8|^11.0", + "phpstan/phpstan": "^1.10" }, "type": "library", "extra": { @@ -13927,9 +14938,9 @@ ], "support": { "issues": "https://github.com/laravel/telescope/issues", - "source": "https://github.com/laravel/telescope/tree/v5.10.0" + "source": "https://github.com/laravel/telescope/tree/v5.20.0" }, - "time": "2025-07-07T14:47:19+00:00" + "time": "2026-04-06T12:52:26+00:00" }, { "name": "mockery/mockery", @@ -14016,39 +15027,36 @@ }, { "name": "nunomaduro/collision", - "version": "v8.8.2", + "version": "v8.9.4", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb" + "reference": "716af8f95a470e9094cfca09ed897b023be191a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", - "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/716af8f95a470e9094cfca09ed897b023be191a5", + "reference": "716af8f95a470e9094cfca09ed897b023be191a5", "shasum": "" }, "require": { - "filp/whoops": "^2.18.1", - "nunomaduro/termwind": "^2.3.1", + "filp/whoops": "^2.18.4", + "nunomaduro/termwind": "^2.4.0", "php": "^8.2.0", - "symfony/console": "^7.3.0" + "symfony/console": "^7.4.8 || ^8.0.8" }, "conflict": { - "laravel/framework": "<11.44.2 || >=13.0.0", - "phpunit/phpunit": "<11.5.15 || >=13.0.0" + "laravel/framework": "<11.48.0 || >=14.0.0", + "phpunit/phpunit": "<11.5.50 || >=14.0.0" }, "require-dev": { - "brianium/paratest": "^7.8.3", - "larastan/larastan": "^3.4.2", - "laravel/framework": "^11.44.2 || ^12.18", - "laravel/pint": "^1.22.1", - "laravel/sail": "^1.43.1", - "laravel/sanctum": "^4.1.1", - "laravel/tinker": "^2.10.1", - "orchestra/testbench-core": "^9.12.0 || ^10.4", - "pestphp/pest": "^3.8.2", - "sebastian/environment": "^7.2.1 || ^8.0" + "brianium/paratest": "^7.8.5", + "larastan/larastan": "^3.9.6", + "laravel/framework": "^11.48.0 || ^12.56.0 || ^13.5.0", + "laravel/pint": "^1.29.1", + "orchestra/testbench-core": "^9.12.0 || ^10.12.1 || ^11.2.1", + "pestphp/pest": "^3.8.5 || ^4.4.3 || ^5.0.0", + "sebastian/environment": "^7.2.1 || ^8.0.4 || ^9.3.0" }, "type": "library", "extra": { @@ -14111,7 +15119,7 @@ "type": "patreon" } ], - "time": "2025-06-25T02:12:12+00:00" + "time": "2026-04-21T14:04:20+00:00" }, { "name": "phar-io/manifest", @@ -14233,16 +15241,11 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.17", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053" - }, + "version": "2.1.55", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053", - "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9eaac3826ed5e9b8427350a43cac825eeca3f566", + "reference": "9eaac3826ed5e9b8427350a43cac825eeca3f566", "shasum": "" }, "require": { @@ -14287,20 +15290,20 @@ "type": "github" } ], - "time": "2025-05-21T20:55:28+00:00" + "time": "2026-05-18T11:57:34+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "12.5.3", + "version": "12.5.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "b015312f28dd75b75d3422ca37dff2cd1a565e8d" + "reference": "876099a072646c7745f673d7aeab5382c4439691" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b015312f28dd75b75d3422ca37dff2cd1a565e8d", - "reference": "b015312f28dd75b75d3422ca37dff2cd1a565e8d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/876099a072646c7745f673d7aeab5382c4439691", + "reference": "876099a072646c7745f673d7aeab5382c4439691", "shasum": "" }, "require": { @@ -14309,7 +15312,6 @@ "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", @@ -14356,7 +15358,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.3" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.6" }, "funding": [ { @@ -14376,7 +15378,7 @@ "type": "tidelift" } ], - "time": "2026-02-06T06:01:44+00:00" + "time": "2026-04-15T08:23:17+00:00" }, { "name": "phpunit/php-file-iterator", @@ -14637,16 +15639,16 @@ }, { "name": "phpunit/phpunit", - "version": "12.5.14", + "version": "12.5.26", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "47283cfd98d553edcb1353591f4e255dc1bb61f0" + "reference": "e78c9ad74f73fd3642a23e65ace83746dc8df26d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/47283cfd98d553edcb1353591f4e255dc1bb61f0", - "reference": "47283cfd98d553edcb1353591f4e255dc1bb61f0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e78c9ad74f73fd3642a23e65ace83746dc8df26d", + "reference": "e78c9ad74f73fd3642a23e65ace83746dc8df26d", "shasum": "" }, "require": { @@ -14660,20 +15662,20 @@ "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.3", - "phpunit/php-code-coverage": "^12.5.3", + "phpunit/php-code-coverage": "^12.5.6", "phpunit/php-file-iterator": "^6.0.1", "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.4", + "sebastian/cli-parser": "^4.2.1", + "sebastian/comparator": "^7.1.8", "sebastian/diff": "^7.0.0", - "sebastian/environment": "^8.0.3", - "sebastian/exporter": "^7.0.2", + "sebastian/environment": "^8.1.1", + "sebastian/exporter": "^7.0.3", "sebastian/global-state": "^8.0.2", "sebastian/object-enumerator": "^7.0.0", "sebastian/recursion-context": "^7.0.1", - "sebastian/type": "^6.0.3", + "sebastian/type": "^6.0.4", "sebastian/version": "^6.0.0", "staabm/side-effects-detector": "^1.0.5" }, @@ -14715,51 +15717,35 @@ "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.14" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.26" }, "funding": [ { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "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" + "url": "https://phpunit.de/sponsoring.html", + "type": "other" } ], - "time": "2026-02-18T12:38:40+00:00" + "time": "2026-05-21T12:36:53+00:00" }, { "name": "sebastian/cli-parser", - "version": "4.2.0", + "version": "4.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04" + "reference": "7d05781b13f7dec9043a629a21d086ed74582a15" }, "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/7d05781b13f7dec9043a629a21d086ed74582a15", + "reference": "7d05781b13f7dec9043a629a21d086ed74582a15", "shasum": "" }, "require": { "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^12.5.25" }, "type": "library", "extra": { @@ -14788,7 +15774,7 @@ "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/4.2.1" }, "funding": [ { @@ -14808,20 +15794,20 @@ "type": "tidelift" } ], - "time": "2025-09-14T09:36:45+00:00" + "time": "2026-05-17T05:29:34+00:00" }, { "name": "sebastian/comparator", - "version": "7.1.4", + "version": "7.1.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "6a7de5df2e094f9a80b40a522391a7e6022df5f6" + "reference": "7c65c1e79836812819705b473a90c12399542485" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a7de5df2e094f9a80b40a522391a7e6022df5f6", - "reference": "6a7de5df2e094f9a80b40a522391a7e6022df5f6", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/7c65c1e79836812819705b473a90c12399542485", + "reference": "7c65c1e79836812819705b473a90c12399542485", "shasum": "" }, "require": { @@ -14829,10 +15815,10 @@ "ext-mbstring": "*", "php": ">=8.3", "sebastian/diff": "^7.0", - "sebastian/exporter": "^7.0" + "sebastian/exporter": "^7.0.3" }, "require-dev": { - "phpunit/phpunit": "^12.2" + "phpunit/phpunit": "^12.5.25" }, "suggest": { "ext-bcmath": "For comparing BcMath\\Number objects" @@ -14880,7 +15866,7 @@ "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.4" + "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.8" }, "funding": [ { @@ -14900,7 +15886,7 @@ "type": "tidelift" } ], - "time": "2026-01-24T09:28:48+00:00" + "time": "2026-05-21T04:45:25+00:00" }, { "name": "sebastian/complexity", @@ -15029,23 +16015,23 @@ }, { "name": "sebastian/environment", - "version": "8.0.3", + "version": "8.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68" + "reference": "334bc42a97ec6fc44c59001dc3467e0d739a20e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/24a711b5c916efc6d6e62aa65aa2ec98fef77f68", - "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/334bc42a97ec6fc44c59001dc3467e0d739a20e9", + "reference": "334bc42a97ec6fc44c59001dc3467e0d739a20e9", "shasum": "" }, "require": { "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^12.5.25" }, "suggest": { "ext-posix": "*" @@ -15053,7 +16039,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "8.0-dev" + "dev-main": "8.1-dev" } }, "autoload": { @@ -15081,7 +16067,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/8.1.1" }, "funding": [ { @@ -15101,29 +16087,29 @@ "type": "tidelift" } ], - "time": "2025-08-12T14:11:56+00:00" + "time": "2026-05-21T08:45:32+00:00" }, { "name": "sebastian/exporter", - "version": "7.0.2", + "version": "7.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "016951ae10980765e4e7aee491eb288c64e505b7" + "reference": "c5e21b5de653ce0a769fb36f5cdfcb5e7a32cf23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/016951ae10980765e4e7aee491eb288c64e505b7", - "reference": "016951ae10980765e4e7aee491eb288c64e505b7", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c5e21b5de653ce0a769fb36f5cdfcb5e7a32cf23", + "reference": "c5e21b5de653ce0a769fb36f5cdfcb5e7a32cf23", "shasum": "" }, "require": { "ext-mbstring": "*", "php": ">=8.3", - "sebastian/recursion-context": "^7.0" + "sebastian/recursion-context": "^7.0.1" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^12.5.25" }, "type": "library", "extra": { @@ -15171,7 +16157,7 @@ "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/7.0.3" }, "funding": [ { @@ -15191,7 +16177,7 @@ "type": "tidelift" } ], - "time": "2025-09-24T06:16:11+00:00" + "time": "2026-05-20T04:37:17+00:00" }, { "name": "sebastian/global-state", @@ -15269,24 +16255,24 @@ }, { "name": "sebastian/lines-of-code", - "version": "4.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f" + "reference": "d543b8ef219dcd8da262cbb958639a96bedba10e" }, "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/d543b8ef219dcd8da262cbb958639a96bedba10e", + "reference": "d543b8ef219dcd8da262cbb958639a96bedba10e", "shasum": "" }, "require": { - "nikic/php-parser": "^5.0", + "nikic/php-parser": "^5.7.0", "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^12.5.25" }, "type": "library", "extra": { @@ -15315,15 +16301,27 @@ "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/4.0.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/lines-of-code", + "type": "tidelift" } ], - "time": "2025-02-07T04:57:28+00:00" + "time": "2026-05-19T16:22:07+00:00" }, { "name": "sebastian/object-enumerator", @@ -15517,23 +16515,23 @@ }, { "name": "sebastian/type", - "version": "6.0.3", + "version": "6.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d" + "reference": "82ff822c2edc46724be9f7411d3163021f602773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/e549163b9760b8f71f191651d22acf32d56d6d4d", - "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/82ff822c2edc46724be9f7411d3163021f602773", + "reference": "82ff822c2edc46724be9f7411d3163021f602773", "shasum": "" }, "require": { "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^12.5.25" }, "type": "library", "extra": { @@ -15562,7 +16560,7 @@ "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/6.0.4" }, "funding": [ { @@ -15582,7 +16580,7 @@ "type": "tidelift" } ], - "time": "2025-08-09T06:57:12+00:00" + "time": "2026-05-20T06:45:45+00:00" }, { "name": "sebastian/version", @@ -15640,16 +16638,16 @@ }, { "name": "spatie/backtrace", - "version": "1.7.4", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "cd37a49fce7137359ac30ecc44ef3e16404cccbe" + "reference": "8ffe78be5ed355b5009e3dd989d183433e9a5adc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/cd37a49fce7137359ac30ecc44ef3e16404cccbe", - "reference": "cd37a49fce7137359ac30ecc44ef3e16404cccbe", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/8ffe78be5ed355b5009e3dd989d183433e9a5adc", + "reference": "8ffe78be5ed355b5009e3dd989d183433e9a5adc", "shasum": "" }, "require": { @@ -15660,7 +16658,7 @@ "laravel/serializable-closure": "^1.3 || ^2.0", "phpunit/phpunit": "^9.3 || ^11.4.3", "spatie/phpunit-snapshot-assertions": "^4.2 || ^5.1.6", - "symfony/var-dumper": "^5.1 || ^6.0 || ^7.0" + "symfony/var-dumper": "^5.1|^6.0|^7.0|^8.0" }, "type": "library", "autoload": { @@ -15687,7 +16685,8 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/backtrace/tree/1.7.4" + "issues": "https://github.com/spatie/backtrace/issues", + "source": "https://github.com/spatie/backtrace/tree/1.8.2" }, "funding": [ { @@ -15699,7 +16698,7 @@ "type": "other" } ], - "time": "2025-05-08T15:41:09+00:00" + "time": "2026-03-11T13:48:28+00:00" }, { "name": "spatie/error-solutions", @@ -15777,26 +16776,26 @@ }, { "name": "spatie/flare-client-php", - "version": "1.10.1", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/spatie/flare-client-php.git", - "reference": "bf1716eb98bd689451b071548ae9e70738dce62f" + "reference": "53f41b08a27cc039e1a8ed2be9a202e924f31bad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/bf1716eb98bd689451b071548ae9e70738dce62f", - "reference": "bf1716eb98bd689451b071548ae9e70738dce62f", + "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/53f41b08a27cc039e1a8ed2be9a202e924f31bad", + "reference": "53f41b08a27cc039e1a8ed2be9a202e924f31bad", "shasum": "" }, "require": { - "illuminate/pipeline": "^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/pipeline": "^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", "php": "^8.0", "spatie/backtrace": "^1.6.1", - "symfony/http-foundation": "^5.2|^6.0|^7.0", - "symfony/mime": "^5.2|^6.0|^7.0", - "symfony/process": "^5.2|^6.0|^7.0", - "symfony/var-dumper": "^5.2|^6.0|^7.0" + "symfony/http-foundation": "^5.2|^6.0|^7.0|^8.0", + "symfony/mime": "^5.2|^6.0|^7.0|^8.0", + "symfony/process": "^5.2|^6.0|^7.0|^8.0", + "symfony/var-dumper": "^5.2|^6.0|^7.0|^8.0" }, "require-dev": { "dms/phpunit-arraysubset-asserts": "^0.5.0", @@ -15834,7 +16833,7 @@ ], "support": { "issues": "https://github.com/spatie/flare-client-php/issues", - "source": "https://github.com/spatie/flare-client-php/tree/1.10.1" + "source": "https://github.com/spatie/flare-client-php/tree/1.11.1" }, "funding": [ { @@ -15842,41 +16841,44 @@ "type": "github" } ], - "time": "2025-02-14T13:42:06+00:00" + "time": "2026-05-15T09:31:32+00:00" }, { "name": "spatie/ignition", - "version": "1.15.1", + "version": "1.16.0", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "31f314153020aee5af3537e507fef892ffbf8c85" + "reference": "b59385bb7aa24dae81bcc15850ebecfda7b40838" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/31f314153020aee5af3537e507fef892ffbf8c85", - "reference": "31f314153020aee5af3537e507fef892ffbf8c85", + "url": "https://api.github.com/repos/spatie/ignition/zipball/b59385bb7aa24dae81bcc15850ebecfda7b40838", + "reference": "b59385bb7aa24dae81bcc15850ebecfda7b40838", "shasum": "" }, "require": { "ext-json": "*", "ext-mbstring": "*", "php": "^8.0", - "spatie/error-solutions": "^1.0", - "spatie/flare-client-php": "^1.7", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "spatie/backtrace": "^1.7.1", + "spatie/error-solutions": "^1.1.2", + "spatie/flare-client-php": "^1.9", + "symfony/console": "^5.4.42|^6.0|^7.0|^8.0", + "symfony/http-foundation": "^5.4.42|^6.0|^7.0|^8.0", + "symfony/mime": "^5.4.42|^6.0|^7.0|^8.0", + "symfony/var-dumper": "^5.4.42|^6.0|^7.0|^8.0" }, "require-dev": { - "illuminate/cache": "^9.52|^10.0|^11.0|^12.0", + "illuminate/cache": "^9.52|^10.0|^11.0|^12.0|^13.0", "mockery/mockery": "^1.4", - "pestphp/pest": "^1.20|^2.0", + "pestphp/pest": "^1.20|^2.0|^3.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", "psr/simple-cache-implementation": "*", - "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", + "symfony/cache": "^5.4.38|^6.0|^7.0|^8.0", + "symfony/process": "^5.4.35|^6.0|^7.0|^8.0", "vlucas/phpdotenv": "^5.5" }, "suggest": { @@ -15925,42 +16927,43 @@ "type": "github" } ], - "time": "2025-02-21T14:31:39+00:00" + "time": "2026-03-17T10:51:08+00:00" }, { "name": "spatie/laravel-ignition", - "version": "2.9.1", + "version": "2.12.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "1baee07216d6748ebd3a65ba97381b051838707a" + "reference": "45b3b6e1e73fc161cba2149972698644b99594ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/1baee07216d6748ebd3a65ba97381b051838707a", - "reference": "1baee07216d6748ebd3a65ba97381b051838707a", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/45b3b6e1e73fc161cba2149972698644b99594ee", + "reference": "45b3b6e1e73fc161cba2149972698644b99594ee", "shasum": "" }, "require": { "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "illuminate/support": "^10.0|^11.0|^12.0", - "php": "^8.1", - "spatie/ignition": "^1.15", - "symfony/console": "^6.2.3|^7.0", - "symfony/var-dumper": "^6.2.3|^7.0" + "illuminate/support": "^11.0|^12.0|^13.0", + "nesbot/carbon": "^2.72|^3.0", + "php": "^8.2", + "spatie/ignition": "^1.16", + "symfony/console": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "require-dev": { - "livewire/livewire": "^2.11|^3.3.5", - "mockery/mockery": "^1.5.1", - "openai-php/client": "^0.8.1|^0.10", - "orchestra/testbench": "8.22.3|^9.0|^10.0", - "pestphp/pest": "^2.34|^3.7", - "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan-deprecation-rules": "^1.1.1|^2.0", - "phpstan/phpstan-phpunit": "^1.3.16|^2.0", - "vlucas/phpdotenv": "^5.5" + "livewire/livewire": "^3.7.0|^4.0|dev-josh/v3-laravel-13-support", + "mockery/mockery": "^1.6.12", + "openai-php/client": "^0.10.3|^0.19", + "orchestra/testbench": "^v9.16.0|^10.6|^11.0", + "pestphp/pest": "^3.7|^4.0", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpstan/phpstan-phpunit": "^2.0.8", + "vlucas/phpdotenv": "^5.6.2" }, "suggest": { "openai-php/client": "Require get solutions from OpenAI", @@ -16016,7 +17019,7 @@ "type": "github" } ], - "time": "2025-02-20T13:13:55+00:00" + "time": "2026-03-17T12:20:04+00:00" }, { "name": "staabm/side-effects-detector", @@ -16072,28 +17075,28 @@ }, { "name": "symfony/yaml", - "version": "v7.3.1", + "version": "v7.4.12", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "0c3555045a46ab3cd4cc5a69d161225195230edb" + "reference": "8b6952b56ca6417f25f7a65758cadd0ce02edc51" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/0c3555045a46ab3cd4cc5a69d161225195230edb", - "reference": "0c3555045a46ab3cd4cc5a69d161225195230edb", + "url": "https://api.github.com/repos/symfony/yaml/zipball/8b6952b56ca6417f25f7a65758cadd0ce02edc51", + "reference": "8b6952b56ca6417f25f7a65758cadd0ce02edc51", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8" }, "conflict": { "symfony/console": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -16124,7 +17127,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.3.1" + "source": "https://github.com/symfony/yaml/tree/v7.4.12" }, "funding": [ { @@ -16135,12 +17138,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-03T06:57:57+00:00" + "time": "2026-05-20T07:20:23+00:00" }, { "name": "theseer/tokenizer", @@ -16194,31 +17201,31 @@ }, { "name": "timacdonald/log-fake", - "version": "v2.4.0", + "version": "v2.4.2", "source": { "type": "git", "url": "https://github.com/timacdonald/log-fake.git", - "reference": "6e052e5b32fe3d1854dafcacd4435c5b83b9721e" + "reference": "c2caae39dbc18d27fc4b8833412dd9eeab32f940" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/timacdonald/log-fake/zipball/6e052e5b32fe3d1854dafcacd4435c5b83b9721e", - "reference": "6e052e5b32fe3d1854dafcacd4435c5b83b9721e", + "url": "https://api.github.com/repos/timacdonald/log-fake/zipball/c2caae39dbc18d27fc4b8833412dd9eeab32f940", + "reference": "c2caae39dbc18d27fc4b8833412dd9eeab32f940", "shasum": "" }, "require": { - "illuminate/collections": "^11.0 || ^12.0", - "illuminate/contracts": "^11.0 || ^12.0", - "illuminate/log": "^11.0 || ^12.0", - "illuminate/support": "^11.0 || ^12.0", + "illuminate/collections": "^11.0 || ^12.0 || ^13.0", + "illuminate/contracts": "^11.0 || ^12.0 || ^13.0", + "illuminate/log": "^11.0 || ^12.0 || ^13.0", + "illuminate/support": "^11.0 || ^12.0 || ^13.0", "php": "^8.2", - "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0 || ^13.0", "psr/log": "^1.0 || ^2.0 || ^3.0", "symfony/var-dumper": "^7.0" }, "require-dev": { - "illuminate/config": "^11.0 || ^12.0", - "illuminate/container": "^11.0 || ^12.0", + "illuminate/config": "^11.0 || ^12.0 || ^13.0", + "illuminate/container": "^11.0 || ^12.0 || ^13.0", "timacdonald/callable-fake": "^1.0" }, "type": "library", @@ -16248,9 +17255,9 @@ ], "support": { "issues": "https://github.com/timacdonald/log-fake/issues", - "source": "https://github.com/timacdonald/log-fake/tree/v2.4.0" + "source": "https://github.com/timacdonald/log-fake/tree/v2.4.2" }, - "time": "2025-03-10T23:38:55+00:00" + "time": "2026-03-19T22:05:27+00:00" } ], "aliases": [], diff --git a/config/app.php b/config/app.php index a15c3759f..b6acb40df 100644 --- a/config/app.php +++ b/config/app.php @@ -7,6 +7,12 @@ use App\Enums\IntervalFormat; use App\Enums\NumberFormat; use App\Enums\TimeFormat; +use App\Providers\AppServiceProvider; +use App\Providers\AuthServiceProvider; +use App\Providers\EventServiceProvider; +use App\Providers\Filament\AdminPanelProvider; +use App\Providers\FortifyServiceProvider; +use App\Providers\RouteServiceProvider; use Illuminate\Support\Facades\Facade; use Illuminate\Support\ServiceProvider; use Nwidart\Modules\LaravelModulesServiceProvider; @@ -190,13 +196,12 @@ /* * Application Service Providers... */ - App\Providers\AppServiceProvider::class, - App\Providers\AuthServiceProvider::class, - App\Providers\EventServiceProvider::class, - App\Providers\Filament\AdminPanelProvider::class, - App\Providers\RouteServiceProvider::class, - App\Providers\FortifyServiceProvider::class, - App\Providers\JetstreamServiceProvider::class, + AppServiceProvider::class, + AuthServiceProvider::class, + EventServiceProvider::class, + AdminPanelProvider::class, + RouteServiceProvider::class, + FortifyServiceProvider::class, // Warning: Do not add TelescopeServiceProvider here since it is already conditionally registered in AppServiceProvider LaravelModulesServiceProvider::class, ])->toArray(), diff --git a/config/audit.php b/config/audit.php index 518aa43a2..81fc80764 100644 --- a/config/audit.php +++ b/config/audit.php @@ -1,6 +1,11 @@ OwenIt\Auditing\Models\Audit::class, + 'implementation' => Audit::class, /* |-------------------------------------------------------------------------- @@ -32,7 +37,7 @@ 'web', 'api', ], - 'resolver' => OwenIt\Auditing\Resolvers\UserResolver::class, + 'resolver' => UserResolver::class, ], /* @@ -44,9 +49,9 @@ | */ 'resolvers' => [ - 'ip_address' => App\Extensions\Auditing\Resolvers\CustomIpAddressResolver::class, - 'user_agent' => OwenIt\Auditing\Resolvers\UserAgentResolver::class, - 'url' => OwenIt\Auditing\Resolvers\UrlResolver::class, + 'ip_address' => CustomIpAddressResolver::class, + 'user_agent' => UserAgentResolver::class, + 'url' => UrlResolver::class, ], /* diff --git a/config/auth.php b/config/auth.php index 8143c2eeb..5127b7417 100644 --- a/config/auth.php +++ b/config/auth.php @@ -1,6 +1,7 @@ [ 'users' => [ 'driver' => 'eloquent', - 'model' => App\Models\User::class, + 'model' => User::class, ], ], diff --git a/config/excel.php b/config/excel.php index 02dc56f54..dfde7d06d 100644 --- a/config/excel.php +++ b/config/excel.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use Maatwebsite\Excel\DefaultValueBinder; use Maatwebsite\Excel\Excel; use PhpOffice\PhpSpreadsheet\Reader\Csv; @@ -226,7 +227,7 @@ | */ 'value_binder' => [ - 'default' => Maatwebsite\Excel\DefaultValueBinder::class, + 'default' => DefaultValueBinder::class, ], 'cache' => [ diff --git a/config/jetstream.php b/config/jetstream.php deleted file mode 100644 index 755a1e679..000000000 --- a/config/jetstream.php +++ /dev/null @@ -1,82 +0,0 @@ - 'inertia', - - /* - |-------------------------------------------------------------------------- - | Jetstream Route Middleware - |-------------------------------------------------------------------------- - | - | Here you may specify which middleware Jetstream will assign to the routes - | that it registers with the application. When necessary, you may modify - | these middleware; however, this default value is usually sufficient. - | - */ - - 'middleware' => ['web'], - - 'auth_session' => AuthenticateSession::class, - - /* - |-------------------------------------------------------------------------- - | Jetstream Guard - |-------------------------------------------------------------------------- - | - | Here you may specify the authentication guard Jetstream will use while - | authenticating users. This value should correspond with one of your - | guards that is already present in your "auth" configuration file. - | - */ - - 'guard' => 'web', - - /* - |-------------------------------------------------------------------------- - | Features - |-------------------------------------------------------------------------- - | - | Some of Jetstream's 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' => [ - Features::termsAndPrivacyPolicy(), - Features::profilePhotos(), - Features::teams(['invitations' => true]), - Features::accountDeletion(), - ], - - /* - |-------------------------------------------------------------------------- - | Profile Photo Disk - |-------------------------------------------------------------------------- - | - | This configuration value determines the default disk that will be used - | when storing profile photos for your application's users. Typically - | this will be the "public" disk but you may adjust this if needed. - | - */ - - 'profile_photo_disk' => env('PROFILE_PHOTO_DISK', env('PUBLIC_FILESYSTEM_DISK', 'public')), - -]; diff --git a/database/factories/OrganizationInvitationFactory.php b/database/factories/OrganizationInvitationFactory.php index a4b2377f0..90896fe40 100644 --- a/database/factories/OrganizationInvitationFactory.php +++ b/database/factories/OrganizationInvitationFactory.php @@ -25,9 +25,24 @@ public function definition(): array 'email' => $this->faker->unique()->safeEmail(), 'role' => Role::Employee->value, 'organization_id' => Organization::factory(), + 'accepted_at' => null, ]; } + public function role(Role $role): self + { + return $this->state(fn (array $attributes) => [ + 'role' => $role->value, + ]); + } + + public function accepted(): self + { + return $this->state(fn (array $attributes): array => [ + 'accepted_at' => $this->faker->dateTime(), + ]); + } + public function forOrganization(Organization $organization): self { return $this->state(fn (array $attributes) => [ diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index a3e0a598f..15b3393e8 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -9,6 +9,7 @@ use App\Models\Organization; use App\Models\User; use Illuminate\Database\Eloquent\Factories\Factory; +use Illuminate\Http\FileHelpers; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; @@ -27,6 +28,7 @@ public function definition(): array return [ 'name' => $this->faker->name(), 'email' => $this->faker->unique()->safeEmail(), + 'pending_email' => null, 'email_verified_at' => now(), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 'two_factor_secret' => null, @@ -90,9 +92,9 @@ public function attachToOrganization(Organization $organization, array $pivot = public function withProfilePicture(): static { $profilePhoto = $this->faker->image(null, 500, 500); - /** @see \Illuminate\Http\FileHelpers::hashName */ + /** @see FileHelpers::hashName */ $path = 'profile-photos/'.Str::random(40).'.png'; - Storage::disk(config('jetstream.profile_photo_disk', 'public'))->put($path, $profilePhoto); + Storage::disk(config('filesystems.public'))->put($path, $profilePhoto); return $this->state(function (array $attributes) use ($path): array { return [ @@ -118,7 +120,7 @@ public function withPersonalOrganization(?callable $callback = null): static $organization->owner()->associate($user); $organization->users()->attach($user, ['role' => Role::Owner->value]); - $user->currentTeam()->associate($organization); + $user->currentOrganization()->associate($organization); $user->save(); }); } diff --git a/database/migrations/2026_02_11_143746_add_accepted_at_to_organization_invitations_table.php b/database/migrations/2026_02_11_143746_add_accepted_at_to_organization_invitations_table.php new file mode 100644 index 000000000..7f0f41557 --- /dev/null +++ b/database/migrations/2026_02_11_143746_add_accepted_at_to_organization_invitations_table.php @@ -0,0 +1,30 @@ +timestamp('accepted_at')->nullable()->after('email'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('organization_invitations', function (Blueprint $table): void { + $table->dropColumn('accepted_at'); + }); + } +}; diff --git a/database/migrations/2026_05_21_000001_add_pending_email_to_users_table.php b/database/migrations/2026_05_21_000001_add_pending_email_to_users_table.php new file mode 100644 index 000000000..d43366666 --- /dev/null +++ b/database/migrations/2026_05_21_000001_add_pending_email_to_users_table.php @@ -0,0 +1,30 @@ +string('pending_email')->nullable()->after('email'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table): void { + $table->dropColumn('pending_email'); + }); + } +}; diff --git a/database/migrations/2026_05_21_000002_lowercase_user_emails.php b/database/migrations/2026_05_21_000002_lowercase_user_emails.php new file mode 100644 index 000000000..fdfc39689 --- /dev/null +++ b/database/migrations/2026_05_21_000002_lowercase_user_emails.php @@ -0,0 +1,64 @@ +selectRaw('LOWER(email) as normalized_email') + ->selectRaw('COUNT(*) as user_count') + ->selectRaw("STRING_AGG(id::text || ' <' || email || '>', ', ' ORDER BY email) as users") + ->where('is_placeholder', false) + ->groupByRaw('LOWER(email)') + ->havingRaw('COUNT(*) > 1') + ->orderBy('normalized_email') + ->get(); + + if ($duplicateEmails->isNotEmpty()) { + $duplicateEmailMessage = $duplicateEmails + ->take(20) + ->map(fn (stdClass $duplicateEmail): string => sprintf( + '%s (%d users: %s)', + $duplicateEmail->normalized_email, + $duplicateEmail->user_count, + $duplicateEmail->users, + )) + ->implode('; '); + + $remainingDuplicateCount = $duplicateEmails->count() - 20; + $remainingDuplicateMessage = $remainingDuplicateCount > 0 + ? sprintf('; and %d more duplicate normalized emails', $remainingDuplicateCount) + : ''; + + throw new RuntimeException( + 'Cannot lowercase users.email because doing so would create duplicate non-placeholder user emails and violate the unique index on users.email for non-placeholder users. Resolve these case-insensitive duplicates first: '. + $duplicateEmailMessage. + $remainingDuplicateMessage + ); + } + + DB::table('users') + ->whereRaw('email <> LOWER(email)') + ->update([ + 'email' => DB::raw('LOWER(email)'), + ]); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // + } +}; diff --git a/e2e/calendar.spec.ts b/e2e/calendar.spec.ts index 68c618141..ad063a8c8 100644 --- a/e2e/calendar.spec.ts +++ b/e2e/calendar.spec.ts @@ -12,7 +12,7 @@ import { createRunningTimeEntryWithStartViaApi, createTaskViaApi, createProjectWithClientViaApi, - updateUserProfileViaWeb, + updateUserProfileViaApi, updateOrganizationSettingViaApi, } from './utils/api'; @@ -1803,28 +1803,22 @@ test.describe('Click-Drag Selection to Create', () => { // ============================================= test.describe('Timezone & Localization', () => { - test('week start day: monday shows Mon as first column', async ({ page }) => { - // Navigate to calendar first to load Inertia page props + test('week start day: monday shows Mon as first column', async ({ page, ctx }) => { + await updateUserProfileViaApi(ctx, { week_start: 'monday' }); await goToCalendar(page); - await updateUserProfileViaWeb(page, { week_start: 'monday' }); - await page.reload(); await expect(page.locator('.fc')).toBeVisible(); const firstHeader = page.locator('.fc-col-header-cell').first(); await expect(firstHeader).toContainText('Mon'); }); - test('week start day: sunday shows Sun as first column', async ({ page }) => { + test('week start day: sunday shows Sun as first column', async ({ page, ctx }) => { + await updateUserProfileViaApi(ctx, { week_start: 'sunday' }); await goToCalendar(page); - await updateUserProfileViaWeb(page, { week_start: 'sunday' }); - await page.reload(); await expect(page.locator('.fc')).toBeVisible(); const firstHeader = page.locator('.fc-col-header-cell').first(); await expect(firstHeader).toContainText('Sun'); - - // Reset to monday for other tests - await updateUserProfileViaWeb(page, { week_start: 'monday' }); }); test('12-hour time format shows AM/PM on slot labels', async ({ page, ctx }) => { diff --git a/e2e/command-palette.spec.ts b/e2e/command-palette.spec.ts index 535a49004..85f5ec3fd 100644 --- a/e2e/command-palette.spec.ts +++ b/e2e/command-palette.spec.ts @@ -348,7 +348,7 @@ test.describe('Command Palette', () => { const newOrgName = 'TestOrg' + Math.floor(Math.random() * 10000); // Create a new organization - await page.goto(PLAYWRIGHT_BASE_URL + '/teams/create'); + await page.goto(PLAYWRIGHT_BASE_URL + '/organizations/create'); await page.getByLabel('Organization Name').fill(newOrgName); await page.getByRole('button', { name: 'Create' }).click(); @@ -393,7 +393,7 @@ test.describe('Command Palette', () => { const newOrgName = 'GroupTestOrg' + Math.floor(Math.random() * 10000); // Create a new organization to ensure we have multiple - await page.goto(PLAYWRIGHT_BASE_URL + '/teams/create'); + await page.goto(PLAYWRIGHT_BASE_URL + '/organizations/create'); await page.getByLabel('Organization Name').fill(newOrgName); await page.getByRole('button', { name: 'Create' }).click(); await expect(page.getByTestId('dashboard_view')).toBeVisible({ timeout: 10000 }); diff --git a/e2e/invitation-accept.spec.ts b/e2e/invitation-accept.spec.ts new file mode 100644 index 000000000..d5c592946 --- /dev/null +++ b/e2e/invitation-accept.spec.ts @@ -0,0 +1,158 @@ +import { expect, test } from '../playwright/fixtures'; +import { PLAYWRIGHT_BASE_URL, TEST_USER_PASSWORD } from '../playwright/config'; +import { getInvitationAcceptUrl } from './utils/mailpit'; +import { registerUser } from './utils/members'; + +// Invitation acceptance flows touch mail delivery + redirects. +test.describe.configure({ timeout: 45000 }); + +test.describe('invitation accept banners', () => { + test('shows success banner on dashboard when a logged-in registered user accepts an invitation', async ({ + page, + browser, + }) => { + const memberId = Math.floor(Math.random() * 100000); + const memberEmail = `success+${memberId}@invite-banner.test`; + + // Invitee already has an account and is logged in. + const invitee = await registerUser(browser, 'Banner Success', memberEmail); + + // Owner sends the invitation. + await page.goto(PLAYWRIGHT_BASE_URL + '/members'); + await page.getByRole('button', { name: 'Invite Member' }).click(); + await expect(page.getByPlaceholder('Member Email')).toBeVisible(); + await page.getByLabel('Email').fill(memberEmail); + await page.getByRole('button', { name: 'Employee' }).click(); + await Promise.all([ + page.waitForResponse( + (response) => + response.url().includes('/invitations') && + response.request().method() === 'POST' && + response.status() === 204 + ), + page.getByRole('button', { name: 'Invite Member', exact: true }).click(), + ]); + + // Invitee clicks the email link. + const acceptUrl = await getInvitationAcceptUrl(invitee.page.request, memberEmail); + await invitee.page.goto(acceptUrl); + await invitee.page.waitForURL(/\/dashboard$/); + + const banner = invitee.page.getByTestId('banner'); + await expect(banner).toBeVisible(); + await expect(banner).toContainText( + /Great! You have accepted the invitation to join the .* organization\./ + ); + + await invitee.close(); + }); + + test('shows info banner on login screen when a registered-but-logged-out invitee clicks the accept link', async ({ + page, + browser, + }) => { + const memberId = Math.floor(Math.random() * 100000); + const memberEmail = `loggedout+${memberId}@invite-banner.test`; + + // Invitee has an account, but the context that clicks the link has no session. + const invitee = await registerUser(browser, 'Banner Loggedout', memberEmail); + await invitee.close(); + + // Owner sends the invitation. + await page.goto(PLAYWRIGHT_BASE_URL + '/members'); + await page.getByRole('button', { name: 'Invite Member' }).click(); + await expect(page.getByPlaceholder('Member Email')).toBeVisible(); + await page.getByLabel('Email').fill(memberEmail); + await page.getByRole('button', { name: 'Employee' }).click(); + await Promise.all([ + page.waitForResponse( + (response) => + response.url().includes('/invitations') && + response.request().method() === 'POST' && + response.status() === 204 + ), + page.getByRole('button', { name: 'Invite Member', exact: true }).click(), + ]); + + // Open the accept link in a fresh browser context (no session). + const context = await browser.newContext(); + const inviteePage = await context.newPage(); + const acceptUrl = await getInvitationAcceptUrl(inviteePage.request, memberEmail); + await inviteePage.goto(acceptUrl); + await inviteePage.waitForURL(/\/login$/); + + const banner = inviteePage.getByTestId('banner'); + await expect(banner).toBeVisible(); + await expect(banner).toContainText( + /Great! You have accepted the invitation to join the .* organization\. Please log in to access it\./ + ); + + // Logging in lands the invitee on the dashboard — they were already added silently + // by the accept controller, so the inviter's members list shows them. + await inviteePage.getByLabel('Email').fill(memberEmail); + await inviteePage.getByLabel('Password', { exact: true }).fill(TEST_USER_PASSWORD); + await inviteePage.getByRole('button', { name: 'Log in' }).click(); + await inviteePage.waitForURL(/\/dashboard/); + + await page.goto(PLAYWRIGHT_BASE_URL + '/members'); + const memberRow = page.getByRole('row').filter({ hasText: 'Banner Loggedout' }); + await expect(memberRow).toBeVisible(); + await expect(memberRow.getByText('Employee', { exact: true })).toBeVisible(); + + await context.close(); + }); + + test('shows info banner on register screen when an unregistered email accepts an invitation, then auto-joins on registration', async ({ + page, + browser, + }) => { + const memberId = Math.floor(Math.random() * 100000); + const memberEmail = `info+${memberId}@invite-banner.test`; + + // Owner invites an email that has no account yet. + await page.goto(PLAYWRIGHT_BASE_URL + '/members'); + await page.getByRole('button', { name: 'Invite Member' }).click(); + await expect(page.getByPlaceholder('Member Email')).toBeVisible(); + await page.getByLabel('Email').fill(memberEmail); + await page.getByRole('button', { name: 'Employee' }).click(); + await Promise.all([ + page.waitForResponse( + (response) => + response.url().includes('/invitations') && + response.request().method() === 'POST' && + response.status() === 204 + ), + page.getByRole('button', { name: 'Invite Member', exact: true }).click(), + ]); + + // Open the accept link in a fresh browser context (no session). + const context = await browser.newContext(); + const inviteePage = await context.newPage(); + const acceptUrl = await getInvitationAcceptUrl(inviteePage.request, memberEmail); + await inviteePage.goto(acceptUrl); + await inviteePage.waitForURL(/\/register$/); + + const banner = inviteePage.getByTestId('banner'); + await expect(banner).toBeVisible(); + await expect(banner).toContainText( + /Please create an account to finish joining the .* organization\./ + ); + + // Complete registration — the invitee should auto-join the inviter's org + // (no fresh personal organization is created on top). + await inviteePage.getByLabel('Name').fill('Banner Info'); + await inviteePage.getByLabel('Email').fill(memberEmail); + await inviteePage.getByLabel('Password', { exact: true }).fill(TEST_USER_PASSWORD); + await inviteePage.getByLabel('Confirm Password').fill(TEST_USER_PASSWORD); + await inviteePage.getByLabel('I agree to the Terms of').click(); + await inviteePage.getByRole('button', { name: 'Register' }).click(); + await inviteePage.waitForURL(/\/dashboard/); + + await page.goto(PLAYWRIGHT_BASE_URL + '/members'); + const memberRow = page.getByRole('row').filter({ hasText: 'Banner Info' }); + await expect(memberRow).toBeVisible(); + await expect(memberRow.getByText('Employee', { exact: true })).toBeVisible(); + + await context.close(); + }); +}); diff --git a/e2e/organization.spec.ts b/e2e/organization.spec.ts index 6df3ba345..d1b6f367b 100644 --- a/e2e/organization.spec.ts +++ b/e2e/organization.spec.ts @@ -36,13 +36,52 @@ async function createTimeEntry(page, duration: string) { test('test that organization name can be updated', async ({ page }) => { await goToOrganizationSettings(page); await page.getByLabel('Organization Name').fill('NEW ORG NAME'); - await page.getByLabel('Organization Name').press('Enter'); - await page.getByLabel('Organization Name').press('Meta+r'); + await Promise.all([ + page.waitForResponse( + (response) => + response.url().includes('/api/v1/organizations/') && + response.request().method() === 'PUT' && + response.status() === 200 + ), + page + .locator('form') + .filter({ hasText: 'Organization Name' }) + .getByRole('button', { name: 'Save' }) + .click(), + ]); + await page.reload(); await expect(page.locator('[data-testid="organization_switcher"]:visible')).toContainText( 'NEW ORG NAME' ); }); +test('test that organization currency can be updated', async ({ page }) => { + await goToOrganizationSettings(page); + await page.getByLabel('Currency', { exact: true }).selectOption('USD'); + await Promise.all([ + page.waitForRequest( + (request) => + request.url().includes('/api/v1/organizations/') && + request.method() === 'PUT' && + request.postDataJSON().currency === 'USD' + ), + page.waitForResponse( + async (response) => + response.url().includes('/api/v1/organizations/') && + response.request().method() === 'PUT' && + response.status() === 200 && + (await response.json()).data.currency === 'USD' + ), + page + .locator('form') + .filter({ hasText: 'Organization Name' }) + .getByRole('button', { name: 'Save' }) + .click(), + ]); + await page.reload(); + await expect(page.getByLabel('Currency', { exact: true })).toHaveValue('USD'); +}); + test('test that organization billable rate can be updated with all existing time entries', async ({ page, }) => { @@ -369,13 +408,130 @@ test('test that format settings persist after page reload', async ({ page }) => await expect(page.getByLabel('Date Format')).toContainText('DD/MM/YYYY'); }); +// ============================================= +// Create, Delete & Switch +// ============================================= + +test.describe('Organization Create, Delete & Switch', () => { + async function createOrganization(page, name: string) { + await page.goto(PLAYWRIGHT_BASE_URL + '/organizations/create'); + await page.getByLabel('Organization Name').fill(name); + await Promise.all([ + page.waitForResponse( + (response) => + response.url().includes('/api/v1/organizations') && + response.request().method() === 'POST' && + response.status() === 201 + ), + page.getByRole('button', { name: 'Create' }).click(), + ]); + // The backend switches the current organization to the new one and the + // frontend reloads into its dashboard. + await expect(page.getByTestId('dashboard_view')).toBeVisible({ timeout: 10000 }); + } + + test('can create a new organization and switches to it automatically', async ({ page }) => { + const newOrgName = 'CreateOrg' + Math.floor(Math.random() * 100000); + await createOrganization(page, newOrgName); + + await expect(page.locator('[data-testid="organization_switcher"]:visible')).toContainText( + newOrgName + ); + }); + + test('does not create an organization when the name is empty', async ({ page }) => { + await page.goto(PLAYWRIGHT_BASE_URL + '/organizations/create'); + + // The form posts to the API, which rejects the empty name with a 422. + await Promise.all([ + page.waitForResponse( + (response) => + response.url().includes('/api/v1/organizations') && + response.request().method() === 'POST' && + response.status() === 422 + ), + page.getByRole('button', { name: 'Create' }).click(), + ]); + + // Validation failed, so we stay on the create form and never reach a + // dashboard. Assert on the form rather than the URL. + await expect(page.getByText('Organization Details')).toBeVisible(); + await expect(page.getByRole('alert')).toContainText('The name field is required.'); + await expect(page.getByLabel('Organization Name')).toHaveAttribute('aria-invalid', 'true'); + await expect(page.getByTestId('dashboard_view')).toHaveCount(0); + }); + + test('can delete an organization', async ({ page }) => { + // Create a throwaway organization so the primary one is never deleted. + const orgName = 'DeleteOrg' + Math.floor(Math.random() * 100000); + await createOrganization(page, orgName); + + // Open the (now current) throwaway organization's settings. + await goToOrganizationSettings(page); + + // Open the confirmation modal, then confirm inside the dialog. + await page.getByRole('button', { name: 'Delete Organization' }).click(); + await Promise.all([ + page.waitForResponse( + (response) => + response.url().includes('/api/v1/organizations') && + response.request().method() === 'DELETE' && + response.status() === 204 + ), + page.getByRole('dialog').getByRole('button', { name: 'Delete Organization' }).click(), + ]); + + // We are redirected to the dashboard of a different organization. + await expect(page.getByTestId('dashboard_view')).toBeVisible({ timeout: 10000 }); + await expect( + page.locator('[data-testid="organization_switcher"]:visible') + ).not.toContainText(orgName); + }); + + test('can switch the current organization via the organization switcher', async ({ page }) => { + await page.goto(PLAYWRIGHT_BASE_URL + '/dashboard'); + const orgSwitcher = page.locator('[data-testid="organization_switcher"]:visible'); + await expect(orgSwitcher).toBeVisible(); + const previousOrgNameLines = (await orgSwitcher.innerText()) + .split('\n') + .map((line) => line.trim()) + .filter(Boolean); + const previousOrgName = previousOrgNameLines[previousOrgNameLines.length - 1]; + + // Ensure there are at least two organizations to switch between. + const orgName = 'SwitchOrg' + Math.floor(Math.random() * 100000); + await createOrganization(page, orgName); + + await expect(orgSwitcher).toContainText(orgName); + + // Open the switcher and pick a different organization. + await orgSwitcher.click(); + await expect(page.getByText('Switch Organizations')).toBeVisible(); + const otherOrgButton = page.getByRole('menuitem', { name: previousOrgName }); + await expect(otherOrgButton).toBeVisible(); + + await Promise.all([ + page.waitForResponse( + (response) => + response.url().includes('/users/me/current-organization') && + response.request().method() === 'PUT' && + response.status() === 200 + ), + otherOrgButton.click(), + ]); + + await expect(orgSwitcher).not.toContainText(orgName, { timeout: 10000 }); + await expect(orgSwitcher).toContainText(previousOrgName, { timeout: 10000 }); + }); +}); + // ============================================= // Admin Permission Tests // ============================================= test.describe('Admin Organization Settings Access', () => { test('admin can see and edit organization settings', async ({ ctx, admin }) => { - await admin.page.goto(PLAYWRIGHT_BASE_URL + '/teams/' + ctx.orgId); + await admin.page.goto(PLAYWRIGHT_BASE_URL + '/organizations/' + ctx.orgId); // Organization Name section is visible await expect( @@ -396,6 +552,9 @@ test.describe('Admin Organization Settings Access', () => { // Save buttons should be visible (admin can update) await expect(admin.page.getByRole('button', { name: 'Save' }).first()).toBeVisible(); + // The Organization Name input is editable (admin can update) + await expect(admin.page.getByLabel('Organization Name')).toBeEnabled(); + // Delete organization should NOT be visible (owner only) await expect( admin.page.getByRole('heading', { name: 'Delete Organization' }) @@ -409,13 +568,17 @@ test.describe('Admin Organization Settings Access', () => { test.describe('Employee Organization Settings Restrictions', () => { test('employee can see org name but not editable settings', async ({ ctx, employee }) => { - await employee.page.goto(PLAYWRIGHT_BASE_URL + '/teams/' + ctx.orgId); + await employee.page.goto(PLAYWRIGHT_BASE_URL + '/organizations/' + ctx.orgId); // Organization Name section is visible (but inputs are disabled) await expect( employee.page.getByRole('heading', { name: 'Organization Name', level: 3 }) ).toBeVisible({ timeout: 10000 }); + // The name and currency inputs are rendered but disabled (employee cannot update) + await expect(employee.page.getByLabel('Organization Name')).toBeDisabled(); + await expect(employee.page.getByLabel('Currency')).toBeDisabled(); + // Editable settings sections should NOT be visible await expect( employee.page.getByRole('heading', { name: 'Billable Rate', level: 3 }) @@ -429,5 +592,10 @@ test.describe('Employee Organization Settings Restrictions', () => { // Save button should not be visible (employee cannot update) await expect(employee.page.getByRole('button', { name: 'Save' })).not.toBeVisible(); + + // Delete organization should NOT be visible (owner only) + await expect( + employee.page.getByRole('heading', { name: 'Delete Organization' }) + ).not.toBeVisible(); }); }); diff --git a/e2e/profile.spec.ts b/e2e/profile.spec.ts index 302312621..bcc115dbc 100644 --- a/e2e/profile.spec.ts +++ b/e2e/profile.spec.ts @@ -1,30 +1,374 @@ import { test, expect } from '../playwright/fixtures'; import { PLAYWRIGHT_BASE_URL, TEST_USER_PASSWORD } from '../playwright/config'; +import { + countEmailsWithSubject, + getEmailChangeVerificationUrl, + waitForEmailCount, +} from './utils/mailpit'; +import { getCurrentUserViaApi } from './utils/api'; +import { registerUser } from './utils/members'; import type { Page } from '@playwright/test'; +import path from 'path'; async function goToProfilePage(page: Page) { await page.goto(PLAYWRIGHT_BASE_URL + '/user/profile'); } -test('test that user name can be updated', async ({ page }) => { - await page.goto(PLAYWRIGHT_BASE_URL + '/user/profile'); +function profileInformationForm(page: Page) { + return page + .getByRole('heading', { name: 'Profile Information', exact: true }) + .locator('xpath=ancestor::*[descendant::form][1]'); +} + +async function saveProfileForm(page: Page): Promise { + const form = profileInformationForm(page); + await form.getByRole('button', { name: 'Save' }).click(); + await expect(form.getByText('Saved.', { exact: true })).toBeVisible(); +} + +test('user name can be updated', async ({ page }) => { + await goToProfilePage(page); await page.getByLabel('Name', { exact: true }).fill('NEW NAME'); + await saveProfileForm(page); + await page.reload(); + await expect(page.getByLabel('Name', { exact: true })).toHaveValue('NEW NAME'); +}); + +test('timezone change persists across reload', async ({ page }) => { + await goToProfilePage(page); + await page.getByLabel('Timezone').selectOption('America/New_York'); + await saveProfileForm(page); + await page.reload(); + await expect(page.getByLabel('Timezone')).toHaveValue('America/New_York'); +}); + +test('week-start change persists across reload', async ({ page }) => { + await goToProfilePage(page); + await page.getByLabel('Start of the week').selectOption('sunday'); + await saveProfileForm(page); + await page.reload(); + await expect(page.getByLabel('Start of the week')).toHaveValue('sunday'); +}); + +test('profile photo can be uploaded, persists across reload, and can be removed', async ({ + page, +}) => { + await goToProfilePage(page); + const form = profileInformationForm(page); + const profilePhoto = form.getByRole('img', { name: 'John Doe' }); + + await expect(profilePhoto).toBeVisible(); + await expect(profilePhoto).toHaveAttribute('src', /ui-avatars\.com/); + await expect(form.getByRole('button', { name: 'Remove Photo' })).toBeHidden(); + + await form.locator('#photo').setInputFiles(path.resolve('resources/testfiles/test.png')); + await saveProfileForm(page); + await expect(profilePhoto).toHaveAttribute('src', /profile-photos/); + await expect(form.getByRole('button', { name: 'Remove Photo' })).toBeVisible(); + + await page.reload(); + const reloadedForm = profileInformationForm(page); + const reloadedProfilePhoto = reloadedForm.getByRole('img', { name: 'John Doe' }); + await expect(reloadedProfilePhoto).toHaveAttribute('src', /profile-photos/); + await Promise.all([ - page.getByRole('button', { name: 'Save' }).first().click(), - page.waitForResponse('**/user/profile-information'), + page.waitForResponse( + (response) => + response.url().includes('/api/v1/users/') && + response.request().method() === 'PUT' && + response.status() === 200 + ), + reloadedForm.getByRole('button', { name: 'Remove Photo' }).click(), ]); + await expect(reloadedProfilePhoto).toHaveAttribute('src', /ui-avatars\.com/); + await expect(reloadedForm.getByRole('button', { name: 'Remove Photo' })).toBeHidden(); + await page.reload(); - await expect(page.getByLabel('Name', { exact: true })).toHaveValue('NEW NAME'); + const finalForm = profileInformationForm(page); + await expect(finalForm.getByRole('img', { name: 'John Doe' })).toHaveAttribute( + 'src', + /ui-avatars\.com/ + ); + await expect(finalForm.getByRole('button', { name: 'Remove Photo' })).toBeHidden(); }); -test.skip('test that user email can be updated', async ({ page }) => { - // this does not work because of email verification currently - await page.goto(PLAYWRIGHT_BASE_URL + '/user/profile'); - const emailId = Math.round(Math.random() * 10000); - await page.getByLabel('Email').fill(`newemail+${emailId}@test.com`); - await page.getByRole('button', { name: 'Save' }).first().click(); +test('field-level validation errors render inline when the server returns 422', async ({ + page, +}) => { + await goToProfilePage(page); + const form = profileInformationForm(page); + await form.getByLabel('Name').fill('a'.repeat(256)); + await Promise.all([ + page.waitForResponse( + (response) => + response.url().includes('/api/v1/users/') && + response.request().method() === 'PUT' && + response.status() === 422 + ), + form.getByRole('button', { name: 'Save' }).click(), + ]); + await expect(form.getByRole('alert').filter({ hasText: /255 characters/i })).toBeVisible(); +}); + +test('submitting a new email keeps the current email displayed after reload', async ({ + page, + ctx, +}) => { + const { email: oldEmail } = await getCurrentUserViaApi(ctx); + const newEmail = `newemail+${Date.now()}@test.com`; + + await goToProfilePage(page); + await page.getByLabel('Email').fill(newEmail); + await saveProfileForm(page); + await page.reload(); + + await expect(page.getByLabel('Email')).toHaveValue(oldEmail); +}); + +test('submitting a new email sends a verification email to the new address', async ({ + page, + request, +}) => { + await goToProfilePage(page); + const newEmail = `newemail+${Date.now()}@test.com`; + + await page.getByLabel('Email').fill(newEmail); + await saveProfileForm(page); + + expect(await waitForEmailCount(request, newEmail, 'Verify Email Address', 1)).toBeGreaterThan( + 0 + ); +}); + +test('mixed-case email is lower-cased before the verification mail is sent', async ({ + page, + request, +}) => { + await goToProfilePage(page); + const stamp = Date.now(); + const mixedCase = `MixedCase+${stamp}@Example.COM`; + const lowerCased = `mixedcase+${stamp}@example.com`; + + await page.getByLabel('Email').fill(mixedCase); + await saveProfileForm(page); + + const verifyUrl = await getEmailChangeVerificationUrl(request, lowerCased); + expect(new URL(verifyUrl).searchParams.get('email')).toBe(lowerCased); +}); + +test('re-submitting the current email does not send a verification email', async ({ + page, + ctx, + request, +}) => { + const { email: currentEmail } = await getCurrentUserViaApi(ctx); + const beforeCount = await countEmailsWithSubject(request, currentEmail, 'Verify Email Address'); + + await goToProfilePage(page); + await page.getByLabel('Email').fill(currentEmail); + await saveProfileForm(page); + + await new Promise((r) => setTimeout(r, 1000)); + const afterCount = await countEmailsWithSubject(request, currentEmail, 'Verify Email Address'); + expect(afterCount).toBe(beforeCount); +}); + +test('after submitting a new email the pending-email banner is shown with a resend button', async ({ + page, +}) => { + await goToProfilePage(page); + const newEmail = `pending+${Date.now()}@test.com`; + await page.getByLabel('Email').fill(newEmail); + await saveProfileForm(page); + + await expect(page.getByText(`A verification link was sent to`)).toBeVisible(); + await expect(page.getByText(newEmail)).toBeVisible(); + await expect(page.getByRole('button', { name: 'Resend verification email' })).toBeVisible(); +}); + +test('clicking resend sends a second verification email and shows confirmation', async ({ + page, + request, +}) => { + await goToProfilePage(page); + const newEmail = `resend+${Date.now()}@test.com`; + await page.getByLabel('Email').fill(newEmail); + await saveProfileForm(page); + + const beforeCount = await waitForEmailCount(request, newEmail, 'Verify Email Address', 1); + await page.getByRole('button', { name: 'Resend verification email' }).click(); + + await expect(page.getByText('Verification email sent.')).toBeVisible(); + const afterCount = await waitForEmailCount( + request, + newEmail, + 'Verify Email Address', + beforeCount + 1 + ); + expect(afterCount).toBeGreaterThan(beforeCount); +}); + +test('cancelling a pending email change clears it and hides the banner', async ({ page, ctx }) => { + const { email: currentEmail } = await getCurrentUserViaApi(ctx); + const newEmail = `cancel+${Date.now()}@test.com`; + + await goToProfilePage(page); + await page.getByLabel('Email').fill(newEmail); + await saveProfileForm(page); + + // The pending-email banner is shown with the cancel control. + await expect(page.getByText('A verification link was sent to')).toBeVisible(); + await expect(page.getByText(newEmail)).toBeVisible(); + const cancelButton = page.getByRole('button', { name: 'Cancel email change' }); + await expect(cancelButton).toBeVisible(); + + // Cancelling clears the pending email server-side (204). + await Promise.all([ + page.waitForResponse( + (response) => + response.url().includes('/reset-pending-email') && + response.request().method() === 'POST' && + response.status() === 204 + ), + cancelButton.click(), + ]); + + // The banner disappears and the email field still shows the current address. + await expect(page.getByText('A verification link was sent to')).toBeHidden(); + await expect(page.getByLabel('Email')).toHaveValue(currentEmail); + + // The cancellation is persistent — still gone after a reload. await page.reload(); - await expect(page.getByLabel('Email')).toHaveValue(`newemail+${emailId}@test.com`); + await expect(page.getByText('A verification link was sent to')).toBeHidden(); + await expect(page.getByLabel('Email')).toHaveValue(currentEmail); +}); + +test('re-submitting the same pending email does not send another verification email', async ({ + page, + request, +}) => { + await goToProfilePage(page); + const newEmail = `dup+${Date.now()}@test.com`; + await page.getByLabel('Email').fill(newEmail); + await saveProfileForm(page); + const beforeCount = await waitForEmailCount(request, newEmail, 'Verify Email Address', 1); + + await page.getByLabel('Email').fill(newEmail); + await saveProfileForm(page); + + await new Promise((r) => setTimeout(r, 1000)); + const afterCount = await countEmailsWithSubject(request, newEmail, 'Verify Email Address'); + expect(afterCount).toBe(beforeCount); +}); + +test('clicking the verification link swaps the email and shows a success banner', async ({ + page, +}) => { + await goToProfilePage(page); + const newEmail = `verify+${Date.now()}@test.com`; + await page.getByLabel('Email').fill(newEmail); + await saveProfileForm(page); + const verifyUrl = await getEmailChangeVerificationUrl(page.request, newEmail); + + await page.goto(verifyUrl); + await page.waitForURL(/\/dashboard/); + + const banner = page.getByTestId('banner'); + await expect(banner).toBeVisible(); + await expect(banner).toContainText('Your email address has been updated successfully.'); + + await goToProfilePage(page); + await expect(page.getByLabel('Email')).toHaveValue(newEmail); +}); + +test('visiting another user’s verification link is forbidden', async ({ page, browser }) => { + await goToProfilePage(page); + const newEmail = `victim+${Date.now()}@test.com`; + await page.getByLabel('Email').fill(newEmail); + await saveProfileForm(page); + const verifyUrl = await getEmailChangeVerificationUrl(page.request, newEmail); + + const other = await registerUser(browser, 'Other User', `other+${Date.now()}@test.com`); + try { + const response = await other.page.goto(verifyUrl); + expect(response?.status()).toBe(403); + } finally { + await other.close(); + } +}); + +test('a stale verification link from a previous submission is rejected', async ({ page }) => { + await goToProfilePage(page); + const stamp = Date.now(); + const olderEmail = `older+${stamp}@test.com`; + const newerEmail = `newer+${stamp}@test.com`; + + await page.getByLabel('Email').fill(olderEmail); + await saveProfileForm(page); + const staleUrl = await getEmailChangeVerificationUrl(page.request, olderEmail); + + await page.getByLabel('Email').fill(newerEmail); + await saveProfileForm(page); + + const response = await page.goto(staleUrl); + expect(response?.status()).toBe(403); +}); + +test('visiting the verification link while logged out redirects to login', async ({ + page, + browser, +}) => { + await goToProfilePage(page); + const newEmail = `loggedout+${Date.now()}@test.com`; + await page.getByLabel('Email').fill(newEmail); + await saveProfileForm(page); + const verifyUrl = await getEmailChangeVerificationUrl(page.request, newEmail); + + const anonContext = await browser.newContext(); + try { + const anonPage = await anonContext.newPage(); + await anonPage.goto(verifyUrl); + await anonPage.waitForURL(/\/login/); + } finally { + await anonContext.close(); + } +}); + +test('delete account shows an error when the password is wrong', async ({ page }) => { + await goToProfilePage(page); + await page.getByRole('button', { name: 'Delete Account' }).click(); + const dialog = page.getByRole('dialog'); + await dialog.getByPlaceholder('Password').fill('not-the-real-password'); + await Promise.all([ + page.waitForResponse( + (response) => + response.url().includes('/user/confirm-password') && + response.request().method() === 'POST' && + response.status() === 422 + ), + dialog.getByRole('button', { name: 'Delete Account' }).click(), + ]); + await expect(dialog.getByRole('alert')).toBeVisible(); + await expect(dialog).toBeVisible(); +}); + +test('delete account succeeds with the correct password and logs the user out', async ({ + page, +}) => { + await goToProfilePage(page); + await page.getByRole('button', { name: 'Delete Account' }).click(); + const dialog = page.getByRole('dialog'); + await dialog.getByPlaceholder('Password').fill(TEST_USER_PASSWORD); + await Promise.all([ + page.waitForResponse( + (response) => + response.url().includes('/api/v1/users/') && + response.request().method() === 'DELETE' && + response.status() === 204 + ), + dialog.getByRole('button', { name: 'Delete Account' }).click(), + ]); + await page.waitForURL(/\/login/); }); async function createNewApiToken(page) { diff --git a/e2e/shared-reports.spec.ts b/e2e/shared-reports.spec.ts index 9ee2ed1ba..ff262b17f 100644 --- a/e2e/shared-reports.spec.ts +++ b/e2e/shared-reports.spec.ts @@ -469,7 +469,7 @@ test('test that creating a report with an expiration date works', async ({ page, await datePicker.click(); // Select a date in the next month - const calendarGrid = page.getByRole('grid'); + const calendarGrid = page.getByRole('gridcell').first(); await expect(calendarGrid).toBeVisible({ timeout: 5000 }); await page.getByRole('button', { name: /Next/i }).click(); await page.getByRole('gridcell').filter({ hasText: /^15$/ }).first().click(); @@ -547,7 +547,7 @@ test('test that editing a report to make it public with expiration date works', await datePicker.click(); // Select a date in the next month - const calendarGrid = page.getByRole('grid'); + const calendarGrid = page.getByRole('gridcell').first(); await expect(calendarGrid).toBeVisible({ timeout: 5000 }); await page.getByRole('button', { name: /Next/i }).click(); await page.getByRole('gridcell').filter({ hasText: /^20$/ }).first().click(); @@ -741,7 +741,7 @@ test('test that updating expiration date on already-public report works', async await datePicker.click(); // Select the 25th of next month - const calendarGrid = page.getByRole('grid'); + const calendarGrid = page.getByRole('gridcell').first(); await expect(calendarGrid).toBeVisible({ timeout: 5000 }); await page.getByRole('button', { name: /Next/i }).click(); await page.getByRole('gridcell').filter({ hasText: /^25$/ }).first().click(); diff --git a/e2e/time.spec.ts b/e2e/time.spec.ts index dfd4ba4ec..87e1c6dd3 100644 --- a/e2e/time.spec.ts +++ b/e2e/time.spec.ts @@ -462,7 +462,7 @@ test('test that setting a date in the create modal works', async ({ page }) => { await startDatePicker.click(); // Wait for calendar to appear - const calendarGrid = page.getByRole('grid'); + const calendarGrid = page.getByRole('gridcell').first(); await expect(calendarGrid).toBeVisible({ timeout: 5000 }); // Navigate to previous month and select the 15th (a day that's always in the middle of the month) @@ -515,7 +515,7 @@ test('test that updating the date via the time entry row range selector works', await startDatePicker.click(); // Wait for the calendar to appear and select a day - const calendarGrid = page.getByRole('grid'); + const calendarGrid = page.getByRole('gridcell').first(); await expect(calendarGrid).toBeVisible({ timeout: 5000 }); // Navigate to previous month and select the 5th @@ -568,7 +568,7 @@ test('test that updating the end date via the time entry row range selector work await endDatePicker.click(); // Wait for the calendar to appear - const calendarGrid = page.getByRole('grid'); + const calendarGrid = page.getByRole('gridcell').first(); await expect(calendarGrid).toBeVisible({ timeout: 5000 }); // Navigate to next month and select the 20th (to ensure end > start) diff --git a/e2e/timetracker.spec.ts b/e2e/timetracker.spec.ts index 58df5b2fc..de364e22e 100644 --- a/e2e/timetracker.spec.ts +++ b/e2e/timetracker.spec.ts @@ -293,7 +293,7 @@ test('test that setting an end time with a different date via the timetracker ra await endDatePicker.click(); // Calendar should appear - const calendarGrid = page.getByRole('grid'); + const calendarGrid = page.getByRole('gridcell').first(); await expect(calendarGrid).toBeVisible({ timeout: 5000 }); // Navigate to the next month and select a day to ensure end > start diff --git a/e2e/utils/api.ts b/e2e/utils/api.ts index 976f1fbfd..e693529e6 100644 --- a/e2e/utils/api.ts +++ b/e2e/utils/api.ts @@ -641,10 +641,13 @@ export async function updateOrganizationCurrencyViaWeb( const xsrfCookie = cookies.find((c) => c.name === 'XSRF-TOKEN'); const xsrfToken = xsrfCookie ? decodeURIComponent(xsrfCookie.value) : ''; - const response = await page.request.put(`${PLAYWRIGHT_BASE_URL}/teams/${ctx.orgId}`, { - headers: { 'X-XSRF-TOKEN': xsrfToken }, - data: { name, currency }, - }); + const response = await page.request.put( + `${PLAYWRIGHT_BASE_URL}/api/v1/organizations/${ctx.orgId}`, + { + headers: { 'X-XSRF-TOKEN': xsrfToken }, + data: { name, currency }, + } + ); expect(response.status()).toBe(200); } @@ -788,53 +791,36 @@ export async function createTimeEntryWithTimestampsViaApi( // User profile helpers // ────────────────────────────────────────────────── -export async function updateUserProfileViaWeb( - page: Page, +export async function getCurrentUserViaApi(ctx: TestContext) { + const response = await ctx.request.get(`${PLAYWRIGHT_BASE_URL}/api/v1/users/me`); + expect(response.status()).toBe(200); + const body = await response.json(); + return body.data as { + id: string; + name: string; + email: string; + timezone: string; + week_start: string; + }; +} + +export async function updateUserProfileViaApi( + ctx: TestContext, settings: { timezone?: string; week_start?: string } ) { - // Read user info from Inertia's data-page attribute on the root element - const userInfo = await page.evaluate(() => { - // Try Inertia's data-page attribute (stores initial page props as JSON) - const appEl = document.getElementById('app'); - if (appEl) { - const dataPage = appEl.getAttribute('data-page'); - if (dataPage) { - try { - const parsed = JSON.parse(dataPage); - const user = parsed?.props?.auth?.user; - if (user) { - return { - name: user.name, - email: user.email, - timezone: user.timezone, - week_start: user.week_start, - }; - } - } catch { - // JSON parse failed - } - } - } - return null; - }); - if (!userInfo) throw new Error('Could not read user info from Inertia data-page attribute'); + const user = await getCurrentUserViaApi(ctx); - const cookies = await page.context().cookies(); - const xsrfCookie = cookies.find((c) => c.name === 'XSRF-TOKEN'); - const xsrfToken = xsrfCookie ? decodeURIComponent(xsrfCookie.value) : ''; + // Only send the fields under test; the endpoint leaves omitted fields untouched. + const data: Record = {}; + if (settings.timezone !== undefined) { + data.timezone = settings.timezone; + } + if (settings.week_start !== undefined) { + data.week_start = settings.week_start; + } - const response = await page.request.put(`${PLAYWRIGHT_BASE_URL}/user/profile-information`, { - headers: { - 'X-XSRF-TOKEN': xsrfToken, - 'Content-Type': 'application/json', - Accept: 'application/json', - }, - data: { - name: userInfo.name, - email: userInfo.email, - timezone: settings.timezone ?? userInfo.timezone, - week_start: settings.week_start ?? userInfo.week_start, - }, + const response = await ctx.request.put(`${PLAYWRIGHT_BASE_URL}/api/v1/users/${user.id}`, { + data, }); expect(response.status()).toBe(200); } diff --git a/e2e/utils/mailpit.ts b/e2e/utils/mailpit.ts index 8d5c807a1..4df6723ae 100644 --- a/e2e/utils/mailpit.ts +++ b/e2e/utils/mailpit.ts @@ -46,7 +46,9 @@ export async function getInvitationAcceptUrl( expect(searchResult.messages.length).toBeGreaterThan(0); const message = await getMessage(request, searchResult.messages[0].ID); - const acceptUrlMatch = message.HTML.match(/href="([^"]*team-invitations[^"]*)"/); + const acceptUrlMatch = message.HTML.match( + /href="([^"]*(?:organization-invitations|team-invitations)[^"]*)"/ + ); expect(acceptUrlMatch).toBeTruthy(); return acceptUrlMatch![1].replace(/&/g, '&'); @@ -79,3 +81,64 @@ export async function getPasswordResetUrl( return resetUrlMatch![1].replace(/&/g, '&'); } + +/** + * Count emails matching the given subject sent to the given address. + */ +export async function countEmailsWithSubject( + request: APIRequestContext, + recipientEmail: string, + subject: string +): Promise { + const searchResult = await searchEmails( + request, + `to:${encodeURIComponent(recipientEmail)} subject:"${subject}"` + ); + return searchResult.messages.length; +} + +/** + * Poll Mailpit until the count of matching emails reaches `min`, or 5 attempts + * (~2.5s) elapse. Returns the final count. + */ +export async function waitForEmailCount( + request: APIRequestContext, + recipientEmail: string, + subject: string, + min: number +): Promise { + let count = 0; + for (let attempt = 0; attempt < 5; attempt++) { + count = await countEmailsWithSubject(request, recipientEmail, subject); + if (count >= min) break; + await new Promise((r) => setTimeout(r, 500)); + } + return count; +} + +/** + * Find the email-change verification URL from a Mailpit email sent to the given address. + * Retries a few times to allow for email delivery delay. + */ +export async function getEmailChangeVerificationUrl( + request: APIRequestContext, + recipientEmail: string +): Promise { + let searchResult: { messages: Array<{ ID: string }> } = { messages: [] }; + + for (let attempt = 0; attempt < 5; attempt++) { + searchResult = await searchEmails( + request, + `to:${encodeURIComponent(recipientEmail)} subject:"Verify Email Address"` + ); + if (searchResult.messages.length > 0) break; + await new Promise((resolve) => setTimeout(resolve, 500)); + } + expect(searchResult.messages.length).toBeGreaterThan(0); + + const message = await getMessage(request, searchResult.messages[0].ID); + const verifyUrlMatch = message.HTML.match(/href="([^"]*verify-email-change[^"]*)"/); + expect(verifyUrlMatch).toBeTruthy(); + + return verifyUrlMatch![1].replace(/&/g, '&'); +} diff --git a/lang/en/exceptions.php b/lang/en/exceptions.php index fda420e65..485eb1455 100644 --- a/lang/en/exceptions.php +++ b/lang/en/exceptions.php @@ -23,6 +23,7 @@ use App\Exceptions\Api\UserIsAlreadyMemberOfOrganizationApiException; use App\Exceptions\Api\UserIsAlreadyMemberOfProjectApiException; use App\Exceptions\Api\UserNotPlaceholderApiException; +use App\Exceptions\Api\UserResendEmailVerificationNoPendingEmailApiException; use App\Service\Export\ExportException; return [ @@ -49,6 +50,7 @@ ThisPlaceholderCanNotBeInvitedUseTheMergeToolInsteadException::KEY => 'This placeholder can not be invited use the merge tool instead', InvitationForTheEmailAlreadyExistsApiException::KEY => 'The email has already been invited to the organization. Please wait for the user to accept the invitation or resend the invitation email.', OverlappingTimeEntryApiException::KEY => 'Overlapping time entries are not allowed.', + UserResendEmailVerificationNoPendingEmailApiException::KEY => 'Resend email not possible, no pending email.', ], 'unknown_error_in_admin_panel' => 'An unknown error occurred. Please check the logs.', ]; diff --git a/package-lock.json b/package-lock.json index 0bc8e8c05..41172b9e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,64 +10,65 @@ "resources/js/packages/api" ], "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/vue": "^1.0.6", - "@heroicons/vue": "^2.1.1", - "@rushstack/eslint-patch": "^1.10.5", + "@floating-ui/core": "^1.7.5", + "@floating-ui/vue": "^1.1.11", + "@heroicons/vue": "^2.2.0", + "@lucide/vue": "^1.14.0", + "@rushstack/eslint-patch": "^1.16.1", "@tailwindcss/container-queries": "^0.1.1", - "@tanstack/vue-form": "^1.3.1", - "@tanstack/vue-query": "^5.56.2", - "@tanstack/vue-query-devtools": "^5.58.0", - "@tanstack/vue-table": "^8.21.2", + "@tanstack/vue-form": "^1.32.0", + "@tanstack/vue-query": "^5.100.10", + "@tanstack/vue-query-devtools": "^5.91.0", + "@tanstack/vue-table": "^8.21.3", "@vue/eslint-config-prettier": "^10.2.0", - "@vue/eslint-config-typescript": "^14.3.0", - "@vueuse/core": "^14.2.1", - "@vueuse/integrations": "^14.0.0", + "@vue/eslint-config-typescript": "^14.7.0", + "@vueuse/core": "^14.3.0", + "@vueuse/integrations": "^14.3.0", "@zodios/core": "^10.9.6", - "chroma-js": "3.1.2", + "chroma-js": "^3.2.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "dayjs": "^1.11.11", + "dayjs": "^1.11.20", "echarts": "^6.0.0", - "focus-trap": "^8.0.0", - "lucide-vue-next": "^0.487.0", - "parse-duration": "^2.0.1", - "pinia": "^3.0.0", - "radix-vue": "^1.9.6", - "reka-ui": "2.8.2", - "tailwind-merge": "^2.6.0", + "focus-trap": "^8.2.0", + "parse-duration": "^2.1.6", + "pinia": "^3.0.4", + "radix-vue": "^1.9.17", + "reka-ui": "^2.9.7", + "tailwind-merge": "^2.6.1", "tailwindcss-animate": "^1.0.7", - "vue-echarts": "^8.0.0", - "zod": "^3.23.8" + "vue-draggable-plus": "^0.6.1", + "vue-echarts": "^8.0.1", + "zod": "^3.25.76" }, "devDependencies": { - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "^9.19.0", - "@inertiajs/vue3": "^2.0.0", - "@playwright/test": "^1.41.1", - "@tailwindcss/forms": "^0.5.9", - "@tailwindcss/typography": "^0.5.15", - "@types/chroma-js": "^3.1.0", - "@types/node": "^22.10.10", - "@vitejs/plugin-vue": "^6.0.3", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "^9.39.4", + "@inertiajs/vue3": "^2.3.23", + "@playwright/test": "^1.60.0", + "@tailwindcss/forms": "^0.5.11", + "@tailwindcss/typography": "^0.5.19", + "@types/chroma-js": "^3.1.2", + "@types/node": "^22.19.19", + "@vitejs/plugin-vue": "^6.0.6", "@vue/test-utils": "^2.4.6", - "@vue/tsconfig": "^0.8.0", - "autoprefixer": "^10.4.20", - "axios": "^1.6.4", - "eslint-plugin-unused-imports": "^4.1.4", + "@vue/tsconfig": "^0.8.1", + "autoprefixer": "^10.5.0", + "axios": "^1.16.0", + "eslint-plugin-unused-imports": "^4.4.1", "happy-dom": "^20.8.9", "laravel-vite-plugin": "^2.1.0", - "openapi-zod-client": "^1.16.2", - "postcss": "^8.4.47", + "openapi-zod-client": "^1.18.3", + "postcss": "^8.5.14", "postcss-import": "^15.1.0", "postcss-nesting": "^12.1.5", - "tailwindcss": "^3.4.13", - "typescript": "^5.7.3", - "vite": "^7.0.0", + "tailwindcss": "^3.4.19", + "typescript": "^5.9.3", + "vite": "^7.3.3", "vite-plugin-checker": "^0.12.0", "vitest": "^4.1.4", - "vue": "^3.5.0", - "vue-tsc": "^3.0.0" + "vue": "^3.5.34", + "vue-tsc": "^3.2.8" } }, "node_modules/@alloc/quick-lru": { @@ -137,9 +138,9 @@ } }, "node_modules/@apidevtools/swagger-parser/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", "dependencies": { @@ -191,9 +192,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", + "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", "dev": true, "license": "MIT", "engines": { @@ -370,9 +371,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", - "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", "license": "MIT", "dependencies": { "@babel/types": "^7.29.0" @@ -875,90 +876,50 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.23.5", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", - "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", "license": "Apache-2.0", "peer": true, "dependencies": { - "@eslint/object-schema": "^3.0.5", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", - "minimatch": "^10.2.4" + "minimatch": "^3.1.5" }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - } - }, - "node_modules/@eslint/config-array/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "license": "MIT", - "peer": true, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "license": "BlueOak-1.0.0", - "peer": true, - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/config-helpers": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz", - "integrity": "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "license": "Apache-2.0", "peer": true, "dependencies": { - "@eslint/core": "^1.2.1" + "@eslint/core": "^0.17.0" }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", - "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "license": "Apache-2.0", "peer": true, "dependencies": { "@types/json-schema": "^7.0.15" }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/eslintrc": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", - "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.14.0", @@ -982,7 +943,6 @@ "version": "9.39.4", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", - "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -992,27 +952,27 @@ } }, "node_modules/@eslint/object-schema": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", - "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "license": "Apache-2.0", "peer": true, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz", - "integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "license": "Apache-2.0", "peer": true, "dependencies": { - "@eslint/core": "^1.2.1", + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@floating-ui/core": { @@ -1087,29 +1047,43 @@ } }, "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", "license": "Apache-2.0", "peer": true, + "dependencies": { + "@humanfs/types": "^0.15.0" + }, "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", "license": "Apache-2.0", "peer": true, "dependencies": { - "@humanfs/core": "^0.19.1", + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", "@humanwhocodes/retry": "^0.4.0" }, "engines": { "node": ">=18.18.0" } }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=18.18.0" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -1139,9 +1113,9 @@ } }, "node_modules/@inertiajs/core": { - "version": "2.3.21", - "resolved": "https://registry.npmjs.org/@inertiajs/core/-/core-2.3.21.tgz", - "integrity": "sha512-grHSCUiWDBWqpRxaobyxUJu0FV6HLkkuJwvoNLVkHwkexLvoaLhb9BmtoQydlIYL5pk2O3jcKaGtWJ83JwTB4A==", + "version": "2.3.23", + "resolved": "https://registry.npmjs.org/@inertiajs/core/-/core-2.3.23.tgz", + "integrity": "sha512-d+jcdf91RY5bjT+ivBn2gu9Qsmxx5CacvVmVp7o9H2Lu/k1cBD0m4UZB5YKWfG11aBCucShBxuppEXme7sSEow==", "dev": true, "license": "MIT", "dependencies": { @@ -1153,13 +1127,13 @@ } }, "node_modules/@inertiajs/vue3": { - "version": "2.3.21", - "resolved": "https://registry.npmjs.org/@inertiajs/vue3/-/vue3-2.3.21.tgz", - "integrity": "sha512-gJuOD9HrB6WXpTCUB6yLDHA2yI5YGzhYcGlHCPB6mzt6Lvm7CsQA06CNOyk8eEooz0MYJhFF2V092hU1i866qg==", + "version": "2.3.23", + "resolved": "https://registry.npmjs.org/@inertiajs/vue3/-/vue3-2.3.23.tgz", + "integrity": "sha512-W6rhjNCIKQQYZsNFdlFEa+prATbXcIR5k9VMg3PsYfRmqTYTORZspdrTH7JLPMneLuhNiI/Y6VbFR0TxGdv5Fg==", "dev": true, "license": "MIT", "dependencies": { - "@inertiajs/core": "2.3.21", + "@inertiajs/core": "2.3.23", "@types/lodash-es": "^4.17.12", "laravel-precognition": "^1.0.2", "lodash-es": "^4.18.1" @@ -1169,18 +1143,18 @@ } }, "node_modules/@internationalized/date": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.12.0.tgz", - "integrity": "sha512-/PyIMzK29jtXaGU23qTvNZxvBXRtKbNnGDFD+PY6CZw/Y8Ex8pFUzkuCJCG9aOqmShjqhS9mPqP6Dk5onQY8rQ==", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.12.1.tgz", + "integrity": "sha512-6IedsVWXyq4P9Tj+TxuU8WGWM70hYLl12nbYU8jkikVpa6WXapFazPUcHUMDMoWftIDE2ILDkFFte6W2nFCkRQ==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" } }, "node_modules/@internationalized/number": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.5.tgz", - "integrity": "sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g==", + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.6.tgz", + "integrity": "sha512-iFgmQaXHE0vytNfpLZWOC2mEJCBRzcUxt53Xf/yCXG93lRvqas237i3r7X4RKMwO3txiyZD4mQjKAByFv6UGSQ==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -1268,25 +1242,33 @@ "fs-extra": "^10.1.0" } }, + "node_modules/@lucide/vue": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@lucide/vue/-/vue-1.14.0.tgz", + "integrity": "sha512-0s2fsXJGXYqcuyigsRtoTPqbeGGFOiLTYMDFfYvWO4rQNOongaJe1XDiExOLiybbI9+uQPBr5aGoiCdQNlSfQg==", + "license": "ISC", + "peerDependencies": { + "vue": ">=3.0.1" + } + }, "node_modules/@microsoft/api-extractor": { - "version": "7.58.2", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.58.2.tgz", - "integrity": "sha512-qmqWa0Fx1xn3irQy8MyuAKUs8e3CdwMJOujaPkM8gx5v/V7RcLhTjBU0/uL2kdhmROpW+5WG1FD98O441kkvQQ==", + "version": "7.58.7", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.58.7.tgz", + "integrity": "sha512-yK6OycD46gIzLRpj6ueVUWPk1ACSpkN1LBo05gY1qPTylbWyUCanXfH7+VgkI5LJrJoRSQR5F04XuCffCXLOBw==", "dev": true, "license": "MIT", "dependencies": { - "@microsoft/api-extractor-model": "7.33.6", + "@microsoft/api-extractor-model": "7.33.8", "@microsoft/tsdoc": "~0.16.0", "@microsoft/tsdoc-config": "~0.18.1", - "@rushstack/node-core-library": "5.22.0", - "@rushstack/rig-package": "0.7.2", - "@rushstack/terminal": "0.22.5", - "@rushstack/ts-command-line": "5.3.5", + "@rushstack/node-core-library": "5.23.1", + "@rushstack/rig-package": "0.7.3", + "@rushstack/terminal": "0.24.0", + "@rushstack/ts-command-line": "5.3.9", "diff": "~8.0.2", - "lodash": "~4.18.1", "minimatch": "10.2.3", "resolve": "~1.22.1", - "semver": "~7.5.4", + "semver": "~7.7.4", "source-map": "~0.6.1", "typescript": "5.9.3" }, @@ -1295,15 +1277,15 @@ } }, "node_modules/@microsoft/api-extractor-model": { - "version": "7.33.6", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.33.6.tgz", - "integrity": "sha512-E9iI4yGEVVusbTAqSLetVFxDuBVCVqCigcoQwdJuOjsLq5Hry3MkBgUQhSZNzLCu17pgjk58MI80GRDJLht/1A==", + "version": "7.33.8", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.33.8.tgz", + "integrity": "sha512-aIcoQggPyer3B6Ze3usz0YWC/oBwUHfRH5ETUsr+oT2BRA6SfTJl7IKPcPZkX4UR+PohowzW4uMxsvjrn8vm+w==", "dev": true, "license": "MIT", "dependencies": { "@microsoft/tsdoc": "~0.16.0", "@microsoft/tsdoc-config": "~0.18.1", - "@rushstack/node-core-library": "5.22.0" + "@rushstack/node-core-library": "5.23.1" } }, "node_modules/@microsoft/api-extractor/node_modules/balanced-match": { @@ -1317,9 +1299,9 @@ } }, "node_modules/@microsoft/api-extractor/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { @@ -1329,19 +1311,6 @@ "node": "18 || 20 || >=22" } }, - "node_modules/@microsoft/api-extractor/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@microsoft/api-extractor/node_modules/minimatch": { "version": "10.2.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.3.tgz", @@ -1359,14 +1328,11 @@ } }, "node_modules/@microsoft/api-extractor/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -1374,13 +1340,6 @@ "node": ">=10" } }, - "node_modules/@microsoft/api-extractor/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, "node_modules/@microsoft/tsdoc": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.16.0.tgz", @@ -1491,13 +1450,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.59.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.59.1.tgz", - "integrity": "sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==", + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.60.0.tgz", + "integrity": "sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.59.1" + "playwright": "1.60.0" }, "bin": { "playwright": "cli.js" @@ -1535,13 +1494,6 @@ } } }, - "node_modules/@rollup/pluginutils/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, - "license": "MIT" - }, "node_modules/@rollup/pluginutils/node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", @@ -1556,9 +1508,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", - "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.3.tgz", + "integrity": "sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==", "cpu": [ "arm" ], @@ -1569,9 +1521,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", - "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.3.tgz", + "integrity": "sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==", "cpu": [ "arm64" ], @@ -1582,9 +1534,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", - "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.3.tgz", + "integrity": "sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==", "cpu": [ "arm64" ], @@ -1595,9 +1547,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", - "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.3.tgz", + "integrity": "sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==", "cpu": [ "x64" ], @@ -1608,9 +1560,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", - "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.3.tgz", + "integrity": "sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==", "cpu": [ "arm64" ], @@ -1621,9 +1573,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", - "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.3.tgz", + "integrity": "sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==", "cpu": [ "x64" ], @@ -1634,9 +1586,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", - "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.3.tgz", + "integrity": "sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==", "cpu": [ "arm" ], @@ -1650,9 +1602,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", - "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.3.tgz", + "integrity": "sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==", "cpu": [ "arm" ], @@ -1666,9 +1618,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", - "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.3.tgz", + "integrity": "sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==", "cpu": [ "arm64" ], @@ -1682,9 +1634,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", - "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.3.tgz", + "integrity": "sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==", "cpu": [ "arm64" ], @@ -1698,9 +1650,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", - "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.3.tgz", + "integrity": "sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==", "cpu": [ "loong64" ], @@ -1714,9 +1666,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", - "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.3.tgz", + "integrity": "sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==", "cpu": [ "loong64" ], @@ -1730,9 +1682,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", - "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.3.tgz", + "integrity": "sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==", "cpu": [ "ppc64" ], @@ -1746,9 +1698,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", - "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.3.tgz", + "integrity": "sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==", "cpu": [ "ppc64" ], @@ -1762,9 +1714,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", - "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.3.tgz", + "integrity": "sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==", "cpu": [ "riscv64" ], @@ -1778,9 +1730,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", - "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.3.tgz", + "integrity": "sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==", "cpu": [ "riscv64" ], @@ -1794,9 +1746,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", - "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.3.tgz", + "integrity": "sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==", "cpu": [ "s390x" ], @@ -1810,9 +1762,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", - "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.3.tgz", + "integrity": "sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==", "cpu": [ "x64" ], @@ -1826,9 +1778,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", - "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.3.tgz", + "integrity": "sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==", "cpu": [ "x64" ], @@ -1842,9 +1794,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", - "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.3.tgz", + "integrity": "sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==", "cpu": [ "x64" ], @@ -1855,9 +1807,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", - "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.3.tgz", + "integrity": "sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==", "cpu": [ "arm64" ], @@ -1868,9 +1820,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", - "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.3.tgz", + "integrity": "sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==", "cpu": [ "arm64" ], @@ -1881,9 +1833,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", - "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.3.tgz", + "integrity": "sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==", "cpu": [ "ia32" ], @@ -1894,9 +1846,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", - "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.3.tgz", + "integrity": "sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==", "cpu": [ "x64" ], @@ -1907,9 +1859,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", - "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.3.tgz", + "integrity": "sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==", "cpu": [ "x64" ], @@ -1926,9 +1878,9 @@ "license": "MIT" }, "node_modules/@rushstack/node-core-library": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.22.0.tgz", - "integrity": "sha512-S/Dm/N+8tkbasS6yM5cF6q4iDFt14mQQniiVIwk1fd0zpPwWESspO4qtPyIl8szEaN86XOYC1HRRzZrOowxjtw==", + "version": "5.23.1", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.23.1.tgz", + "integrity": "sha512-wlKmIKIYCKuCASbITvOxLZXepPbwXvrv7S6ig6XNWFchSyhL/E2txmVXspHY49Wu2dzf7nI27a2k/yV5BA3EiA==", "dev": true, "license": "MIT", "dependencies": { @@ -1939,7 +1891,7 @@ "import-lazy": "~4.0.0", "jju": "~1.4.0", "resolve": "~1.22.1", - "semver": "~7.5.4" + "semver": "~7.7.4" }, "peerDependencies": { "@types/node": "*" @@ -1983,9 +1935,9 @@ } }, "node_modules/@rushstack/node-core-library/node_modules/fs-extra": { - "version": "11.3.4", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", - "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz", + "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==", "dev": true, "license": "MIT", "dependencies": { @@ -2004,28 +1956,12 @@ "dev": true, "license": "MIT" }, - "node_modules/@rushstack/node-core-library/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@rushstack/node-core-library/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -2033,13 +1969,6 @@ "node": ">=10" } }, - "node_modules/@rushstack/node-core-library/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, "node_modules/@rushstack/problem-matcher": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@rushstack/problem-matcher/-/problem-matcher-0.2.1.tgz", @@ -2056,24 +1985,24 @@ } }, "node_modules/@rushstack/rig-package": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.7.2.tgz", - "integrity": "sha512-9XbFWuqMYcHUso4mnETfhGVUSaADBRj6HUAAEYk50nMPn8WRICmBuCphycQGNB3duIR6EEZX3Xj3SYc2XiP+9A==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.7.3.tgz", + "integrity": "sha512-aAA518n6wxxjCfnTAOjQnm7ngNE0FVHxHAw2pxKlIhxrMn0XQjGcXKF0oKWpjBgJOmsaJpVob/v+zr3zxgPWuA==", "dev": true, "license": "MIT", "dependencies": { - "resolve": "~1.22.1", - "strip-json-comments": "~3.1.1" + "jju": "~1.4.0", + "resolve": "~1.22.1" } }, "node_modules/@rushstack/terminal": { - "version": "0.22.5", - "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.22.5.tgz", - "integrity": "sha512-umej8J6A+WRbfQV1G/uNfnz4bMa8CzFU9IJzQb/ZcH4j7Ybg3BQ8UBKOCF3o5U3/2yah1TDU/zE71ugg2JJv+Q==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.24.0.tgz", + "integrity": "sha512-8ZQS4MMaGsv27EXCBiH7WMPkRZrffeDoIevs6z9TM5dzqiY6+Hn4evfK/G+gvgBTjfvfkHIZPQQmalmI2sM4TQ==", "dev": true, "license": "MIT", "dependencies": { - "@rushstack/node-core-library": "5.22.0", + "@rushstack/node-core-library": "5.23.1", "@rushstack/problem-matcher": "0.2.1", "supports-color": "~8.1.1" }, @@ -2086,14 +2015,30 @@ } } }, + "node_modules/@rushstack/terminal/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/@rushstack/ts-command-line": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-5.3.5.tgz", - "integrity": "sha512-ToJQu3+o6aEdDoApGrwb/RsbwDi/NSC7jIEaAezzWM470TRrsXfSHoYAm1eWkhh34xJ+kZxU1ZzKSHiOMlOFPA==", + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-5.3.9.tgz", + "integrity": "sha512-GIHqU+sRGQ3LGWAZu1O+9Yh++qwtyNIIGuNbcWHJjBTm2qRez0cwINUHZ+pQLR8UuzZDcMajrDaNbUYoaL/XtQ==", "dev": true, "license": "MIT", "dependencies": { - "@rushstack/terminal": "0.22.5", + "@rushstack/terminal": "0.24.0", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" @@ -2191,9 +2136,9 @@ } }, "node_modules/@tanstack/form-core": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@tanstack/form-core/-/form-core-1.29.0.tgz", - "integrity": "sha512-uyeKEdJBfbj0bkBSwvSYVRtWLOaXvfNX3CeVw1HqGOXVLxpBBGAqWdYLc+UoX/9xcoFwFXrjR9QqMPzvwm2yyQ==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/@tanstack/form-core/-/form-core-1.32.0.tgz", + "integrity": "sha512-Tn5VRDSjyqjmaet2tJMuEWDRFyrCaon03vxXPlSSaiSs6C/N7lCIwGCXJbZXEUq1kTj8jYN9qyXHbsz4LQHcow==", "license": "MIT", "dependencies": { "@tanstack/devtools-event-client": "^0.4.1", @@ -2235,9 +2180,9 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.99.0", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.99.0.tgz", - "integrity": "sha512-3Jv3WQG0BCcH7G+7lf/bP8QyBfJOXeY+T08Rin3GZ1bshvwlbPt7NrDHMEzGdKIOmOzvIQmxjk28YEQX60k7pQ==", + "version": "5.100.10", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.100.10.tgz", + "integrity": "sha512-8UR0yJR+GiQ40m3lPhUr0xbfAupe6GSQiksSBSa9SM2NjezFyxXCIA69/lz8cSoNKZLrw1/PktIyQBJcVeMi3w==", "license": "MIT", "funding": { "type": "github", @@ -2278,9 +2223,9 @@ } }, "node_modules/@tanstack/virtual-core": { - "version": "3.13.23", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.23.tgz", - "integrity": "sha512-zSz2Z2HNyLjCplANTDyl3BcdQJc2k1+yyFoKhNRmCr7V7dY8o8q5m8uFTI1/Pg1kL+Hgrz6u3Xo6eFUB7l66cg==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.14.0.tgz", + "integrity": "sha512-JLANqGy/D6k4Ujmh8Tr25lGimuOXNiaVyXaCAZS0W+1390sADdGnyUdSWNIfd49gebtIxGMij4IktRVzrdr12Q==", "license": "MIT", "funding": { "type": "github", @@ -2288,12 +2233,12 @@ } }, "node_modules/@tanstack/vue-form": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@tanstack/vue-form/-/vue-form-1.29.0.tgz", - "integrity": "sha512-BBZFPQ0vlBHE3vBAHt8XdyVSVOLzZ1tgyjb7InJ4tAz+Sb/ePtwwIGvSUv6duuA9Nuusu+BX2O7lu5g4cvfLvg==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/@tanstack/vue-form/-/vue-form-1.32.0.tgz", + "integrity": "sha512-1GR01rtX2DTG46dyMo0I63fLBoAA+m3CPUOx/2WH2lFN82dHEenWGRfoX5d7OtX31HKPG2+ElQ1InahThHb8Cw==", "license": "MIT", "dependencies": { - "@tanstack/form-core": "1.29.0", + "@tanstack/form-core": "1.32.0", "@tanstack/vue-store": "^0.9.1" }, "funding": { @@ -2305,13 +2250,13 @@ } }, "node_modules/@tanstack/vue-query": { - "version": "5.99.0", - "resolved": "https://registry.npmjs.org/@tanstack/vue-query/-/vue-query-5.99.0.tgz", - "integrity": "sha512-okrHNkouasL5cjo7O8hUxul22DiIL335KUQus/cfoAdCOUytF/OIv3BpNDevfqE6zHqqJ651Fb9OkUJPUCL0ZQ==", + "version": "5.100.10", + "resolved": "https://registry.npmjs.org/@tanstack/vue-query/-/vue-query-5.100.10.tgz", + "integrity": "sha512-S1aOmIPQNd5axR2Sw7H8d96EybY3kEZ396KA90e0SGLDYSfd2QgWi7+ItYXRGIDiSjOjlPUnthKDP0mDDBV8Kw==", "license": "MIT", "dependencies": { "@tanstack/match-sorter-utils": "^8.19.4", - "@tanstack/query-core": "5.99.0", + "@tanstack/query-core": "5.100.10", "@vue/devtools-api": "^6.6.3", "vue-demi": "^0.14.10" }, @@ -2441,12 +2386,12 @@ } }, "node_modules/@tanstack/vue-virtual": { - "version": "3.13.23", - "resolved": "https://registry.npmjs.org/@tanstack/vue-virtual/-/vue-virtual-3.13.23.tgz", - "integrity": "sha512-b5jPluAR6U3eOq6GWAYSpj3ugnAIZgGR0e6aGAgyRse0Yu6MVQQ0ZWm9SArSXWtageogn6bkVD8D//c4IjW3xQ==", + "version": "3.13.24", + "resolved": "https://registry.npmjs.org/@tanstack/vue-virtual/-/vue-virtual-3.13.24.tgz", + "integrity": "sha512-A0k2qF0zFSUStXSZkGXABouXr2Tw2Ztl/cVIYG9qy84uR8W7UNjAcX3DvzBS3YnDcwvLxab8v7dbmYBZ39itDA==", "license": "MIT", "dependencies": { - "@tanstack/virtual-core": "3.13.23" + "@tanstack/virtual-core": "3.14.0" }, "funding": { "type": "github", @@ -2488,16 +2433,10 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/esrecurse": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", - "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", - "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.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "license": "MIT" }, "node_modules/@types/fs-extra": { @@ -2534,15 +2473,21 @@ } }, "node_modules/@types/node": { - "version": "22.19.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", - "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", + "version": "22.19.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz", + "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==", "devOptional": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" } }, + "node_modules/@types/sortablejs": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.9.tgz", + "integrity": "sha512-7HP+rZGE2p886PKV9c9OJzLBI6BBJu1O7lJGYnPyG3fS4/duUCcngkNCjsLwIMV+WMqANe3tt4irrXHSIe68OQ==", + "license": "MIT" + }, "node_modules/@types/web-bluetooth": { "version": "0.0.21", "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", @@ -2567,16 +2512,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.2.tgz", - "integrity": "sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==", + "version": "8.59.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.3.tgz", + "integrity": "sha512-PwFvSKsXGShKGW6n5bZOhGHEcCZXM8HofLK9fNsEwZXzFRjoY+XT1Vsf1zgyXdwTr0ZYz1/2tkZ0DBTT9jZjhw==", "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.58.2", - "@typescript-eslint/type-utils": "8.58.2", - "@typescript-eslint/utils": "8.58.2", - "@typescript-eslint/visitor-keys": "8.58.2", + "@typescript-eslint/scope-manager": "8.59.3", + "@typescript-eslint/type-utils": "8.59.3", + "@typescript-eslint/utils": "8.59.3", + "@typescript-eslint/visitor-keys": "8.59.3", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -2589,7 +2534,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.58.2", + "@typescript-eslint/parser": "^8.59.3", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } @@ -2604,15 +2549,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.2.tgz", - "integrity": "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==", + "version": "8.59.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.3.tgz", + "integrity": "sha512-HPwA+hVkfcriajbNvTmZv4VRauibay+cWArYUYq7u7W7PmGShMxbPxLvrwDme55a6d5alG3nrYfhyJ/G28XlLg==", "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.58.2", - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/typescript-estree": "8.58.2", - "@typescript-eslint/visitor-keys": "8.58.2", + "@typescript-eslint/scope-manager": "8.59.3", + "@typescript-eslint/types": "8.59.3", + "@typescript-eslint/typescript-estree": "8.59.3", + "@typescript-eslint/visitor-keys": "8.59.3", "debug": "^4.4.3" }, "engines": { @@ -2628,13 +2573,13 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.2.tgz", - "integrity": "sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==", + "version": "8.59.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.3.tgz", + "integrity": "sha512-ECiUWa/KYRGDFUqTNehaRgzDshnJfkTABJxVemHk4ko22gcr0ukloKjWvyQ64g8YCV/UI47kN1dbmjf/GaQYng==", "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.58.2", - "@typescript-eslint/types": "^8.58.2", + "@typescript-eslint/tsconfig-utils": "^8.59.3", + "@typescript-eslint/types": "^8.59.3", "debug": "^4.4.3" }, "engines": { @@ -2649,13 +2594,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.2.tgz", - "integrity": "sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==", + "version": "8.59.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.3.tgz", + "integrity": "sha512-t2LvZnoEfzKtnPjgeEu41xw5gxq9mQVfYy4OoZ4Vlt0sk3JwxmhCca/AR7DwOiHrjWgjAj6as4AhRLKSDfvZIA==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/visitor-keys": "8.58.2" + "@typescript-eslint/types": "8.59.3", + "@typescript-eslint/visitor-keys": "8.59.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2666,9 +2611,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.2.tgz", - "integrity": "sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==", + "version": "8.59.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.3.tgz", + "integrity": "sha512-PcIJHjmaREXLgIAIzLnSY9VucEzz8FKXsRgFa1DmdGCK/5tJpW03TKJF01Q6VZd1lLdz2sIKPWaDUZN9dp//dw==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2682,14 +2627,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.2.tgz", - "integrity": "sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==", + "version": "8.59.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.3.tgz", + "integrity": "sha512-g71d8QD8UaiHGvrJwyIS1hCX5r63w6Jll+4VEYhEAHXTDIqX1JgxhTAbEHtKntL9kuc4jRo7/GWw5xfCepSccQ==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/typescript-estree": "8.58.2", - "@typescript-eslint/utils": "8.58.2", + "@typescript-eslint/types": "8.59.3", + "@typescript-eslint/typescript-estree": "8.59.3", + "@typescript-eslint/utils": "8.59.3", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -2706,9 +2651,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.2.tgz", - "integrity": "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==", + "version": "8.59.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.3.tgz", + "integrity": "sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2719,15 +2664,15 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.2.tgz", - "integrity": "sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==", + "version": "8.59.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.3.tgz", + "integrity": "sha512-CbRjVRAf7Lr9Kr8RopKcbY45p2VfmmHrm0ygOCYFi7oU8q19m0Fs/6iHS7kNOmwpp+ob07ZVcAqlxUod9lYdmg==", "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.58.2", - "@typescript-eslint/tsconfig-utils": "8.58.2", - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/visitor-keys": "8.58.2", + "@typescript-eslint/project-service": "8.59.3", + "@typescript-eslint/tsconfig-utils": "8.59.3", + "@typescript-eslint/types": "8.59.3", + "@typescript-eslint/visitor-keys": "8.59.3", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -2755,9 +2700,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -2782,15 +2727,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.2.tgz", - "integrity": "sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==", + "version": "8.59.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.3.tgz", + "integrity": "sha512-JAvT14goBzRzzzZyqq3P9BLArIxTtQURUtFgQ/V7FO+eU+Gg6ES+5ymOPP1wRxXcxAYeivCk4uS3jCKWI1K8Zg==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.58.2", - "@typescript-eslint/types": "8.58.2", - "@typescript-eslint/typescript-estree": "8.58.2" + "@typescript-eslint/scope-manager": "8.59.3", + "@typescript-eslint/types": "8.59.3", + "@typescript-eslint/typescript-estree": "8.59.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2805,12 +2750,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.2.tgz", - "integrity": "sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==", + "version": "8.59.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.3.tgz", + "integrity": "sha512-f1UQF7ggd42YiwI5wGrRaPsa+P0CINBlrkLPmGfpq/u/I/oVtecoEIfFR9ag/oa1sLOsRNZ6xehf6qMZhQGBDg==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.58.2", + "@typescript-eslint/types": "8.59.3", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -2850,16 +2795,16 @@ } }, "node_modules/@vitest/expect": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.4.tgz", - "integrity": "sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.7.tgz", + "integrity": "sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.4", - "@vitest/utils": "4.1.4", + "@vitest/spy": "4.1.7", + "@vitest/utils": "4.1.7", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" }, @@ -2868,13 +2813,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.4.tgz", - "integrity": "sha512-R9HTZBhW6yCSGbGQnDnH3QHfJxokKN4KB+Yvk9Q1le7eQNYwiCyKxmLmurSpFy6BzJanSLuEUDrD+j97Q+ZLPg==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.7.tgz", + "integrity": "sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.1.4", + "@vitest/spy": "4.1.7", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -2894,10 +2839,20 @@ } } }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/@vitest/pretty-format": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.4.tgz", - "integrity": "sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.7.tgz", + "integrity": "sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw==", "dev": true, "license": "MIT", "dependencies": { @@ -2908,13 +2863,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.4.tgz", - "integrity": "sha512-xTp7VZ5aXP5ZJrn15UtJUWlx6qXLnGtF6jNxHepdPHpMfz/aVPx+htHtgcAL2mDXJgKhpoo2e9/hVJsIeFbytQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.7.tgz", + "integrity": "sha512-BapjmAQ2aI78WdMEfeUWivnfVzB+VPGwWRQcJE0OUq7qEeEcBsCSf+0T5iREBNE5nBb4wA5Ya0W6IA+sghdEFw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.1.4", + "@vitest/utils": "4.1.7", "pathe": "^2.0.3" }, "funding": { @@ -2922,14 +2877,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.4.tgz", - "integrity": "sha512-MCjCFgaS8aZz+m5nTcEcgk/xhWv0rEH4Yl53PPlMXOZ1/Ka2VcZU6CJ+MgYCZbcJvzGhQRjVrGQNZqkGPttIKw==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.7.tgz", + "integrity": "sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.4", - "@vitest/utils": "4.1.4", + "@vitest/pretty-format": "4.1.7", + "@vitest/utils": "4.1.7", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -2938,9 +2893,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.4.tgz", - "integrity": "sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.7.tgz", + "integrity": "sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q==", "dev": true, "license": "MIT", "funding": { @@ -2948,13 +2903,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.4.tgz", - "integrity": "sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.7.tgz", + "integrity": "sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.4", + "@vitest/pretty-format": "4.1.7", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" }, @@ -2989,65 +2944,53 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.32", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.32.tgz", - "integrity": "sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==", + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.34.tgz", + "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.2", - "@vue/shared": "3.5.32", + "@babel/parser": "^7.29.3", + "@vue/shared": "3.5.34", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, - "node_modules/@vue/compiler-core/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "license": "MIT" - }, "node_modules/@vue/compiler-dom": { - "version": "3.5.32", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.32.tgz", - "integrity": "sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==", + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz", + "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==", "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.32", - "@vue/shared": "3.5.32" + "@vue/compiler-core": "3.5.34", + "@vue/shared": "3.5.34" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.32", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz", - "integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==", + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz", + "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.2", - "@vue/compiler-core": "3.5.32", - "@vue/compiler-dom": "3.5.32", - "@vue/compiler-ssr": "3.5.32", - "@vue/shared": "3.5.32", + "@babel/parser": "^7.29.3", + "@vue/compiler-core": "3.5.34", + "@vue/compiler-dom": "3.5.34", + "@vue/compiler-ssr": "3.5.34", + "@vue/shared": "3.5.34", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", - "postcss": "^8.5.8", + "postcss": "^8.5.14", "source-map-js": "^1.2.1" } }, - "node_modules/@vue/compiler-sfc/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "license": "MIT" - }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.32", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.32.tgz", - "integrity": "sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw==", + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz", + "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.32", - "@vue/shared": "3.5.32" + "@vue/compiler-dom": "3.5.34", + "@vue/shared": "3.5.34" } }, "node_modules/@vue/compiler-vue2": { @@ -3131,18 +3074,18 @@ } }, "node_modules/@vue/language-core": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.2.6.tgz", - "integrity": "sha512-xYYYX3/aVup576tP/23sEUpgiEnujrENaoNRbaozC1/MA9I6EGFQRJb4xrt/MmUCAGlxTKL2RmT8JLTPqagCkg==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.2.8.tgz", + "integrity": "sha512-9OiSPQFiAAWNVnXb0d2dcTmcKnFQamhuNES6ayyISrb/mwPWVgoGdAqSfCWqKhQpa3D5gDTcYD+w7ObiheZ81g==", "license": "MIT", "dependencies": { "@volar/language-core": "2.4.28", "@vue/compiler-dom": "^3.5.0", "@vue/shared": "^3.5.0", - "alien-signals": "^3.0.0", + "alien-signals": "^3.1.2", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1", - "picomatch": "^4.0.2" + "picomatch": "^4.0.4" } }, "node_modules/@vue/language-core/node_modules/picomatch": { @@ -3158,64 +3101,74 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.5.32", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.32.tgz", - "integrity": "sha512-/ORasxSGvZ6MN5gc+uE364SxFdJ0+WqVG0CENXaGW58TOCdrAW76WWaplDtECeS1qphvtBZtR+3/o1g1zL4xPQ==", + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.34.tgz", + "integrity": "sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==", "license": "MIT", "dependencies": { - "@vue/shared": "3.5.32" + "@vue/shared": "3.5.34" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.32", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.32.tgz", - "integrity": "sha512-pDrXCejn4UpFDFmMd27AcJEbHaLemaE5o4pbb7sLk79SRIhc6/t34BQA7SGNgYtbMnvbF/HHOftYBgFJtUoJUQ==", + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.34.tgz", + "integrity": "sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.32", - "@vue/shared": "3.5.32" + "@vue/reactivity": "3.5.34", + "@vue/shared": "3.5.34" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.32", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.32.tgz", - "integrity": "sha512-1CDVv7tv/IV13V8Nip1k/aaObVbWqRlVCVezTwx3K07p7Vxossp5JU1dcPNhJk3w347gonIUT9jQOGutyJrSVQ==", + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.34.tgz", + "integrity": "sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.32", - "@vue/runtime-core": "3.5.32", - "@vue/shared": "3.5.32", + "@vue/reactivity": "3.5.34", + "@vue/runtime-core": "3.5.34", + "@vue/shared": "3.5.34", "csstype": "^3.2.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.32", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.32.tgz", - "integrity": "sha512-IOjm2+JQwRFS7W28HNuJeXQle9KdZbODFY7hFGVtnnghF51ta20EWAZJHX+zLGtsHhaU6uC9BGPV52KVpYryMQ==", + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.34.tgz", + "integrity": "sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==", "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.32", - "@vue/shared": "3.5.32" + "@vue/compiler-ssr": "3.5.34", + "@vue/shared": "3.5.34" }, "peerDependencies": { - "vue": "3.5.32" + "vue": "3.5.34" } }, "node_modules/@vue/shared": { - "version": "3.5.32", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.32.tgz", - "integrity": "sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==", + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.34.tgz", + "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==", "license": "MIT" }, "node_modules/@vue/test-utils": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.6.tgz", - "integrity": "sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==", + "version": "2.4.10", + "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.10.tgz", + "integrity": "sha512-SmoZ5EA1kYiAFs9NkYdiFFQF+cSnUwnvlYEbY+DogWQZUiqOm/Y29eSbc5T6yi75SgSF9863SBeXniIEoPajCA==", "dev": true, "license": "MIT", "dependencies": { "js-beautify": "^1.14.9", - "vue-component-type-helpers": "^2.0.0" + "vue-component-type-helpers": "^3.0.0" + }, + "peerDependencies": { + "@vue/compiler-dom": "3.x", + "@vue/server-renderer": "3.x", + "vue": "3.x" + }, + "peerDependenciesMeta": { + "@vue/server-renderer": { + "optional": true + } } }, "node_modules/@vue/tsconfig": { @@ -3238,14 +3191,14 @@ } }, "node_modules/@vueuse/core": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.2.1.tgz", - "integrity": "sha512-3vwDzV+GDUNpdegRY6kzpLm4Igptq+GA0QkJ3W61Iv27YWwW/ufSlOfgQIpN6FZRMG0mkaz4gglJRtq5SeJyIQ==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.3.0.tgz", + "integrity": "sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==", "license": "MIT", "dependencies": { "@types/web-bluetooth": "^0.0.21", - "@vueuse/metadata": "14.2.1", - "@vueuse/shared": "14.2.1" + "@vueuse/metadata": "14.3.0", + "@vueuse/shared": "14.3.0" }, "funding": { "url": "https://github.com/sponsors/antfu" @@ -3255,13 +3208,13 @@ } }, "node_modules/@vueuse/integrations": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-14.2.1.tgz", - "integrity": "sha512-2LIUpBi/67PoXJGqSDQUF0pgQWpNHh7beiA+KG2AbybcNm+pTGWT6oPGlBgUoDWmYwfeQqM/uzOHqcILpKL7nA==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-14.3.0.tgz", + "integrity": "sha512-76I5FT2ESvCmCaSwapI+a/u/CFtNXmzl9f9lNp1hRtx8vKB8hfiokJr8IvQqcQG5ckGXElyXK516b54ozV3MvA==", "license": "MIT", "dependencies": { - "@vueuse/core": "14.2.1", - "@vueuse/shared": "14.2.1" + "@vueuse/core": "14.3.0", + "@vueuse/shared": "14.3.0" }, "funding": { "url": "https://github.com/sponsors/antfu" @@ -3321,18 +3274,18 @@ } }, "node_modules/@vueuse/metadata": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.2.1.tgz", - "integrity": "sha512-1ButlVtj5Sb/HDtIy1HFr1VqCP4G6Ypqt5MAo0lCgjokrk2mvQKsK2uuy0vqu/Ks+sHfuHo0B9Y9jn9xKdjZsw==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.3.0.tgz", + "integrity": "sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/shared": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.2.1.tgz", - "integrity": "sha512-shTJncjV9JTI4oVNyF1FQonetYAiTBd+Qj7cY89SWbXSkx7gyhrgtEdF2ZAVWS1S3SHlaROO6F2IesJxQEkZBw==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.3.0.tgz", + "integrity": "sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/antfu" @@ -3383,9 +3336,9 @@ } }, "node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -3417,9 +3370,9 @@ } }, "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", "dependencies": { @@ -3460,13 +3413,15 @@ } }, "node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=12" + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" @@ -3501,7 +3456,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, "license": "Python-2.0" }, "node_modules/aria-hidden": { @@ -3570,12 +3524,12 @@ } }, "node_modules/axios": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz", - "integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.0.tgz", + "integrity": "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.11", + "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "proxy-from-env": "^2.1.0" } @@ -3584,13 +3538,12 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.10.18", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.18.tgz", - "integrity": "sha512-VSnGQAOLtP5mib/DPyg2/t+Tlv65NTBz83BJBJvmLVHHuKJVaDOBvJJykiT5TR++em5nfAySPccDZDa4oSrn8A==", + "version": "2.10.29", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz", + "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3632,7 +3585,6 @@ "version": "1.1.14", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -3736,7 +3688,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -3752,9 +3703,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001788", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001788.tgz", - "integrity": "sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==", + "version": "1.0.30001792", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz", + "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==", "dev": true, "funding": [ { @@ -3782,6 +3733,23 @@ "node": ">=18" } }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -3819,9 +3787,9 @@ } }, "node_modules/chroma-js": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-3.1.2.tgz", - "integrity": "sha512-IJnETTalXbsLx1eKEgx19d5L6SRM7cH4vINw/99p/M11HCuXGRWL+6YmCm7FWFGIo6dtWuQoQi1dc5yQ7ESIHg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-3.2.0.tgz", + "integrity": "sha512-os/OippSlX1RlWWr+QDPcGUZs0uoqr32urfxESG9U93lhUfbnlyckte84Q8P1UQY/qth983AS1JONKmLS4T0nw==", "license": "(BSD-3-Clause AND Apache-2.0)" }, "node_modules/class-variance-authority": { @@ -3849,7 +3817,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -3862,7 +3829,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/combined-stream": { @@ -3878,13 +3844,12 @@ } }, "node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "license": "MIT", "engines": { - "node": ">=14" + "node": ">= 6" } }, "node_modules/compare-versions": { @@ -3898,7 +3863,6 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, "license": "MIT" }, "node_modules/confbox": { @@ -4107,6 +4071,16 @@ "balanced-match": "^1.0.0" } }, + "node_modules/editorconfig/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/editorconfig/node_modules/minimatch": { "version": "9.0.9", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", @@ -4124,9 +4098,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.336", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.336.tgz", - "integrity": "sha512-AbH9q9J455r/nLmdNZes0G0ZKcRX73FicwowalLs6ijwOmCJSRRrLX63lcAlzy9ux3dWK1w1+1nsBJEWN11hcQ==", + "version": "1.5.353", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.353.tgz", + "integrity": "sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w==", "dev": true, "license": "ISC" }, @@ -4168,9 +4142,9 @@ } }, "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "dev": true, "license": "MIT" }, @@ -4266,30 +4240,33 @@ } }, "node_modules/eslint": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.0.tgz", - "integrity": "sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "license": "MIT", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.2", - "@eslint/config-array": "^0.23.4", - "@eslint/config-helpers": "^0.5.4", - "@eslint/core": "^1.2.0", - "@eslint/plugin-kit": "^0.7.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", + "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^9.1.2", - "eslint-visitor-keys": "^5.0.1", - "espree": "^11.2.0", - "esquery": "^1.7.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", @@ -4299,7 +4276,8 @@ "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "minimatch": "^10.2.4", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -4307,7 +4285,7 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://eslint.org/donate" @@ -4383,9 +4361,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "10.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.8.0.tgz", - "integrity": "sha512-f1J/tcbnrpgC8suPN5AtdJ5MQjuXbSU9pGRSSYAuF3SHoiYCOdEX6O22pLaRyLHXvDcOe+O5ENgc1owQ587agA==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.9.1.tgz", + "integrity": "sha512-cHB0Tf4Duvzwecwd/AqWzZvF/QszE13BhjVUpVXWCy9AeMR5GjkAjP3i85vqgLgOuTmkHR1OJ5oMeqLHtuw8zg==", "license": "MIT", "peer": true, "dependencies": { @@ -4403,7 +4381,7 @@ "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "vue-eslint-parser": "^10.0.0" + "vue-eslint-parser": "^10.3.0" }, "peerDependenciesMeta": { "@stylistic/eslint-plugin": { @@ -4429,18 +4407,16 @@ } }, "node_modules/eslint-scope": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", - "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "license": "BSD-2-Clause", "dependencies": { - "@types/esrecurse": "^4.3.1", - "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4458,76 +4434,19 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "license": "MIT", - "peer": true, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "license": "Apache-2.0", "peer": true, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/espree": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", - "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "acorn": "^8.16.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^5.0.1" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "license": "BlueOak-1.0.0", - "peer": true, - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -4591,14 +4510,10 @@ } }, "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" }, "node_modules/esutils": { "version": "2.0.3", @@ -4688,9 +4603,9 @@ "peer": true }, "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "dev": true, "funding": [ { @@ -4777,9 +4692,9 @@ "peer": true }, "node_modules/focus-trap": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-8.0.1.tgz", - "integrity": "sha512-9ptSG6z51YQOstI/oN4XuVGP/03u2nh0g//qz7L6zX0i6PZiPnkcf3GenXq7N2hZnASXaMxTPpbKwdI+PFvxlw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-8.2.0.tgz", + "integrity": "sha512-CaBdQ9P4fa/yCA6pDf/3aJd8bf9IOG5QGK21/E+86o2V4V8kzXaR4A9E6tNR7KkkS1+T5ZIU1tJDBDLwsucz9g==", "license": "MIT", "dependencies": { "tabbable": "^6.4.0" @@ -5001,7 +4916,6 @@ "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -5073,7 +4987,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5107,9 +5020,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -5147,7 +5060,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -5200,12 +5112,12 @@ } }, "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "hasown": "^2.0.3" }, "engines": { "node": ">= 0.4" @@ -5327,13 +5239,13 @@ } }, "node_modules/js-cookie": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.7.tgz", + "integrity": "sha512-z/wZZgDrkNV1eA0ULjM/F9/50Ya8fbzgKneSpoPsXSGd0KnpdtHfOZWK+GcwLk+EZbS4F9RBhU+K2RgzuDaItw==", "dev": true, "license": "MIT", "engines": { - "node": ">=14" + "node": ">=20" } }, "node_modules/js-tokens": { @@ -5347,7 +5259,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -5403,9 +5314,9 @@ } }, "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", "dev": true, "license": "MIT", "dependencies": { @@ -5529,13 +5440,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", - "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash-es": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", @@ -5543,6 +5447,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "license": "MIT", + "peer": true + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -5554,10 +5465,12 @@ } }, "node_modules/lucide-vue-next": { - "version": "0.487.0", - "resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-0.487.0.tgz", - "integrity": "sha512-ilVgu9EHkfId7WSjmoPkzp13cuzpSGO5J16AmltjRHFoj6MlCBGY8BzsBU/ISKVlDheUxM+MsIYjNo/1hSEa6w==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-1.0.0.tgz", + "integrity": "sha512-V6SPvx1IHTj/UY+FrIYWV5faISsPSb8BnWSFDxAtezWKvWc9ZZ40PDrdu1/Qb5vg4lHWr1hs1BAMGVGm6V1Xdg==", + "deprecated": "Package deprecated. Please use @lucide/vue instead.", "license": "ISC", + "peer": true, "peerDependencies": { "vue": ">=3.0.1" } @@ -5637,7 +5550,6 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -5728,9 +5640,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "funding": [ { "type": "github", @@ -5759,9 +5671,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.37", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz", - "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==", + "version": "2.0.44", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", + "integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==", "dev": true, "license": "MIT" }, @@ -6001,7 +5913,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -6177,25 +6088,25 @@ } }, "node_modules/pkg-types": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", - "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.1.tgz", + "integrity": "sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==", "dev": true, "license": "MIT", "dependencies": { - "confbox": "^0.2.2", - "exsolve": "^1.0.7", + "confbox": "^0.2.4", + "exsolve": "^1.0.8", "pathe": "^2.0.3" } }, "node_modules/playwright": { - "version": "1.59.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz", - "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==", + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz", + "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.59.1" + "playwright-core": "1.60.0" }, "bin": { "playwright": "cli.js" @@ -6208,9 +6119,9 @@ } }, "node_modules/playwright-core": { - "version": "1.59.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz", - "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==", + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz", + "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -6221,9 +6132,9 @@ } }, "node_modules/postcss": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", - "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", "funding": [ { "type": "opencollective", @@ -6489,9 +6400,9 @@ } }, "node_modules/prettier": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.2.tgz", - "integrity": "sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "license": "MIT", "peer": true, "bin": { @@ -6711,9 +6622,9 @@ } }, "node_modules/radix-vue/node_modules/nanoid": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.7.tgz", - "integrity": "sha512-ua3NDgISf6jdwezAheMOk4mbE1LXjm1DfMUDMuJf4AqxLFK3ccGpgWizwa5YV7Yz9EpXwEaWoRXSb/BnV0t5dQ==", + "version": "5.1.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.11.tgz", + "integrity": "sha512-v+KEsUv2ps74PaSKv0gHTxTCgMXOIfBEbaqa6w6ISIGC7ZsvHN4N9oJ8d4cmf0n5oTzQz2SLmThbQWhjd/8eKg==", "funding": [ { "type": "github", @@ -6750,9 +6661,9 @@ } }, "node_modules/reka-ui": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.8.2.tgz", - "integrity": "sha512-8lTKcJhmG+D3UyJxhBnNnW/720sLzm0pbA9AC1MWazmJ5YchJAyTSl+O00xP/kxBmEN0fw5JqWVHguiFmsGjzA==", + "version": "2.9.7", + "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.9.7.tgz", + "integrity": "sha512-aX7foYYR20v4+majO58OJJdBNfLMm0eJb448l9N4JVy8JB7GXOr4H/S4a+J1pkcoxZH8Cb7YHpJ855+miAm7sA==", "license": "MIT", "dependencies": { "@floating-ui/dom": "^1.6.13", @@ -6763,7 +6674,7 @@ "@vueuse/core": "^14.1.0", "@vueuse/shared": "^14.1.0", "aria-hidden": "^1.2.4", - "defu": "^6.1.4", + "defu": "^6.1.5", "ohash": "^2.0.11" }, "funding": { @@ -6771,7 +6682,7 @@ "url": "https://github.com/sponsors/zernonia" }, "peerDependencies": { - "vue": ">= 3.2.0" + "vue": ">= 3.4.0" } }, "node_modules/remove-accents": { @@ -6815,7 +6726,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -6838,9 +6748,9 @@ "license": "MIT" }, "node_modules/rollup": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", - "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.3.tgz", + "integrity": "sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==", "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -6853,34 +6763,40 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.1", - "@rollup/rollup-android-arm64": "4.60.1", - "@rollup/rollup-darwin-arm64": "4.60.1", - "@rollup/rollup-darwin-x64": "4.60.1", - "@rollup/rollup-freebsd-arm64": "4.60.1", - "@rollup/rollup-freebsd-x64": "4.60.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", - "@rollup/rollup-linux-arm-musleabihf": "4.60.1", - "@rollup/rollup-linux-arm64-gnu": "4.60.1", - "@rollup/rollup-linux-arm64-musl": "4.60.1", - "@rollup/rollup-linux-loong64-gnu": "4.60.1", - "@rollup/rollup-linux-loong64-musl": "4.60.1", - "@rollup/rollup-linux-ppc64-gnu": "4.60.1", - "@rollup/rollup-linux-ppc64-musl": "4.60.1", - "@rollup/rollup-linux-riscv64-gnu": "4.60.1", - "@rollup/rollup-linux-riscv64-musl": "4.60.1", - "@rollup/rollup-linux-s390x-gnu": "4.60.1", - "@rollup/rollup-linux-x64-gnu": "4.60.1", - "@rollup/rollup-linux-x64-musl": "4.60.1", - "@rollup/rollup-openbsd-x64": "4.60.1", - "@rollup/rollup-openharmony-arm64": "4.60.1", - "@rollup/rollup-win32-arm64-msvc": "4.60.1", - "@rollup/rollup-win32-ia32-msvc": "4.60.1", - "@rollup/rollup-win32-x64-gnu": "4.60.1", - "@rollup/rollup-win32-x64-msvc": "4.60.1", + "@rollup/rollup-android-arm-eabi": "4.60.3", + "@rollup/rollup-android-arm64": "4.60.3", + "@rollup/rollup-darwin-arm64": "4.60.3", + "@rollup/rollup-darwin-x64": "4.60.3", + "@rollup/rollup-freebsd-arm64": "4.60.3", + "@rollup/rollup-freebsd-x64": "4.60.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.3", + "@rollup/rollup-linux-arm-musleabihf": "4.60.3", + "@rollup/rollup-linux-arm64-gnu": "4.60.3", + "@rollup/rollup-linux-arm64-musl": "4.60.3", + "@rollup/rollup-linux-loong64-gnu": "4.60.3", + "@rollup/rollup-linux-loong64-musl": "4.60.3", + "@rollup/rollup-linux-ppc64-gnu": "4.60.3", + "@rollup/rollup-linux-ppc64-musl": "4.60.3", + "@rollup/rollup-linux-riscv64-gnu": "4.60.3", + "@rollup/rollup-linux-riscv64-musl": "4.60.3", + "@rollup/rollup-linux-s390x-gnu": "4.60.3", + "@rollup/rollup-linux-x64-gnu": "4.60.3", + "@rollup/rollup-linux-x64-musl": "4.60.3", + "@rollup/rollup-openbsd-x64": "4.60.3", + "@rollup/rollup-openharmony-arm64": "4.60.3", + "@rollup/rollup-win32-arm64-msvc": "4.60.3", + "@rollup/rollup-win32-ia32-msvc": "4.60.3", + "@rollup/rollup-win32-x64-gnu": "4.60.3", + "@rollup/rollup-win32-x64-msvc": "4.60.3", "fsevents": "~2.3.2" } }, + "node_modules/rollup/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==", + "license": "MIT" + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -6905,9 +6821,9 @@ } }, "node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -7076,9 +6992,9 @@ "license": "MIT" }, "node_modules/std-env": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", - "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", + "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", "dev": true, "license": "MIT" }, @@ -7200,7 +7116,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -7231,15 +7146,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/sucrase/node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/superjson": { "version": "2.2.6", "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", @@ -7253,19 +7159,16 @@ } }, "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "license": "MIT", + "peer": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -7438,9 +7341,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", - "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.2.tgz", + "integrity": "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==", "dev": true, "license": "MIT", "engines": { @@ -7592,15 +7495,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.58.2", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.58.2.tgz", - "integrity": "sha512-V8iSng9mRbdZjl54VJ9NKr6ZB+dW0J3TzRXRGcSbLIej9jV86ZRtlYeTKDR/QLxXykocJ5icNzbsl2+5TzIvcQ==", + "version": "8.59.3", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.3.tgz", + "integrity": "sha512-KgusgyDgG4LI8Ih/sWaCtZ06tckLAS5CvT5A4D1Q7bYVoAAyzwiZvE4BmwDHkhRVkvhRBepKeASoFzQetha7Fg==", "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.58.2", - "@typescript-eslint/parser": "8.58.2", - "@typescript-eslint/typescript-estree": "8.58.2", - "@typescript-eslint/utils": "8.58.2" + "@typescript-eslint/eslint-plugin": "8.59.3", + "@typescript-eslint/parser": "8.59.3", + "@typescript-eslint/typescript-estree": "8.59.3", + "@typescript-eslint/utils": "8.59.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7615,9 +7518,9 @@ } }, "node_modules/ufo": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", - "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", "dev": true, "license": "MIT" }, @@ -7712,9 +7615,9 @@ "license": "MIT" }, "node_modules/vite": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", - "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.3.tgz", + "integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==", "license": "MIT", "dependencies": { "esbuild": "^0.27.0", @@ -8033,19 +7936,19 @@ } }, "node_modules/vitest": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.4.tgz", - "integrity": "sha512-tFuJqTxKb8AvfyqMfnavXdzfy3h3sWZRWwfluGbkeR7n0HUev+FmNgZ8SDrRBTVrVCjgH5cA21qGbCffMNtWvg==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.7.tgz", + "integrity": "sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.1.4", - "@vitest/mocker": "4.1.4", - "@vitest/pretty-format": "4.1.4", - "@vitest/runner": "4.1.4", - "@vitest/snapshot": "4.1.4", - "@vitest/spy": "4.1.4", - "@vitest/utils": "4.1.4", + "@vitest/expect": "4.1.7", + "@vitest/mocker": "4.1.7", + "@vitest/pretty-format": "4.1.7", + "@vitest/runner": "4.1.7", + "@vitest/snapshot": "4.1.7", + "@vitest/spy": "4.1.7", + "@vitest/utils": "4.1.7", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", @@ -8073,12 +7976,12 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.4", - "@vitest/browser-preview": "4.1.4", - "@vitest/browser-webdriverio": "4.1.4", - "@vitest/coverage-istanbul": "4.1.4", - "@vitest/coverage-v8": "4.1.4", - "@vitest/ui": "4.1.4", + "@vitest/browser-playwright": "4.1.7", + "@vitest/browser-preview": "4.1.7", + "@vitest/browser-webdriverio": "4.1.7", + "@vitest/coverage-istanbul": "4.1.7", + "@vitest/coverage-v8": "4.1.7", + "@vitest/ui": "4.1.7", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -8142,16 +8045,16 @@ "license": "MIT" }, "node_modules/vue": { - "version": "3.5.32", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.32.tgz", - "integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==", + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.34.tgz", + "integrity": "sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.32", - "@vue/compiler-sfc": "3.5.32", - "@vue/runtime-dom": "3.5.32", - "@vue/server-renderer": "3.5.32", - "@vue/shared": "3.5.32" + "@vue/compiler-dom": "3.5.34", + "@vue/compiler-sfc": "3.5.34", + "@vue/runtime-dom": "3.5.34", + "@vue/server-renderer": "3.5.34", + "@vue/shared": "3.5.34" }, "peerDependencies": { "typescript": "*" @@ -8163,12 +8066,29 @@ } }, "node_modules/vue-component-type-helpers": { - "version": "2.2.12", - "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-2.2.12.tgz", - "integrity": "sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-3.3.1.tgz", + "integrity": "sha512-pu58kqxmVyEH6VfNYW1UyEfR3XAnJ27ZXT3yzXxxpjLxVzAbyC35Zk/nm/RMs7ijWnJNSd9fWkeex2OhUsx3MA==", "dev": true, "license": "MIT" }, + "node_modules/vue-draggable-plus": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/vue-draggable-plus/-/vue-draggable-plus-0.6.1.tgz", + "integrity": "sha512-FbtQ/fuoixiOfTZzG3yoPl4JAo9HJXRHmBQZFB9x2NYCh6pq0TomHf7g5MUmpaDYv+LU2n6BPq2YN9sBO+FbIg==", + "license": "MIT", + "dependencies": { + "@types/sortablejs": "^1.15.8" + }, + "peerDependencies": { + "@types/sortablejs": "^1.15.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/vue-echarts": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/vue-echarts/-/vue-echarts-8.0.1.tgz", @@ -8203,25 +8123,25 @@ } }, "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "license": "Apache-2.0", "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/vue-tsc": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.2.6.tgz", - "integrity": "sha512-gYW/kWI0XrwGzd0PKc7tVB/qpdeAkIZLNZb10/InizkQjHjnT8weZ/vBarZoj4kHKbUTZT/bAVgoOr8x4NsQ/Q==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.2.8.tgz", + "integrity": "sha512-27vTLJ6Q2370obOd0PFYoYoKnmXJ521uUIedrs3Zhhhg/8YG10VOCMmwt+JQslatpAMTDbnWiitLnoD5VlIvog==", "license": "MIT", "dependencies": { "@volar/typescript": "2.4.28", - "@vue/language-core": "3.2.6" + "@vue/language-core": "3.2.8" }, "bin": { "vue-tsc": "bin/vue-tsc.js" @@ -8350,22 +8270,6 @@ "node": ">=8" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -8401,10 +8305,23 @@ "node": ">=8" } }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/ws": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", - "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "dev": true, "license": "MIT", "engines": { @@ -8441,9 +8358,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", - "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", "devOptional": true, "license": "ISC", "bin": { diff --git a/package.json b/package.json index d049f966d..d6c4154d6 100644 --- a/package.json +++ b/package.json @@ -25,64 +25,65 @@ "watch:api": "npm run watch --workspace=@solidtime/api" }, "devDependencies": { - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "^9.19.0", - "@inertiajs/vue3": "^2.0.0", - "@playwright/test": "^1.41.1", - "@tailwindcss/forms": "^0.5.9", - "@tailwindcss/typography": "^0.5.15", - "@types/chroma-js": "^3.1.0", - "@types/node": "^22.10.10", - "@vitejs/plugin-vue": "^6.0.3", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "^9.39.4", + "@inertiajs/vue3": "^2.3.23", + "@playwright/test": "^1.60.0", + "@tailwindcss/forms": "^0.5.11", + "@tailwindcss/typography": "^0.5.19", + "@types/chroma-js": "^3.1.2", + "@types/node": "^22.19.19", + "@vitejs/plugin-vue": "^6.0.6", "@vue/test-utils": "^2.4.6", - "@vue/tsconfig": "^0.8.0", - "autoprefixer": "^10.4.20", - "axios": "^1.6.4", - "eslint-plugin-unused-imports": "^4.1.4", + "@vue/tsconfig": "^0.8.1", + "autoprefixer": "^10.5.0", + "axios": "^1.16.0", + "eslint-plugin-unused-imports": "^4.4.1", "happy-dom": "^20.8.9", "laravel-vite-plugin": "^2.1.0", - "openapi-zod-client": "^1.16.2", - "postcss": "^8.4.47", + "openapi-zod-client": "^1.18.3", + "postcss": "^8.5.14", "postcss-import": "^15.1.0", "postcss-nesting": "^12.1.5", - "tailwindcss": "^3.4.13", - "typescript": "^5.7.3", - "vite": "^7.0.0", + "tailwindcss": "^3.4.19", + "typescript": "^5.9.3", + "vite": "^7.3.3", "vite-plugin-checker": "^0.12.0", "vitest": "^4.1.4", - "vue": "^3.5.0", - "vue-tsc": "^3.0.0" + "vue": "^3.5.34", + "vue-tsc": "^3.2.8" }, "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/vue": "^1.0.6", - "@heroicons/vue": "^2.1.1", - "@rushstack/eslint-patch": "^1.10.5", + "@floating-ui/core": "^1.7.5", + "@floating-ui/vue": "^1.1.11", + "@heroicons/vue": "^2.2.0", + "@lucide/vue": "^1.14.0", + "@rushstack/eslint-patch": "^1.16.1", "@tailwindcss/container-queries": "^0.1.1", - "@tanstack/vue-form": "^1.3.1", - "@tanstack/vue-query": "^5.56.2", - "@tanstack/vue-query-devtools": "^5.58.0", - "@tanstack/vue-table": "^8.21.2", + "@tanstack/vue-form": "^1.32.0", + "@tanstack/vue-query": "^5.100.10", + "@tanstack/vue-query-devtools": "^5.91.0", + "@tanstack/vue-table": "^8.21.3", "@vue/eslint-config-prettier": "^10.2.0", - "@vue/eslint-config-typescript": "^14.3.0", - "@vueuse/core": "^14.2.1", - "@vueuse/integrations": "^14.0.0", + "@vue/eslint-config-typescript": "^14.7.0", + "@vueuse/core": "^14.3.0", + "@vueuse/integrations": "^14.3.0", "@zodios/core": "^10.9.6", - "chroma-js": "3.1.2", + "chroma-js": "^3.2.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "dayjs": "^1.11.11", + "dayjs": "^1.11.20", "echarts": "^6.0.0", - "focus-trap": "^8.0.0", - "lucide-vue-next": "^0.487.0", - "parse-duration": "^2.0.1", - "pinia": "^3.0.0", - "radix-vue": "^1.9.6", - "reka-ui": "2.8.2", - "tailwind-merge": "^2.6.0", + "focus-trap": "^8.2.0", + "parse-duration": "^2.1.6", + "pinia": "^3.0.4", + "radix-vue": "^1.9.17", + "reka-ui": "^2.9.7", + "tailwind-merge": "^2.6.1", "tailwindcss-animate": "^1.0.7", - "vue-echarts": "^8.0.0", - "zod": "^3.23.8" + "vue-draggable-plus": "^0.6.1", + "vue-echarts": "^8.0.1", + "zod": "^3.25.76" }, "overrides": { "vite-plugin-checker": { diff --git a/phpstan.neon b/phpstan.neon index 147234996..4e9d0084b 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -14,5 +14,4 @@ parameters: noEnvCallsOutsideOfConfig: true ignoreErrors: - - '# is not subtype of native type Illuminate\\Database\\Eloquent\\Builder#' - '# is not subtype of native type Illuminate\\Database\\Eloquent\\Relations\\Relation#' diff --git a/playwright/fixtures.ts b/playwright/fixtures.ts index 877e7cf32..41695593c 100644 --- a/playwright/fixtures.ts +++ b/playwright/fixtures.ts @@ -32,6 +32,9 @@ export const test = baseTest.extend< const email = `john+${Date.now()}_${Math.floor(Math.random() * 10000)}@doe.com`; const password = TEST_USER_PASSWORD; const name = 'John Doe'; + const timezone = await page.evaluate( + () => Intl.DateTimeFormat().resolvedOptions().timeZone + ); // Use page.context().request() so cookies are automatically shared with the page const request = page.context().request; @@ -64,6 +67,7 @@ export const test = baseTest.extend< password, password_confirmation: password, terms: 'on', + timezone, }, maxRedirects: 0, }); diff --git a/resources/js/Components/Banner.vue b/resources/js/Components/Banner.vue index 475f0eaee..5f429dc42 100644 --- a/resources/js/Components/Banner.vue +++ b/resources/js/Components/Banner.vue @@ -1,36 +1,53 @@ + +
@@ -114,11 +114,7 @@ const page = usePage<{
diff --git a/resources/js/Pages/Profile/Partials/DeleteUserForm.vue b/resources/js/Pages/Profile/Partials/DeleteUserForm.vue index 187dc1b70..ae5cd48b0 100644 --- a/resources/js/Pages/Profile/Partials/DeleteUserForm.vue +++ b/resources/js/Pages/Profile/Partials/DeleteUserForm.vue @@ -1,40 +1,57 @@ @@ -84,8 +99,8 @@ const closeModal = () => { Delete Account diff --git a/resources/js/Pages/Profile/Partials/UpdateProfileInformationForm.vue b/resources/js/Pages/Profile/Partials/UpdateProfileInformationForm.vue index 695cb8e0f..e1957e078 100644 --- a/resources/js/Pages/Profile/Partials/UpdateProfileInformationForm.vue +++ b/resources/js/Pages/Profile/Partials/UpdateProfileInformationForm.vue @@ -1,93 +1,181 @@