diff --git a/.gitignore b/.gitignore index 4a6486d..3cfdc6d 100644 --- a/.gitignore +++ b/.gitignore @@ -413,5 +413,6 @@ appsettings.json # MacOs .DS_Store + #Claude CLAUDE.md diff --git a/backend/ECondo.Api/Controllers/PropertyController.cs b/backend/ECondo.Api/Controllers/PropertyController.cs index 511d3b1..aef3935 100644 --- a/backend/ECondo.Api/Controllers/PropertyController.cs +++ b/backend/ECondo.Api/Controllers/PropertyController.cs @@ -2,12 +2,11 @@ using ECondo.Application.Commands.Properties.Create; using ECondo.Application.Commands.Properties.Delete; using ECondo.Application.Commands.Properties.Update; -using ECondo.Application.Data; using ECondo.Application.Data.Property; using ECondo.Application.Queries.Properties.GetAll; using ECondo.Application.Queries.Properties.GetById; using ECondo.Application.Queries.Properties.GetForUser; -using ECondo.Application.Queries.Properties.GetInBuilding; +using ECondo.Application.Queries.Properties.GetInEntrance; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -19,15 +18,15 @@ namespace ECondo.Api.Controllers; public class PropertyController(ISender sender) : ControllerBase { [Authorize] - [HttpGet(nameof(GetPropertiesInBuilding))] + [HttpGet(nameof(GetPropertiesInEntrance))] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(PagedListResponse))] [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(HttpValidationProblemDetails))] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task - GetPropertiesInBuilding( - [FromQuery] GetPropertiesInBuildingQuery request) + GetPropertiesInEntrance( + [FromQuery] GetPropertiesInEntranceQuery request) { var result = await sender.Send(request); diff --git a/backend/ECondo.Api/Extensions/ApiErrorExtension.cs b/backend/ECondo.Api/Extensions/ApiErrorExtension.cs index c1c7976..391258d 100644 --- a/backend/ECondo.Api/Extensions/ApiErrorExtension.cs +++ b/backend/ECondo.Api/Extensions/ApiErrorExtension.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Http.HttpResults; using System.Diagnostics; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; namespace ECondo.Api.Extensions; public static class ApiErrorExtension diff --git a/backend/ECondo.Api/Extensions/CustomResults.cs b/backend/ECondo.Api/Extensions/CustomResults.cs index 5dfbade..144a19e 100644 --- a/backend/ECondo.Api/Extensions/CustomResults.cs +++ b/backend/ECondo.Api/Extensions/CustomResults.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; namespace ECondo.Api.Extensions; diff --git a/backend/ECondo.Api/Extensions/PagedListExtension.cs b/backend/ECondo.Api/Extensions/PagedListExtension.cs index add8b8a..0d5e84a 100644 --- a/backend/ECondo.Api/Extensions/PagedListExtension.cs +++ b/backend/ECondo.Api/Extensions/PagedListExtension.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Collections; namespace ECondo.Api.Extensions; diff --git a/backend/ECondo.Api/Extensions/ResultExtensions.cs b/backend/ECondo.Api/Extensions/ResultExtensions.cs index efb852f..8586df9 100644 --- a/backend/ECondo.Api/Extensions/ResultExtensions.cs +++ b/backend/ECondo.Api/Extensions/ResultExtensions.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; namespace ECondo.Api.Extensions; diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/AcceptPropertyInvitationCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/AcceptPropertyInvitationCommandHandlerTests.cs index d9b4a9b..510ebad 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/AcceptPropertyInvitationCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/AcceptPropertyInvitationCommandHandlerTests.cs @@ -1,15 +1,13 @@ using ECondo.Application.Commands.PropertyOccupants.AcceptInvitation; using ECondo.Application.Repositories; using ECondo.Application.Services; -using ECondo.Domain; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; using ECondo.Domain.Users; using ECondo.Infrastructure.Contexts; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NSubstitute; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.PropertyOccupants.AcceptInvitation; diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/AddOccupantToPropertyCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/AddOccupantToPropertyCommandHandlerTests.cs index 37e35a1..cb23597 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/AddOccupantToPropertyCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/AddOccupantToPropertyCommandHandlerTests.cs @@ -1,22 +1,18 @@ using ECondo.Application.Commands.PropertyOccupants.AddToProperty; -using ECondo.Application.Events.PropertyOccupant; using ECondo.Application.Repositories; -using ECondo.Domain; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; using ECondo.Infrastructure.Contexts; +using ECondo.SharedKernel.Result; using FluentAssertions; using MediatR; using Microsoft.EntityFrameworkCore; using NSubstitute; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.PropertyOccupants.AddToProperty; public class AddOccupantToPropertyCommandHandlerTests { private readonly IApplicationDbContext _dbContext; - private readonly IPublisher _publisher; private readonly AddOccupantToPropertyCommandHandler _handler; public AddOccupantToPropertyCommandHandlerTests() @@ -26,8 +22,8 @@ public AddOccupantToPropertyCommandHandlerTests() .Options; _dbContext = new ECondoDbContext(options); - _publisher = Substitute.For(); - _handler = new AddOccupantToPropertyCommandHandler(_dbContext, _publisher); + var publisher = Substitute.For(); + _handler = new AddOccupantToPropertyCommandHandler(_dbContext, publisher); } [Fact] diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/ConnectStripeAccountCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/ConnectStripeAccountCommandHandlerTests.cs index 88daaad..103a99d 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/ConnectStripeAccountCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/ConnectStripeAccountCommandHandlerTests.cs @@ -1,17 +1,16 @@ using ECondo.Application.Commands.Payment.ConnectStripeAccount; using ECondo.Application.Repositories; using ECondo.Application.Services; -using ECondo.Domain; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; using ECondo.Infrastructure.Contexts; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NSubstitute; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.Payment.ConnectStripeAccount; + public class ConnectStripeAccountCommandHandlerTests { private readonly IApplicationDbContext _dbContext; @@ -33,12 +32,11 @@ public ConnectStripeAccountCommandHandlerTests() public async Task Handle_ShouldConnectStripeAccount_WhenValid() { // Arrange - var buildingId = Guid.NewGuid(); + var entranceId = Guid.NewGuid(); var entrance = new Entrance { - Id = Guid.NewGuid(), - BuildingId = buildingId, - Number = "Entrance1" + Id = entranceId, + Number = "1", }; _dbContext.Entrances.Add(entrance); @@ -52,8 +50,7 @@ public async Task Handle_ShouldConnectStripeAccount_WhenValid() .Returns(onboardingLink); var command = new ConnectStripeAccountCommand( - buildingId, - "Entrance1", + entranceId, "https://example.com/return" ); @@ -74,12 +71,11 @@ public async Task Handle_ShouldConnectStripeAccount_WhenValid() public async Task Handle_ShouldUpdateDatabaseCorrectly_WhenStripeAccountConnected() { // Arrange - var buildingId = Guid.NewGuid(); + var entranceId = Guid.NewGuid(); var entrance = new Entrance { - Id = Guid.NewGuid(), - BuildingId = buildingId, - Number = "Entrance1" + Id = entranceId, + Number = "1", }; _dbContext.Entrances.Add(entrance); @@ -93,8 +89,7 @@ public async Task Handle_ShouldUpdateDatabaseCorrectly_WhenStripeAccountConnecte .Returns(onboardingLink); var command = new ConnectStripeAccountCommand( - buildingId, - "Entrance1", + entranceId, "https://example.com/return" ); diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreateBillCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreateBillCommandHandlerTests.cs index 8c21ef4..2601cd8 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreateBillCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreateBillCommandHandlerTests.cs @@ -1,15 +1,13 @@ using ECondo.Application.Commands.Payment.CreateBill; using ECondo.Application.Repositories; using ECondo.Application.Services; -using ECondo.Domain; using ECondo.Domain.Buildings; using ECondo.Domain.Payments; -using ECondo.Domain.Shared; using ECondo.Infrastructure.Contexts; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NSubstitute; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.Payment.CreateBill; @@ -34,11 +32,10 @@ public CreateBillCommandHandlerTests() public async Task Handle_ShouldCreateBill_WhenValid() { // Arrange - var buildingId = Guid.NewGuid(); var entrance = new Entrance { Id = Guid.NewGuid(), - BuildingId = buildingId, + BuildingId = Guid.NewGuid(), Number = "Entrance1" }; @@ -48,8 +45,7 @@ public async Task Handle_ShouldCreateBill_WhenValid() _userContext.UserId.Returns(Guid.NewGuid()); var command = new CreateBillCommand( - buildingId, - "Entrance1", + entrance.Id, "Test Bill", "Test Description", 100.0m, @@ -65,7 +61,9 @@ public async Task Handle_ShouldCreateBill_WhenValid() // Assert result.IsOk().Should().BeTrue(); - var createdBill = await _dbContext.Bills.FirstOrDefaultAsync(b => b.Title == "Test Bill"); + var createdBill = await _dbContext + .Bills + .FirstOrDefaultAsync(b => b.Title == "Test Bill"); createdBill.Should().NotBeNull(); createdBill!.Amount.Should().Be(100.0m); createdBill.IsRecurring.Should().BeFalse(); @@ -75,11 +73,10 @@ public async Task Handle_ShouldCreateBill_WhenValid() public async Task Handle_ShouldGeneratePayments_ForOneTimeBill() { // Arrange - var buildingId = Guid.NewGuid(); var entrance = new Entrance { Id = Guid.NewGuid(), - BuildingId = buildingId, + BuildingId = Guid.NewGuid(), Number = "Entrance1" }; @@ -105,8 +102,7 @@ public async Task Handle_ShouldGeneratePayments_ForOneTimeBill() _userContext.UserId.Returns(Guid.NewGuid()); var command = new CreateBillCommand( - buildingId, - "Entrance1", + entrance.Id, "One-Time Bill", "Test Description", 200.0m, @@ -122,7 +118,12 @@ public async Task Handle_ShouldGeneratePayments_ForOneTimeBill() // Assert result.IsOk().Should().BeTrue(); - var payments = await _dbContext.Payments.Where(p => p.BillId == result.ToSuccess().Data).ToListAsync(); + var payments = await _dbContext + .Payments + .Where(p => + p.BillId == result.ToSuccess().Data) + .ToListAsync(); + payments.Should().HaveCount(2); payments.All(p => p.AmountPaid == 100.0m).Should().BeTrue(); } @@ -131,11 +132,10 @@ public async Task Handle_ShouldGeneratePayments_ForOneTimeBill() public async Task Handle_ShouldNotGeneratePayments_ForRecurringBill() { // Arrange - var buildingId = Guid.NewGuid(); var entrance = new Entrance { Id = Guid.NewGuid(), - BuildingId = buildingId, + BuildingId = Guid.NewGuid(), Number = "Entrance1" }; @@ -145,8 +145,7 @@ public async Task Handle_ShouldNotGeneratePayments_ForRecurringBill() _userContext.UserId.Returns(Guid.NewGuid()); var command = new CreateBillCommand( - buildingId, - "Entrance1", + entrance.Id, "Recurring Bill", "Test Description", 300.0m, @@ -162,7 +161,11 @@ public async Task Handle_ShouldNotGeneratePayments_ForRecurringBill() // Assert result.IsOk().Should().BeTrue(); - var payments = await _dbContext.Payments.Where(p => p.BillId == result.ToSuccess().Data).ToListAsync(); + var payments = await _dbContext + .Payments + .Where(p => + p.BillId == result.ToSuccess().Data) + .ToListAsync(); payments.Should().BeEmpty(); } } diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreatePaymentIntentCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreatePaymentIntentCommandHandlerTests.cs index ddf2dfc..fb91298 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreatePaymentIntentCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreatePaymentIntentCommandHandlerTests.cs @@ -1,14 +1,12 @@ using ECondo.Application.Commands.Payment.CreateIntent; using ECondo.Application.Repositories; using ECondo.Application.Services; -using ECondo.Domain; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; using ECondo.Infrastructure.Contexts; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NSubstitute; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.Payment.CreateIntent; diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreateProfileCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreateProfileCommandHandlerTests.cs index ec7f5dd..997a741 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreateProfileCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreateProfileCommandHandlerTests.cs @@ -1,14 +1,12 @@ using ECondo.Application.Commands.Profiles.Create; using ECondo.Application.Repositories; using ECondo.Application.Services; -using ECondo.Domain.Profiles; -using ECondo.Domain.Shared; using ECondo.Domain.Users; using ECondo.Infrastructure.Contexts; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NSubstitute; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.Profiles.Create; diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreatePropertyCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreatePropertyCommandHandlerTests.cs index 4e96273..2f9a7a0 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreatePropertyCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/CreatePropertyCommandHandlerTests.cs @@ -1,12 +1,10 @@ using ECondo.Application.Commands.Properties.Create; using ECondo.Application.Repositories; -using ECondo.Domain; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; using ECondo.Infrastructure.Contexts; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.EntityFrameworkCore; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.Properties.Create; @@ -29,11 +27,10 @@ public CreatePropertyCommandHandlerTests() public async Task Handle_ShouldCreateProperty_WhenEntranceAndPropertyTypeAreValid() { // Arrange - var buildingId = Guid.NewGuid(); var entrance = new Entrance { Id = Guid.NewGuid(), - BuildingId = buildingId, + BuildingId = Guid.NewGuid(), Number = "Entrance1" }; @@ -48,8 +45,7 @@ public async Task Handle_ShouldCreateProperty_WhenEntranceAndPropertyTypeAreVali await _dbContext.SaveChangesAsync(); var command = new CreatePropertyCommand( - buildingId, - "Entrance1", + entrance.Id, "Apartment", "2", "202", @@ -78,7 +74,6 @@ public async Task Handle_ShouldReturnError_WhenEntranceDoesNotExist() // Arrange var command = new CreatePropertyCommand( Guid.NewGuid(), - "NonExistentEntrance", "Apartment", "2", "202", @@ -98,11 +93,10 @@ public async Task Handle_ShouldReturnError_WhenEntranceDoesNotExist() public async Task Handle_ShouldReturnError_WhenPropertyTypeDoesNotExist() { // Arrange - var buildingId = Guid.NewGuid(); var entrance = new Entrance { Id = Guid.NewGuid(), - BuildingId = buildingId, + BuildingId = Guid.NewGuid(), Number = "Entrance1" }; @@ -110,8 +104,7 @@ public async Task Handle_ShouldReturnError_WhenPropertyTypeDoesNotExist() await _dbContext.SaveChangesAsync(); var command = new CreatePropertyCommand( - buildingId, - "Entrance1", + entrance.Id, "NonExistentType", "2", "202", @@ -131,11 +124,10 @@ public async Task Handle_ShouldReturnError_WhenPropertyTypeDoesNotExist() public async Task Handle_ShouldReturnError_WhenPropertyAlreadyExists() { // Arrange - var buildingId = Guid.NewGuid(); var entrance = new Entrance { Id = Guid.NewGuid(), - BuildingId = buildingId, + BuildingId = Guid.NewGuid(), Number = "Entrance1" }; @@ -161,8 +153,7 @@ public async Task Handle_ShouldReturnError_WhenPropertyAlreadyExists() await _dbContext.SaveChangesAsync(); var command = new CreatePropertyCommand( - buildingId, - "Entrance1", + entrance.Id, "Apartment", "2", "202", diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/DeleteBuildingEntranceCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/DeleteBuildingEntranceCommandHandlerTests.cs index d6d8abd..6152af0 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/DeleteBuildingEntranceCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/DeleteBuildingEntranceCommandHandlerTests.cs @@ -54,7 +54,7 @@ public async Task Handle_ShouldDeleteEntranceAndRelatedEntities_WhenEntranceExis _dbContext.Entrances.Add(entrance); await _dbContext.SaveChangesAsync(); - var command = new DeleteBuildingEntranceCommand(buildingId, "Entrance1"); + var command = new DeleteBuildingEntranceCommand(entrance.Id); // Act var result = await _handler.Handle(command, CancellationToken.None); @@ -70,55 +70,10 @@ public async Task Handle_ShouldDeleteEntranceAndRelatedEntities_WhenEntranceExis public async Task Handle_ShouldThrowException_WhenEntranceNotFound() { // Arrange - var command = new DeleteBuildingEntranceCommand(Guid.NewGuid(), "NonExistentEntrance"); + var command = new DeleteBuildingEntranceCommand(Guid.NewGuid()); // Act & Assert await Assert.ThrowsAsync(() => _handler.Handle(command, CancellationToken.None)); } - - [Fact] - public async Task Handle_ShouldLeaveDatabaseInConsistentState_AfterDeletion() - { - // Arrange - var buildingId = Guid.NewGuid(); - var entrance = new Entrance - { - Id = Guid.NewGuid(), - BuildingId = buildingId, - Number = "Entrance1", - Properties = new HashSet - { - new Property - { - EntranceId = Guid.NewGuid(), - Floor = "1", - Number = "1", - PropertyOccupants = new HashSet - { - new PropertyOccupant - { - Id = Guid.NewGuid(), - FirstName = "A", - MiddleName = "A", - LastName = "A", - } - } - } - } - }; - - _dbContext.Entrances.Add(entrance); - await _dbContext.SaveChangesAsync(); - - var command = new DeleteBuildingEntranceCommand(buildingId, "Entrance1"); - - // Act - await _handler.Handle(command, CancellationToken.None); - - // Assert - Assert.False(await _dbContext.Entrances.AnyAsync()); - Assert.False(await _dbContext.Properties.AnyAsync()); - Assert.False(await _dbContext.PropertyOccupants.AnyAsync()); - } } diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/DeletePropertyCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/DeletePropertyCommandHandlerTests.cs index 25ff9e6..673ade6 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/DeletePropertyCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/DeletePropertyCommandHandlerTests.cs @@ -1,12 +1,10 @@ using ECondo.Application.Commands.Properties.Delete; using ECondo.Application.Repositories; -using ECondo.Domain; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; using ECondo.Infrastructure.Contexts; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.EntityFrameworkCore; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.Properties.Delete; diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/DeletePropertyOccupantCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/DeletePropertyOccupantCommandHandlerTests.cs index 61e95de..5823d58 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/DeletePropertyOccupantCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/DeletePropertyOccupantCommandHandlerTests.cs @@ -1,12 +1,9 @@ using ECondo.Application.Commands.PropertyOccupants.Delete; using ECondo.Application.Repositories; -using ECondo.Domain; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; using ECondo.Infrastructure.Contexts; using FluentAssertions; using Microsoft.EntityFrameworkCore; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.PropertyOccupants.Delete; @@ -63,6 +60,7 @@ public async Task Handle_ShouldLeaveDatabaseInConsistentState_AfterDeletion() { // Arrange var occupantId = Guid.NewGuid(); + var propertyOccupant = new PropertyOccupant { Id = occupantId, diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/RegisterBuildingEntranceCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/RegisterBuildingEntranceCommandHandlerTests.cs index 235b9ba..89758b2 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/RegisterBuildingEntranceCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/RegisterBuildingEntranceCommandHandlerTests.cs @@ -3,19 +3,17 @@ using ECondo.Application.Services; using ECondo.Domain.Buildings; using ECondo.Domain.Provinces; -using ECondo.Domain.Shared; using ECondo.Infrastructure.Contexts; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NSubstitute; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.Buildings.RegisterEntrance; public class RegisterBuildingEntranceCommandHandlerTests { private readonly IApplicationDbContext _dbContext; - private readonly IUserContext _userContext; private readonly RegisterBuildingEntranceCommandHandler _handler; public RegisterBuildingEntranceCommandHandlerTests() @@ -25,9 +23,9 @@ public RegisterBuildingEntranceCommandHandlerTests() .Options; _dbContext = new ECondoDbContext(options); - _userContext = Substitute.For(); - _userContext.UserId.Returns(Guid.NewGuid()); - _handler = new RegisterBuildingEntranceCommandHandler(_dbContext, _userContext); + var userContext = Substitute.For(); + userContext.UserId.Returns(Guid.NewGuid()); + _handler = new RegisterBuildingEntranceCommandHandler(_dbContext, userContext); } [Fact] diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdateBuildingCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdateBuildingCommandHandlerTests.cs index 6750a87..1b70f32 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdateBuildingCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdateBuildingCommandHandlerTests.cs @@ -2,11 +2,10 @@ using ECondo.Application.Repositories; using ECondo.Domain.Buildings; using ECondo.Domain.Provinces; -using ECondo.Domain.Shared; using ECondo.Infrastructure.Contexts; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.EntityFrameworkCore; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.Buildings.Update; diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdateProfileCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdateProfileCommandHandlerTests.cs index 58f9654..b9e94bb 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdateProfileCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdateProfileCommandHandlerTests.cs @@ -2,12 +2,11 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; using ECondo.Domain.Profiles; -using ECondo.Domain.Shared; using ECondo.Infrastructure.Contexts; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NSubstitute; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.Profiles.Update; diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdatePropertyCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdatePropertyCommandHandlerTests.cs index 19ae09e..67da02b 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdatePropertyCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdatePropertyCommandHandlerTests.cs @@ -1,12 +1,10 @@ using ECondo.Application.Commands.Properties.Update; using ECondo.Application.Repositories; -using ECondo.Domain; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; using ECondo.Infrastructure.Contexts; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.EntityFrameworkCore; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.Properties.Update; diff --git a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdatePropertyOccupantCommandHandlerTests.cs b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdatePropertyOccupantCommandHandlerTests.cs index 911e969..a5caef8 100644 --- a/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdatePropertyOccupantCommandHandlerTests.cs +++ b/backend/ECondo.Application.IntegrationTests/Commands/Buildings/UpdatePropertyOccupantCommandHandlerTests.cs @@ -1,15 +1,13 @@ using ECondo.Application.Commands.PropertyOccupants.Update; using ECondo.Application.Events.PropertyOccupant; using ECondo.Application.Repositories; -using ECondo.Domain; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; using ECondo.Infrastructure.Contexts; +using ECondo.SharedKernel.Result; using FluentAssertions; using MediatR; using Microsoft.EntityFrameworkCore; using NSubstitute; -using Xunit; namespace ECondo.Application.IntegrationTests.Commands.PropertyOccupants.Update; diff --git a/backend/ECondo.Application.UnitTests/Authorization/AccessLevelTests.cs b/backend/ECondo.Application.UnitTests/Authorization/AccessLevelTests.cs new file mode 100644 index 0000000..914062f --- /dev/null +++ b/backend/ECondo.Application.UnitTests/Authorization/AccessLevelTests.cs @@ -0,0 +1,69 @@ +using ECondo.Domain.Authorization; + +namespace ECondo.Application.UnitTests.Authorization; + +public class AccessLevelTests +{ + [Fact] + public void AccessLevel_FlagsWork_Correctly() + { + // Test individual flags + Assert.Equal(0, (int)AccessLevel.None); + Assert.Equal(1, (int)AccessLevel.Create); + Assert.Equal(2, (int)AccessLevel.Read); + Assert.Equal(4, (int)AccessLevel.Update); + Assert.Equal(8, (int)AccessLevel.Delete); + } + + [Fact] + public void AccessLevel_CombinedFlags_WorkCorrectly() + { + // Test combined flags + Assert.Equal(AccessLevel.Create | AccessLevel.Update, AccessLevel.Write); + Assert.Equal(AccessLevel.Read | AccessLevel.Write, AccessLevel.ReadWrite); + Assert.Equal(AccessLevel.Read | AccessLevel.Update, AccessLevel.ReadUpdate); + Assert.Equal(AccessLevel.Read | AccessLevel.Write | AccessLevel.Delete, AccessLevel.All); + } + + [Fact] + public void AccessLevel_HasFlag_WorksCorrectly() + { + // Test HasFlag method + Assert.True(AccessLevel.All.HasFlag(AccessLevel.Read)); + Assert.True(AccessLevel.All.HasFlag(AccessLevel.Create)); + Assert.True(AccessLevel.All.HasFlag(AccessLevel.Update)); + Assert.True(AccessLevel.All.HasFlag(AccessLevel.Delete)); + + Assert.True(AccessLevel.ReadWrite.HasFlag(AccessLevel.Read)); + Assert.True(AccessLevel.ReadWrite.HasFlag(AccessLevel.Create)); + Assert.True(AccessLevel.ReadWrite.HasFlag(AccessLevel.Update)); + Assert.False(AccessLevel.ReadWrite.HasFlag(AccessLevel.Delete)); + + Assert.False(AccessLevel.None.HasFlag(AccessLevel.Read)); + Assert.False(AccessLevel.None.HasFlag(AccessLevel.Create)); + Assert.False(AccessLevel.None.HasFlag(AccessLevel.Update)); + Assert.False(AccessLevel.None.HasFlag(AccessLevel.Delete)); + } + + [Fact] + public void AccessLevel_BitwiseOperations_WorkCorrectly() + { + // Test bitwise AND + var readWrite = AccessLevel.Read | AccessLevel.Write; + Assert.Equal(AccessLevel.Read, readWrite & AccessLevel.Read); + Assert.Equal(AccessLevel.None, readWrite & AccessLevel.Delete); + + // Test bitwise OR + var combined = AccessLevel.Read | AccessLevel.Delete; + Assert.True(combined.HasFlag(AccessLevel.Read)); + Assert.True(combined.HasFlag(AccessLevel.Delete)); + Assert.False(combined.HasFlag(AccessLevel.Create)); + + // Test bitwise XOR (remove flag) + var withoutRead = AccessLevel.All ^ AccessLevel.Read; + Assert.False(withoutRead.HasFlag(AccessLevel.Read)); + Assert.True(withoutRead.HasFlag(AccessLevel.Create)); + Assert.True(withoutRead.HasFlag(AccessLevel.Update)); + Assert.True(withoutRead.HasFlag(AccessLevel.Delete)); + } +} \ No newline at end of file diff --git a/backend/ECondo.Application.UnitTests/Authorization/AuthorizationPipelineBehaviourTests.cs b/backend/ECondo.Application.UnitTests/Authorization/AuthorizationPipelineBehaviourTests.cs new file mode 100644 index 0000000..518fac5 --- /dev/null +++ b/backend/ECondo.Application.UnitTests/Authorization/AuthorizationPipelineBehaviourTests.cs @@ -0,0 +1,111 @@ +using ECondo.Application.Behaviours; +using ECondo.Application.Services; +using ECondo.Domain.Authorization; +using ECondo.Domain.Exceptions; +using ECondo.SharedKernel.Result; +using FluentAssertions; +using MediatR; +using NSubstitute; + +namespace ECondo.Application.UnitTests.Authorization; + +public class AuthorizationPipelineBehaviourTests +{ + private readonly IAuthorizationService _mockAuthorizationService; + private readonly IUserContext _mockUserContext; + private readonly AuthorizationPipelineBehaviour> _behaviour; + private readonly RequestHandlerDelegate> _mockNext; + + public AuthorizationPipelineBehaviourTests() + { + _mockAuthorizationService = Substitute.For(); + _mockUserContext = Substitute.For(); + _behaviour = new AuthorizationPipelineBehaviour>(_mockAuthorizationService, _mockUserContext); + _mockNext = Substitute.For>>(); + } + + [Fact] + public async Task Handle_UserHasPermission_CallsNextHandler() + { + // Arrange + var userId = Guid.NewGuid(); + var request = new TestCommand { ResourceId = Guid.NewGuid() }; + var expectedResult = Result.Ok("test"); + + _mockUserContext.UserId.Returns(userId); + _mockAuthorizationService + .CanPerformActionAsync(userId, request.ResourceId, request.ResourceAction, Arg.Any()) + .Returns(true); + _mockNext().Returns(expectedResult); + + // Act + var result = await _behaviour.Handle(request, _mockNext, CancellationToken.None); + + // Assert + result.Should().Be(expectedResult); + await _mockNext.Received(1)(); + } + + [Fact] + public async Task Handle_UserDoesNotHavePermission_ReturnsFailureResult() + { + // Arrange + var userId = Guid.NewGuid(); + var request = new TestCommand { ResourceId = Guid.NewGuid() }; + + _mockUserContext.UserId.Returns(userId); + _mockAuthorizationService + .CanPerformActionAsync(userId, request.ResourceId, request.ResourceAction, Arg.Any()) + .Returns(false); + + // Act + var result = await _behaviour.Handle(request, _mockNext, CancellationToken.None); + + // Assert + result + .IsOk() + .Should() + .BeFalse(); + + result + .ToError() + .Data! + .Code + .Should() + .Be("Resource.Forbidden"); + + await _mockNext.DidNotReceive()(); + } + + [Fact] + public async Task Handle_UserDoesNotHavePermission_NonResultType_ThrowsForbiddenException() + { + // Arrange + var userId = Guid.NewGuid(); + var request = new TestCommand { ResourceId = Guid.NewGuid() }; + var nonResultBehaviour = new AuthorizationPipelineBehaviour(_mockAuthorizationService, _mockUserContext); + var mockNextString = Substitute.For>(); + + _mockUserContext.UserId.Returns(userId); + _mockAuthorizationService + .CanPerformActionAsync(userId, request.ResourceId, request.ResourceAction, Arg.Any()) + .Returns(false); + + // Act & Assert + var act = async () => await nonResultBehaviour.Handle(request, mockNextString, CancellationToken.None); + + await act.Should().ThrowAsync(); + await mockNextString.DidNotReceive()(); + } + + private class TestCommand : IResourcePolicy + { + public Guid? ResourceId { get; init; } + public Type ResourceType => typeof(TestEntity); + public AccessLevel ResourceAction => AccessLevel.Read; + } + + private class TestEntity + { + } +} \ No newline at end of file diff --git a/backend/ECondo.Application.UnitTests/Authorization/BillAuthorizationHandlerTests.cs b/backend/ECondo.Application.UnitTests/Authorization/BillAuthorizationHandlerTests.cs new file mode 100644 index 0000000..049e9d5 --- /dev/null +++ b/backend/ECondo.Application.UnitTests/Authorization/BillAuthorizationHandlerTests.cs @@ -0,0 +1,285 @@ +using ECondo.Application.Authorization; +using ECondo.Application.Repositories; +using ECondo.Application.UnitTests.Helper; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; +using ECondo.Domain.Payments; +using ECondo.Domain.Users; +using FluentAssertions; +using NSubstitute; + +namespace ECondo.Application.UnitTests.Authorization; + +public class BillAuthorizationHandlerTests +{ + private readonly IApplicationDbContext _mockDbContext; + private readonly BillAuthorizationHandler _handler; + + public BillAuthorizationHandlerTests() + { + _mockDbContext = Substitute.For(); + _handler = new BillAuthorizationHandler(_mockDbContext); + } + + [Fact] + public async Task GetAccessLevelAsync_AdminUser_ReturnsAllAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var billId = Guid.NewGuid(); + + var userRoles = new List + { + new() { UserId = userId, Role = new Role { Name = Role.Admin } } + }.AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, billId); + + // Assert + result + .Should() + .Be(AccessLevel.All); + } + + [Fact] + public async Task GetAccessLevelAsync_NoResourceId_ReturnsNoAccess() + { + // Arrange + var userId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, null); + + // Assert + result + .Should() + .Be(AccessLevel.None); + } + + [Fact] + public async Task GetAccessLevelAsync_EntranceManager_ReturnsAllAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var billId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var bills = new List + { + new() + { + Id = billId, + Entrance = new Entrance + { + ManagerId = userId, + Number = "1", + } + } + }.AsQueryable(); + var propertyOccupants = new List().AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + var mockBillSet = DbSetMockHelper.CreateMockDbSet(bills); + var mockPropertyOccupantSet = DbSetMockHelper.CreateMockDbSet(propertyOccupants); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + _mockDbContext.Bills.Returns(mockBillSet); + _mockDbContext.PropertyOccupants.Returns(mockPropertyOccupantSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, billId); + + // Assert + result + .Should() + .Be(AccessLevel.All); + } + + [Fact] + public async Task GetAccessLevelAsync_PropertyOccupantInEntrance_ReturnsReadAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var billId = Guid.NewGuid(); + var managerId = Guid.NewGuid(); + + + var userRoles = new List().AsQueryable(); + var propertyOccupants = new List + { + new() + { + UserId = userId, + } + }.AsQueryable(); + + var bills = new List + { + new() + { + Id = billId, + Entrance = new Entrance + { + ManagerId = managerId, + Properties = + [ + new() + { + PropertyOccupants = propertyOccupants.ToHashSet() + } + ] + } + } + }.AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + var mockBillSet = DbSetMockHelper.CreateMockDbSet(bills); + var mockPropertyOccupantSet = DbSetMockHelper.CreateMockDbSet(propertyOccupants); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + _mockDbContext.Bills.Returns(mockBillSet); + _mockDbContext.PropertyOccupants.Returns(mockPropertyOccupantSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, billId); + + // Assert + result + .Should() + .Be(AccessLevel.Read); + } + + [Fact] + public async Task GetAccessLevelAsync_NotManagerNotOccupant_ReturnsNoAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var billId = Guid.NewGuid(); + var managerId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var bills = new List + { + new() + { + Id = billId, + Entrance = new Entrance { ManagerId = managerId } + } + }.AsQueryable(); + var propertyOccupants = new List().AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + var mockBillSet = DbSetMockHelper.CreateMockDbSet(bills); + var mockPropertyOccupantSet = DbSetMockHelper.CreateMockDbSet(propertyOccupants); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + _mockDbContext.Bills.Returns(mockBillSet); + _mockDbContext.PropertyOccupants.Returns(mockPropertyOccupantSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, billId); + + // Assert + result + .Should() + .Be(AccessLevel.None); + } + + [Fact] + public async Task ApplyDataFilterAsync_AdminUser_ReturnsUnfilteredQuery() + { + // Arrange + var userId = Guid.NewGuid(); + var bills = new List + { + new() { Id = Guid.NewGuid(), Entrance = new Entrance { ManagerId = Guid.NewGuid(), Properties = new HashSet() } }, + new() { Id = Guid.NewGuid(), Entrance = new Entrance { ManagerId = Guid.NewGuid(), Properties = new HashSet() } } + }.AsQueryable(); + + var userRoles = new List + { + new() { UserId = userId, Role = new Role { Name = Role.Admin } } + }.AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + + // Act + var result = await _handler.ApplyDataFilterAsync(bills, userId); + + // Assert + result + .Count() + .Should() + .Be(2); + } + + [Fact] + public async Task ApplyDataFilterAsync_NonAdminUser_ReturnsFilteredQuery() + { + // Arrange + var userId = Guid.NewGuid(); + var bills = new List + { + new() + { + Id = Guid.NewGuid(), + Entrance = new Entrance + { + ManagerId = userId, + Properties = new HashSet() + } + }, + new() + { + Id = Guid.NewGuid(), + Entrance = new Entrance + { + ManagerId = Guid.NewGuid(), + Properties = [ + new Property + { + PropertyOccupants = [ + new PropertyOccupant + { + UserId = userId + } + ] + } + ] + } + }, + new() + { + Id = Guid.NewGuid(), + Entrance = new Entrance + { + ManagerId = Guid.NewGuid(), + Properties = new HashSet() + } + } + }.AsQueryable(); + + var userRoles = new List().AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + + // Act + var result = await _handler.ApplyDataFilterAsync(bills, userId); + + // Assert + result + .Count() + .Should() + .Be(2); + } +} \ No newline at end of file diff --git a/backend/ECondo.Application.UnitTests/Authorization/DefaultAuthorizationHandlerTests.cs b/backend/ECondo.Application.UnitTests/Authorization/DefaultAuthorizationHandlerTests.cs new file mode 100644 index 0000000..a3d47e7 --- /dev/null +++ b/backend/ECondo.Application.UnitTests/Authorization/DefaultAuthorizationHandlerTests.cs @@ -0,0 +1,69 @@ +using ECondo.Application.Authorization; +using ECondo.Domain.Authorization; +using FluentAssertions; + +namespace ECondo.Application.UnitTests.Authorization; + +public class DefaultAuthorizationHandlerTests +{ + private readonly DefaultAuthorizationHandler _handler = new(); + + [Fact] + public async Task GetAccessLevelAsync_ReturnsNoAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var resourceId = Guid.NewGuid(); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, resourceId); + + // Assert + result + .Should() + .Be(AccessLevel.None); + } + + [Fact] + public async Task GetAccessLevelAsync_WithNullResourceId_ReturnsNoAccess() + { + // Arrange + var userId = Guid.NewGuid(); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, null); + + // Assert + result + .Should() + .Be(AccessLevel.None); + } + + [Fact] + public async Task ApplyDataFilterAsync_ReturnsUnmodifiedQuery() + { + // Arrange + var userId = Guid.NewGuid(); + var entities = new List + { + new(), + new(), + new() + }.AsQueryable(); + + // Act + var result = await _handler.ApplyDataFilterAsync(entities, userId); + + // Assert + result + .Count() + .Should() + .Be(3); + + result.Should().BeSameAs(entities); + } + + private class TestEntity + { + } +} \ No newline at end of file diff --git a/backend/ECondo.Application.UnitTests/Authorization/EntranceAuthorizationHandlerTests.cs b/backend/ECondo.Application.UnitTests/Authorization/EntranceAuthorizationHandlerTests.cs new file mode 100644 index 0000000..9d2c047 --- /dev/null +++ b/backend/ECondo.Application.UnitTests/Authorization/EntranceAuthorizationHandlerTests.cs @@ -0,0 +1,172 @@ +using ECondo.Application.Authorization; +using ECondo.Application.Repositories; +using ECondo.Application.UnitTests.Helper; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; +using ECondo.Domain.Users; +using FluentAssertions; +using NSubstitute; + +namespace ECondo.Application.UnitTests.Authorization; + +public class EntranceAuthorizationHandlerTests +{ + private readonly IApplicationDbContext _mockDbContext; + private readonly EntranceAuthorizationHandler _handler; + + public EntranceAuthorizationHandlerTests() + { + _mockDbContext = Substitute.For(); + _handler = new EntranceAuthorizationHandler(_mockDbContext); + } + + [Fact] + public async Task GetAccessLevelAsync_AdminUser_ReturnsAllAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var entranceId = Guid.NewGuid(); + + var userRoles = new List + { + new() { UserId = userId, Role = new Role { Name = Role.Admin } } + }.AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, entranceId); + + // Assert + result.Should().Be(AccessLevel.All); + } + + [Fact] + public async Task GetAccessLevelAsync_NoResourceId_ReturnsReadAccess() + { + // Arrange + var userId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, null); + + // Assert + result.Should().Be(AccessLevel.Read); + } + + [Fact] + public async Task GetAccessLevelAsync_EntranceManager_ReturnsAllAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var entranceId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var entrances = new List + { + new() + { + Id = entranceId, + ManagerId = userId + } + }.AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + var mockEntranceSet = DbSetMockHelper.CreateMockDbSet(entrances); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + _mockDbContext.Entrances.Returns(mockEntranceSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, entranceId); + + // Assert + result.Should().Be(AccessLevel.All); + } + + [Fact] + public async Task GetAccessLevelAsync_NotManager_ReturnsNoAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var entranceId = Guid.NewGuid(); + var managerId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var entrances = new List + { + new() + { + Id = entranceId, + ManagerId = managerId + } + }.AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + var mockEntranceSet = DbSetMockHelper.CreateMockDbSet(entrances); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + _mockDbContext.Entrances.Returns(mockEntranceSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, entranceId); + + // Assert + result.Should().Be(AccessLevel.None); + } + + [Fact] + public async Task ApplyDataFilterAsync_AdminUser_ReturnsUnfilteredQuery() + { + // Arrange + var userId = Guid.NewGuid(); + var entrances = new List + { + new() { Id = Guid.NewGuid(), ManagerId = Guid.NewGuid() }, + new() { Id = Guid.NewGuid(), ManagerId = Guid.NewGuid() } + }.AsQueryable(); + + var userRoles = new List + { + new() { UserId = userId, Role = new Role { Name = Role.Admin } } + }.AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + + // Act + var result = await _handler.ApplyDataFilterAsync(entrances, userId); + + // Assert + result.Count().Should().Be(2); + } + + [Fact] + public async Task ApplyDataFilterAsync_NonAdminUser_ReturnsFilteredQuery() + { + // Arrange + var userId = Guid.NewGuid(); + var entrances = new List + { + new() { Id = Guid.NewGuid(), ManagerId = userId }, + new() { Id = Guid.NewGuid(), ManagerId = Guid.NewGuid() }, + new() { Id = Guid.NewGuid(), ManagerId = Guid.NewGuid() } + }.AsQueryable(); + + var userRoles = new List().AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + + // Act + var result = await _handler.ApplyDataFilterAsync(entrances, userId); + + // Assert + result.Count().Should().Be(1); + } +} \ No newline at end of file diff --git a/backend/ECondo.Application.UnitTests/Authorization/OccupantAuthorizationHandlerUnitTests.cs b/backend/ECondo.Application.UnitTests/Authorization/OccupantAuthorizationHandlerUnitTests.cs new file mode 100644 index 0000000..af6f8e9 --- /dev/null +++ b/backend/ECondo.Application.UnitTests/Authorization/OccupantAuthorizationHandlerUnitTests.cs @@ -0,0 +1,279 @@ +using ECondo.Application.Authorization; +using ECondo.Application.Repositories; +using ECondo.Application.UnitTests.Helper; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; +using ECondo.Domain.Users; +using FluentAssertions; +using NSubstitute; + +namespace ECondo.Application.UnitTests.Authorization; + +public class OccupantAuthorizationHandlerUnitTests +{ + private readonly IApplicationDbContext _mockDbContext; + private readonly OccupantAuthorizationHandler _handler; + + public OccupantAuthorizationHandlerUnitTests() + { + _mockDbContext = Substitute.For(); + _handler = new OccupantAuthorizationHandler(_mockDbContext); + } + + [Fact] + public async Task GetAccessLevelAsync_AdminUser_ReturnsAllAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var propertyId = Guid.NewGuid(); + + var userRoles = new List + { + new() { UserId = userId, Role = new Role { Name = Role.Admin } } + }.AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, propertyId); + + // Assert + Assert.Equal(AccessLevel.All, result); + } + + [Fact] + public async Task GetAccessLevelAsync_NoResourceId_ReturnsNoneAccess() + { + // Arrange + var userId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, null); + + // Assert + Assert.Equal(AccessLevel.None, result); + } + + [Fact] + public async Task GetAccessLevelAsync_EntranceManager_ReturnsAllAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var occupantId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var propertyOccupants = new List() + { + new() + { + Id = occupantId, + Property = new Property + { + Entrance = new Entrance + { + ManagerId = userId + } + }, + OccupantType = new OccupantType + { + Name = OccupantType.TenantType + } + } + }.AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + var mockPropertyOccupantSet = DbSetMockHelper.CreateMockDbSet(propertyOccupants); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + _mockDbContext.PropertyOccupants.Returns(mockPropertyOccupantSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, occupantId); + + // Assert + Assert.Equal(AccessLevel.All, result); + } + + [Fact] + public async Task GetAccessLevelAsync_PropertyOccupant_ReturnsReadAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var propertyId = Guid.NewGuid(); + var managerId = Guid.NewGuid(); + var propertyOccupantId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var properties = new List + { + new() + { + Id = propertyId, + Entrance = new Entrance { ManagerId = managerId } + } + }.AsQueryable(); + var propertyOccupants = new List + { + new() + { + Id = propertyOccupantId, + UserId = userId, + Property = properties.First(), + OccupantType = new OccupantType + { + Name = OccupantType.TenantType + } + + } + }.AsQueryable(); + + properties.First().PropertyOccupants = propertyOccupants.ToHashSet(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + var mockPropertySet = DbSetMockHelper.CreateMockDbSet(properties); + var mockPropertyOccupantSet = DbSetMockHelper.CreateMockDbSet(propertyOccupants); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + _mockDbContext.Properties.Returns(mockPropertySet); + _mockDbContext.PropertyOccupants.Returns(mockPropertyOccupantSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, propertyOccupantId); + + // Assert + Assert.Equal(AccessLevel.Read, result); + } + + [Fact] + public async Task GetAccessLevelAsync_PropertyOwner_ReturnsAllAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var propertyId = Guid.NewGuid(); + var managerId = Guid.NewGuid(); + var occupantId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + + var properties = new List + { + new() + { + Id = propertyId, + Entrance = new Entrance { ManagerId = managerId } + } + }.AsQueryable(); + var propertyOccupants = new List + { + new() + { + Id = occupantId, + Property = properties.First(), + OccupantType = new OccupantType + { + Name = OccupantType.TenantType + } + }, + new() + { + UserId = userId, + Property = properties.First(), + OccupantType = new OccupantType + { + Name = OccupantType.OwnerType + } + } + }.AsQueryable(); + + properties.First().PropertyOccupants = propertyOccupants.ToHashSet(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + var mockPropertySet = DbSetMockHelper.CreateMockDbSet(properties); + var mockPropertyOccupantSet = DbSetMockHelper.CreateMockDbSet(propertyOccupants); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + _mockDbContext.Properties.Returns(mockPropertySet); + _mockDbContext.PropertyOccupants.Returns(mockPropertyOccupantSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, occupantId); + + // Assert + result.Should().Be(AccessLevel.All); + } + + [Fact] + public async Task GetAccessLevelAsync_NotManagerNotOccupant_ReturnsNoAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var propertyId = Guid.NewGuid(); + var propertyId2 = Guid.NewGuid(); + var managerId = Guid.NewGuid(); + var occupantId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var entrance = new Entrance() + { + ManagerId = managerId, + }; + var properties = new List + { + new() + { + Id = propertyId, + Entrance = entrance + }, + new() + { + Id = propertyId2, + Entrance = entrance + } + }.AsQueryable(); + var propertyOccupants = new List + { + new() + { + Id = occupantId, + Property = properties.First(), + OccupantType = new OccupantType + { + Name = OccupantType.TenantType + } + }, + new() + { + UserId = userId, + Property = properties.ElementAt(1), + OccupantType = new OccupantType + { + Name = OccupantType.OwnerType + } + } + }.AsQueryable(); + + properties.First().PropertyOccupants = new HashSet([propertyOccupants.First()]); + properties.ElementAt(1).PropertyOccupants = new HashSet([propertyOccupants.ElementAt(1)]); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + var mockPropertySet = DbSetMockHelper.CreateMockDbSet(properties); + var mockPropertyOccupantSet = DbSetMockHelper.CreateMockDbSet(propertyOccupants); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + _mockDbContext.Properties.Returns(mockPropertySet); + _mockDbContext.PropertyOccupants.Returns(mockPropertyOccupantSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, occupantId); + + // Assert + result.Should().Be(AccessLevel.None); + } +} diff --git a/backend/ECondo.Application.UnitTests/Authorization/PropertyAuthorizationHandlerTests.cs b/backend/ECondo.Application.UnitTests/Authorization/PropertyAuthorizationHandlerTests.cs new file mode 100644 index 0000000..af83d42 --- /dev/null +++ b/backend/ECondo.Application.UnitTests/Authorization/PropertyAuthorizationHandlerTests.cs @@ -0,0 +1,168 @@ +using ECondo.Application.Authorization; +using ECondo.Application.Repositories; +using ECondo.Application.UnitTests.Helper; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; +using ECondo.Domain.Users; +using FluentAssertions; +using NSubstitute; + +namespace ECondo.Application.UnitTests.Authorization; + +public class PropertyAuthorizationHandlerTests +{ + private readonly IApplicationDbContext _mockDbContext; + private readonly PropertyAuthorizationHandler _handler; + + public PropertyAuthorizationHandlerTests() + { + _mockDbContext = Substitute.For(); + _handler = new PropertyAuthorizationHandler(_mockDbContext); + } + + [Fact] + public async Task GetAccessLevelAsync_AdminUser_ReturnsAllAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var propertyId = Guid.NewGuid(); + + var userRoles = new List + { + new() { UserId = userId, Role = new Role { Name = Role.Admin } } + }.AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, propertyId); + + // Assert + result.Should().Be(AccessLevel.All); + } + + [Fact] + public async Task GetAccessLevelAsync_NoResourceId_ReturnsReadAccess() + { + // Arrange + var userId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, null); + + // Assert + result.Should().Be(AccessLevel.Read); + } + + [Fact] + public async Task GetAccessLevelAsync_EntranceManager_ReturnsAllAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var propertyId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var properties = new List + { + new() + { + Id = propertyId, + Entrance = new Entrance { ManagerId = userId } + } + }.AsQueryable(); + var propertyOccupants = new List().AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + var mockPropertySet = DbSetMockHelper.CreateMockDbSet(properties); + var mockPropertyOccupantSet = DbSetMockHelper.CreateMockDbSet(propertyOccupants); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + _mockDbContext.Properties.Returns(mockPropertySet); + _mockDbContext.PropertyOccupants.Returns(mockPropertyOccupantSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, propertyId); + + // Assert + result.Should().Be(AccessLevel.All); + } + + [Fact] + public async Task GetAccessLevelAsync_PropertyOccupant_ReturnsReadAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var propertyId = Guid.NewGuid(); + var managerId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var propertyOccupants = new List + { + new() { UserId = userId, PropertyId = propertyId } + }.AsQueryable(); + var properties = new List + { + new() + { + Id = propertyId, + Entrance = new Entrance { ManagerId = managerId }, + PropertyOccupants = propertyOccupants.ToHashSet(), + } + }.AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + var mockPropertySet = DbSetMockHelper.CreateMockDbSet(properties); + var mockPropertyOccupantSet = DbSetMockHelper.CreateMockDbSet(propertyOccupants); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + _mockDbContext.Properties.Returns(mockPropertySet); + _mockDbContext.PropertyOccupants.Returns(mockPropertyOccupantSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, propertyId); + + // Assert + result.Should().Be(AccessLevel.Read); + } + + [Fact] + public async Task GetAccessLevelAsync_NotManagerNotOccupant_ReturnsNoAccess() + { + // Arrange + var userId = Guid.NewGuid(); + var propertyId = Guid.NewGuid(); + var managerId = Guid.NewGuid(); + + var userRoles = new List().AsQueryable(); + var properties = new List + { + new() + { + Id = propertyId, + Entrance = new Entrance { ManagerId = managerId } + } + }.AsQueryable(); + var propertyOccupants = new List().AsQueryable(); + + var mockUserRoleSet = DbSetMockHelper.CreateMockDbSet(userRoles); + var mockPropertySet = DbSetMockHelper.CreateMockDbSet(properties); + var mockPropertyOccupantSet = DbSetMockHelper.CreateMockDbSet(propertyOccupants); + + _mockDbContext.UserRoles.Returns(mockUserRoleSet); + _mockDbContext.Properties.Returns(mockPropertySet); + _mockDbContext.PropertyOccupants.Returns(mockPropertyOccupantSet); + + // Act + var result = await _handler.GetAccessLevelAsync(userId, propertyId); + + // Assert + result.Should().Be(AccessLevel.None); + } +} \ No newline at end of file diff --git a/backend/ECondo.Application.UnitTests/Commands/Buildings/DeleteBuildingEntranceCommandHandlerTests.cs b/backend/ECondo.Application.UnitTests/Commands/Buildings/DeleteBuildingEntranceCommandHandlerTests.cs index 2f0170c..83a3b3b 100644 --- a/backend/ECondo.Application.UnitTests/Commands/Buildings/DeleteBuildingEntranceCommandHandlerTests.cs +++ b/backend/ECondo.Application.UnitTests/Commands/Buildings/DeleteBuildingEntranceCommandHandlerTests.cs @@ -1,126 +1,87 @@ -using System.Linq.Expressions; using ECondo.Application.Commands.Buildings.Delete; using ECondo.Application.Repositories; +using ECondo.Application.UnitTests.Helper; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; -using ECondo.Domain.Users; using FluentAssertions; -using Microsoft.EntityFrameworkCore; using NSubstitute; namespace ECondo.Application.UnitTests.Commands.Buildings.Delete; public class DeleteBuildingEntranceCommandHandlerTests { - private readonly IApplicationDbContext _dbContext; + private readonly IApplicationDbContext _mockDbContext; private readonly DeleteBuildingEntranceCommandHandler _handler; public DeleteBuildingEntranceCommandHandlerTests() { - _dbContext = Substitute.For(); - _handler = new DeleteBuildingEntranceCommandHandler(_dbContext); + _mockDbContext = Substitute.For(); + _handler = new DeleteBuildingEntranceCommandHandler(_mockDbContext); } [Fact] public async Task Handle_ShouldDeleteEntranceAndRelatedEntities_WhenEntranceExists() { - try + // Arrange + var entranceId = Guid.NewGuid(); + var command = new DeleteBuildingEntranceCommand(entranceId); + var propertyOccupants = new List() { - // Arrange - var command = new DeleteBuildingEntranceCommand(Guid.NewGuid(), "Entrance1"); - var entrance = new Entrance + new() { - BuildingId = command.BuildingId, - Number = command.EntranceNumber, - Properties = new HashSet - { - new Property - { - PropertyOccupants = new HashSet - { - new PropertyOccupant { Id = Guid.NewGuid() } - } - } - } - }; + Id = Guid.NewGuid(), + } + }.AsQueryable(); - _dbContext.Entrances.Include(e => e.Properties) - .ThenInclude(e => e.PropertyOccupants) - .FirstAsync(Arg.Any>>(), CancellationToken.None) - .Returns(entrance); - - // Act - var result = await _handler.Handle(command, CancellationToken.None); - - // Assert - result.IsOk().Should().BeTrue(); - _dbContext.PropertyOccupants.Received(1).RemoveRange(Arg.Any>()); - _dbContext.Properties.Received(1).RemoveRange(Arg.Any>()); - _dbContext.Entrances.Received(1).Remove(entrance); - await _dbContext.Received(1).SaveChangesAsync(CancellationToken.None); - } - catch (NotSupportedException) + var properties = new List() { - Assert.True(true); - } - } - - [Fact] - public async Task Handle_ShouldThrowException_WhenEntranceNotFound() - { - try + new() + { + PropertyOccupants = propertyOccupants.ToHashSet(), + } + }.AsQueryable(); + + var entrances = new List() { - // Arrange - var command = new DeleteBuildingEntranceCommand(Guid.NewGuid(), "NonExistentEntrance"); - _dbContext.Entrances.Include(e => e.Properties) - .ThenInclude(e => e.PropertyOccupants) - .FirstAsync(Arg.Any>>(), CancellationToken.None) - .Returns(Task.FromException(new InvalidOperationException())); + new() + { + Id = entranceId, + Properties = properties.ToHashSet(), + } + }.AsQueryable(); - // Act - var act = async () => await _handler.Handle(command, CancellationToken.None); + var mockEntranceSet = DbSetMockHelper.CreateMockDbSet(entrances); + var mockPropertySet = DbSetMockHelper.CreateMockDbSet(properties); + var mockPropertyOccupantSet = DbSetMockHelper.CreateMockDbSet(propertyOccupants); + _mockDbContext.Entrances.Returns(mockEntranceSet); + _mockDbContext.Properties.Returns(mockPropertySet); + _mockDbContext.PropertyOccupants.Returns(mockPropertyOccupantSet); + + // Act + var result = await _handler.Handle(command, CancellationToken.None); - // Assert - await act.Should().ThrowAsync(); - } - catch (NotSupportedException) - { - Assert.True(true); - } + // Assert + result.IsOk().Should().BeTrue(); + _mockDbContext.PropertyOccupants.Received(1).RemoveRange(Arg.Any>()); + _mockDbContext.Properties.Received(1).RemoveRange(Arg.Any>()); + _mockDbContext.Entrances.Received(1).Remove(entrances.First()); + await _mockDbContext.Received(1).SaveChangesAsync(CancellationToken.None); } [Fact] - public async Task Handle_ShouldHandleSaveChangesException_WhenSaveFails() + public async Task Handle_ShouldThrowException_WhenEntranceNotFound() { - try - { - // Arrange - var command = new DeleteBuildingEntranceCommand(Guid.NewGuid(), "Entrance1"); - var entrance = new Entrance - { - BuildingId = command.BuildingId, - Number = command.EntranceNumber, - Properties = new HashSet() - }; + // Arrange + var entranceId = Guid.NewGuid(); + var command = new DeleteBuildingEntranceCommand(entranceId); + var entrances = new List().AsQueryable(); + var mockEntranceSet = DbSetMockHelper.CreateMockDbSet(entrances); + _mockDbContext.Entrances.Returns(mockEntranceSet); - _dbContext.Entrances.Include(e => e.Properties) - .ThenInclude(e => e.PropertyOccupants) - .FirstAsync(Arg.Any>>(), CancellationToken.None) - .Returns(entrance); + // Act + var act = async () => await _handler.Handle(command, CancellationToken.None); - _dbContext.SaveChangesAsync(CancellationToken.None) - .Returns(Task.FromException(new DbUpdateException())); - - // Act - var result = await _handler.Handle(command, CancellationToken.None); - - // Assert - result.IsOk().Should().BeFalse(); - result.ToError().Data.Should().BeOfType(); - } - catch(NotSupportedException) - { - Assert.True(true); - } + // Assert + await act.Should().ThrowAsync(); } } + diff --git a/backend/ECondo.Application.UnitTests/Commands/Identity/ConfirmEmailCommandHandlerTests.cs b/backend/ECondo.Application.UnitTests/Commands/Identity/ConfirmEmailCommandHandlerTests.cs index bb72068..67315be 100644 --- a/backend/ECondo.Application.UnitTests/Commands/Identity/ConfirmEmailCommandHandlerTests.cs +++ b/backend/ECondo.Application.UnitTests/Commands/Identity/ConfirmEmailCommandHandlerTests.cs @@ -1,10 +1,9 @@ using ECondo.Application.Commands.Identity.ConfirmEmail; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.AspNetCore.Identity; using NSubstitute; -using Xunit; namespace ECondo.Application.UnitTests.Commands.Identity.ConfirmEmail; diff --git a/backend/ECondo.Application.UnitTests/Commands/Identity/DeleteUserCommandHandlerTests.cs b/backend/ECondo.Application.UnitTests/Commands/Identity/DeleteUserCommandHandlerTests.cs index 38fa3d3..f22933b 100644 --- a/backend/ECondo.Application.UnitTests/Commands/Identity/DeleteUserCommandHandlerTests.cs +++ b/backend/ECondo.Application.UnitTests/Commands/Identity/DeleteUserCommandHandlerTests.cs @@ -1,80 +1,67 @@ using ECondo.Application.Commands.Identity.Delete; using ECondo.Application.Repositories; -using ECondo.Domain.Shared; +using ECondo.Application.UnitTests.Helper; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using FluentAssertions; -using Microsoft.EntityFrameworkCore; using NSubstitute; -using Xunit; namespace ECondo.Application.UnitTests.Commands.Identity.Delete; public class DeleteUserCommandHandlerTests { - private readonly IApplicationDbContext _dbContext; + private readonly IApplicationDbContext _mockDbContext; private readonly DeleteUserCommandHandler _handler; public DeleteUserCommandHandlerTests() { - _dbContext = Substitute.For(); - _handler = new DeleteUserCommandHandler(_dbContext); + _mockDbContext = Substitute.For(); + _handler = new DeleteUserCommandHandler(_mockDbContext); } [Fact] public async Task Handle_ShouldReturnInvalidUserError_WhenUserNotFound() { - try - { - // Arrange - var command = new DeleteUserCommand("nonexistent@example.com"); - var users = new List().AsQueryable(); - - // Act - var mockSet = Substitute.For, IQueryable, IAsyncEnumerable>(); - ((IQueryable)mockSet).Provider.Returns(new TestAsyncQueryProvider(users.Provider)); - ((IQueryable)mockSet).Expression.Returns(users.Expression); - ((IQueryable)mockSet).ElementType.Returns(users.ElementType); - ((IQueryable)mockSet).GetEnumerator().Returns(users.GetEnumerator()); - ((IAsyncEnumerable)mockSet).GetAsyncEnumerator(Arg.Any()) - .Returns(new TestAsyncEnumerator(users.GetEnumerator())); + // Arrange + var userId = Guid.NewGuid(); + var command = new DeleteUserCommand(userId); + var users = new List().AsQueryable(); - _dbContext.Users.Returns(mockSet); - var result = await _handler.Handle(command, CancellationToken.None); - // Assert - result.IsOk().Should().BeFalse(); - result.ToError().Data.Should().BeOfType(); - result.ToError().Data!.Code.Should().Be("Users.NotFound"); - } - catch - { - Assert.True(true); - } + var mockUserSet = DbSetMockHelper.CreateMockDbSet(users); + _mockDbContext.Users.Returns(mockUserSet); + + // Act + var result = await _handler.Handle(command, CancellationToken.None); + + // Assert + result.IsOk().Should().BeFalse(); + result.ToError().Data.Should().BeOfType(); + result.ToError().Data!.Code.Should().Be("Users.NotFound"); } [Fact] public async Task Handle_ShouldDeleteUser_WhenUserExists() { - try - { - // Arrange - var command = new DeleteUserCommand("test@example.com"); - var user = new User { Email = command.Email }; - _dbContext.Users.FirstOrDefaultAsync( - u => u.Email == command.Email, Arg.Any()) - .Returns(user); - // Act - var result = await _handler.Handle(command, CancellationToken.None); - - // Assert - result.IsOk().Should().BeTrue(); - _dbContext.Users.Received(1).Remove(user); - await _dbContext.Received(1).SaveChangesAsync(Arg.Any()); - } - catch + // Arrange + var userId = Guid.NewGuid(); + var command = new DeleteUserCommand(userId); + var users = new List() { - Assert.True(true); - } + new() + { + Id = userId, + } + }.AsQueryable(); + var mockUserSet = DbSetMockHelper.CreateMockDbSet(users); + _mockDbContext.Users.Returns(mockUserSet); + + // Act + var result = await _handler.Handle(command, CancellationToken.None); + // Assert + result.IsOk().Should().BeTrue(); + _mockDbContext.Users.Received(1).Remove(users.First()); + await _mockDbContext.Received(1).SaveChangesAsync(Arg.Any()); } } diff --git a/backend/ECondo.Application.UnitTests/Commands/Identity/ForgotPasswordCommandHandlerTests.cs b/backend/ECondo.Application.UnitTests/Commands/Identity/ForgotPasswordCommandHandlerTests.cs index 74e816f..aac1366 100644 --- a/backend/ECondo.Application.UnitTests/Commands/Identity/ForgotPasswordCommandHandlerTests.cs +++ b/backend/ECondo.Application.UnitTests/Commands/Identity/ForgotPasswordCommandHandlerTests.cs @@ -1,12 +1,11 @@ using ECondo.Application.Commands.Identity.ForgotPassword; using ECondo.Application.Services; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.WebUtilities; using NSubstitute; -using Xunit; namespace ECondo.Application.UnitTests.Commands.Identity.ForgotPassword; @@ -58,7 +57,7 @@ public async Task Handle_ShouldSendPasswordResetEmail_WhenUserExists() // Assert result.IsOk().Should().BeTrue(); await _emailService.Received(1).SendPasswordResetMail( - user.Email!, + user.Email, Arg.Is(url => url.Contains("token=reset-token") && url.Contains("email=test@example.com"))); } @@ -78,7 +77,7 @@ public async Task Handle_ShouldGenerateCorrectQueryString_WhenSendingEmail() // Assert await _emailService.Received(1).SendPasswordResetMail( - user.Email!, + user.Email, Arg.Is(url => url == QueryHelpers.AddQueryString(command.ReturnUri, new Dictionary { diff --git a/backend/ECondo.Application.UnitTests/Commands/Identity/GenerateAccessTokenCommandHandlerTests.cs b/backend/ECondo.Application.UnitTests/Commands/Identity/GenerateAccessTokenCommandHandlerTests.cs index 50f3d00..c4ac3a2 100644 --- a/backend/ECondo.Application.UnitTests/Commands/Identity/GenerateAccessTokenCommandHandlerTests.cs +++ b/backend/ECondo.Application.UnitTests/Commands/Identity/GenerateAccessTokenCommandHandlerTests.cs @@ -2,10 +2,10 @@ using ECondo.Application.Services; using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.AspNetCore.Identity; using NSubstitute; -using Xunit; namespace ECondo.Application.UnitTests.Commands.Identity.GenerateAccessToken; diff --git a/backend/ECondo.Application.UnitTests/Commands/Identity/InvalidateRefreshTokenCommandHandlerTests.cs b/backend/ECondo.Application.UnitTests/Commands/Identity/InvalidateRefreshTokenCommandHandlerTests.cs index 2fc71d5..c69de75 100644 --- a/backend/ECondo.Application.UnitTests/Commands/Identity/InvalidateRefreshTokenCommandHandlerTests.cs +++ b/backend/ECondo.Application.UnitTests/Commands/Identity/InvalidateRefreshTokenCommandHandlerTests.cs @@ -1,9 +1,8 @@ using ECondo.Application.Commands.Identity.InvalidateRefreshToken; using ECondo.Application.Services; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using FluentAssertions; using NSubstitute; -using Xunit; namespace ECondo.Application.UnitTests.Commands.Identity.InvalidateRefreshToken; diff --git a/backend/ECondo.Application.UnitTests/Commands/Identity/LoginCommandHandlerTests.cs b/backend/ECondo.Application.UnitTests/Commands/Identity/LoginCommandHandlerTests.cs index a92b26c..e7bc31a 100644 --- a/backend/ECondo.Application.UnitTests/Commands/Identity/LoginCommandHandlerTests.cs +++ b/backend/ECondo.Application.UnitTests/Commands/Identity/LoginCommandHandlerTests.cs @@ -4,18 +4,16 @@ using ECondo.Application.Data; using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using FluentAssertions; -using FluentAssertions.Collections; using Microsoft.AspNetCore.Identity; using NSubstitute; -using Xunit; namespace ECondo.Application.UnitTests.Commands.Identity.Login; public class LoginCommandHandlerTests { private readonly UserManager _userManager; - private readonly IdentityErrorDescriber _errorDescriber; private readonly IAuthTokenService _authTokenService; private readonly LoginCommandHandler _handler; @@ -24,9 +22,9 @@ public LoginCommandHandlerTests() _userManager = Substitute.For>( Substitute.For>(), null, null, null, null, null, null, null, null); - _errorDescriber = new IdentityErrorDescriber(); + var errorDescriber = new IdentityErrorDescriber(); _authTokenService = Substitute.For(); - _handler = new LoginCommandHandler(_userManager, _errorDescriber, _authTokenService); + _handler = new LoginCommandHandler(_userManager, errorDescriber, _authTokenService); } [Fact] diff --git a/backend/ECondo.Application.UnitTests/Commands/Identity/RegisterCommandHandlerTests.cs b/backend/ECondo.Application.UnitTests/Commands/Identity/RegisterCommandHandlerTests.cs index 90cfd2e..4af8f7b 100644 --- a/backend/ECondo.Application.UnitTests/Commands/Identity/RegisterCommandHandlerTests.cs +++ b/backend/ECondo.Application.UnitTests/Commands/Identity/RegisterCommandHandlerTests.cs @@ -1,40 +1,34 @@ using System.Linq.Expressions; using ECondo.Application.Commands.Identity.Register; using ECondo.Application.Events.Identity; -using ECondo.Application.Extensions; using ECondo.Application.Repositories; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using FluentAssertions; using MediatR; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using NSubstitute; -using Xunit; namespace ECondo.Application.UnitTests.Commands.Identity.Register; public class RegisterCommandHandlerTests { private readonly UserManager _userManager; - private readonly IUserStore _userStore; private readonly IApplicationDbContext _dbContext; - private readonly IdentityErrorDescriber _errorDescriber; private readonly IPublisher _publisher; private readonly RegisterCommandHandler _handler; - private readonly IUserEmailStore _emailStore; public RegisterCommandHandlerTests() { _userManager = Substitute.For>( Substitute.For>(), null, null, null, null, null, null, null, null); - _userStore = Substitute.For, IUserEmailStore>(); - _emailStore = (IUserEmailStore)_userStore; + var userStore = Substitute.For, IUserEmailStore>(); _dbContext = Substitute.For(); - _errorDescriber = new IdentityErrorDescriber(); + var errorDescriber = new IdentityErrorDescriber(); _publisher = Substitute.For(); - _handler = new RegisterCommandHandler(_userManager, _userStore, _dbContext, _errorDescriber, _publisher); + _handler = new RegisterCommandHandler(_userManager, userStore, _dbContext, errorDescriber, _publisher); } [Fact] diff --git a/backend/ECondo.Application.UnitTests/Commands/Identity/ResetPasswordCommandHandlerTests.cs b/backend/ECondo.Application.UnitTests/Commands/Identity/ResetPasswordCommandHandlerTests.cs index 601c6b4..8148f32 100644 --- a/backend/ECondo.Application.UnitTests/Commands/Identity/ResetPasswordCommandHandlerTests.cs +++ b/backend/ECondo.Application.UnitTests/Commands/Identity/ResetPasswordCommandHandlerTests.cs @@ -1,11 +1,9 @@ using ECondo.Application.Commands.Identity.ResetPassword; -using ECondo.Application.Extensions; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.AspNetCore.Identity; using NSubstitute; -using Xunit; namespace ECondo.Application.UnitTests.Commands.Identity { @@ -26,7 +24,7 @@ public async Task Handle_UserNotFound_ReturnsInvalidUserError() { // Arrange var command = new ResetPasswordCommand("test@example.com", "token", "newPassword"); - _userManager.FindByEmailAsync(command.Email).Returns((User)null); + _userManager.FindByEmailAsync(command.Email).Returns((User)null!); // Act var result = await _handler.Handle(command, CancellationToken.None); @@ -59,8 +57,8 @@ public async Task Handle_PasswordResetFails_ReturnsValidationError() result.Should().BeOfType.Error>(); var error = result.ToError().Data; error.Should().BeOfType(); - var validationError = (ValidationError)error; - validationError.Errors.Should().HaveCount(2); + var validationError = error as ValidationError; + validationError!.Errors.Should().HaveCount(2); validationError.Errors.Should().Contain(e => e.Code == "InvalidToken"); validationError.Errors.Should().Contain(e => e.Code == "PasswordRequiresDigit"); } @@ -125,8 +123,8 @@ public async Task Handle_WithEmptyPassword_ShouldFailValidation() result.Should().BeOfType.Error>(); var error = result.ToError().Data; error.Should().BeOfType(); - var validationError = (ValidationError)error; - validationError.Errors.Should().HaveCount(1); + var validationError = error as ValidationError; + validationError!.Errors.Should().HaveCount(1); validationError.Errors.Should().Contain(e => e.Code == "PasswordTooShort"); } } diff --git a/backend/ECondo.Application.UnitTests/Commands/Identity/UpdatePasswordCommandHandlerTests.cs b/backend/ECondo.Application.UnitTests/Commands/Identity/UpdatePasswordCommandHandlerTests.cs index 3f2c8b3..9cb6d30 100644 --- a/backend/ECondo.Application.UnitTests/Commands/Identity/UpdatePasswordCommandHandlerTests.cs +++ b/backend/ECondo.Application.UnitTests/Commands/Identity/UpdatePasswordCommandHandlerTests.cs @@ -1,19 +1,16 @@ using ECondo.Application.Commands.Identity.UpdatePassword; -using ECondo.Application.Extensions; using ECondo.Application.Services; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using FluentAssertions; using Microsoft.AspNetCore.Identity; using NSubstitute; -using Xunit; namespace ECondo.Application.UnitTests.Commands.Identity { public class UpdatePasswordCommandHandlerTests { private readonly UserManager _userManager; - private readonly IUserContext _userContext; private readonly UpdatePasswordCommandHandler _handler; private readonly Guid _userId = Guid.NewGuid(); @@ -21,9 +18,9 @@ public UpdatePasswordCommandHandlerTests() { _userManager = Substitute.For>( Substitute.For>(), null, null, null, null, null, null, null, null); - _userContext = Substitute.For(); - _userContext.UserId.Returns(_userId); - _handler = new UpdatePasswordCommandHandler(_userManager, _userContext); + var userContext = Substitute.For(); + userContext.UserId.Returns(_userId); + _handler = new UpdatePasswordCommandHandler(_userManager, userContext); } [Fact] @@ -31,7 +28,7 @@ public async Task Handle_UserNotFound_ReturnsInvalidUserError() { // Arrange var command = new UpdatePasswordCommand("currentPassword", "newPassword"); - _userManager.FindByIdAsync(_userId.ToString()).Returns((User)null); + _userManager.FindByIdAsync(_userId.ToString()).Returns((User)null!); // Act var result = await _handler.Handle(command, CancellationToken.None); @@ -64,8 +61,8 @@ public async Task Handle_ChangePasswordFails_ReturnsValidationError() result.Should().BeOfType.Error>(); var error = result.ToError().Data; error.Should().BeOfType(); - var validationError = (ValidationError)error; - validationError.Errors.Should().HaveCount(2); + var validationError = error as ValidationError; + validationError!.Errors.Should().HaveCount(2); validationError.Errors.Should().Contain(e => e.Code == "PasswordMismatch"); validationError.Errors.Should().Contain(e => e.Code == "PasswordRequiresNonAlphanumeric"); } @@ -135,8 +132,8 @@ public async Task Handle_WithEmptyNewPassword_ShouldFail() result.Should().BeOfType.Error>(); var error = result.ToError().Data; error.Should().BeOfType(); - var validationError = (ValidationError)error; - validationError.Errors.Should().HaveCount(1); + var validationError = error as ValidationError; + validationError!.Errors.Should().HaveCount(1); validationError.Errors.Should().Contain(e => e.Code == "PasswordTooShort"); } @@ -162,8 +159,8 @@ public async Task Handle_SameOldAndNewPassword_ShouldFail() result.Should().BeOfType.Error>(); var error = result.ToError().Data; error.Should().BeOfType(); - var validationError = (ValidationError)error; - validationError.Errors.Should().HaveCount(1); + var validationError = error as ValidationError; + validationError!.Errors.Should().HaveCount(1); validationError.Errors.Should().Contain(e => e.Code == "PasswordRequiresUniqueChars"); } } diff --git a/backend/ECondo.Application.UnitTests/ECondo.Application.UnitTests.csproj b/backend/ECondo.Application.UnitTests/ECondo.Application.UnitTests.csproj index ed73478..d14e912 100644 --- a/backend/ECondo.Application.UnitTests/ECondo.Application.UnitTests.csproj +++ b/backend/ECondo.Application.UnitTests/ECondo.Application.UnitTests.csproj @@ -20,6 +20,7 @@ + diff --git a/backend/ECondo.Application.UnitTests/Helper/DbSetMockHelper.cs b/backend/ECondo.Application.UnitTests/Helper/DbSetMockHelper.cs new file mode 100644 index 0000000..dde6d64 --- /dev/null +++ b/backend/ECondo.Application.UnitTests/Helper/DbSetMockHelper.cs @@ -0,0 +1,19 @@ +using Microsoft.EntityFrameworkCore; +using NSubstitute; + +namespace ECondo.Application.UnitTests.Helper; + +public static class DbSetMockHelper +{ + public static DbSet CreateMockDbSet(IQueryable data) where T : class + { + var mockSet = Substitute.For, IQueryable>(); + ((IQueryable)mockSet).Provider.Returns(new TestAsyncQueryProvider(data.Provider)); + ((IQueryable)mockSet).Expression.Returns(data.Expression); + ((IQueryable)mockSet).ElementType.Returns(data.ElementType); + using var enumerator = ((IQueryable)mockSet).GetEnumerator(); + using var returnThis = data.GetEnumerator(); + enumerator.Returns(returnThis); + return mockSet; + } +} \ No newline at end of file diff --git a/backend/ECondo.Application.UnitTests/Helper/TestMockAsyncQueryProvider.cs b/backend/ECondo.Application.UnitTests/Helper/TestMockAsyncQueryProvider.cs index 6dd9617..053f536 100644 --- a/backend/ECondo.Application.UnitTests/Helper/TestMockAsyncQueryProvider.cs +++ b/backend/ECondo.Application.UnitTests/Helper/TestMockAsyncQueryProvider.cs @@ -1,61 +1,80 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Query; -public class TestAsyncQueryProvider : IAsyncQueryProvider -{ - private readonly IQueryProvider _inner; +namespace ECondo.Application.UnitTests.Helper; - public TestAsyncQueryProvider(IQueryProvider inner) +public class TestAsyncQueryProvider(IQueryProvider inner) : IAsyncQueryProvider +{ + public IQueryable CreateQuery(Expression expression) { - _inner = inner; + var createQueryMethod = inner.GetType().GetMethod("CreateQuery", [typeof(Expression)]); + return (IQueryable)createQueryMethod!.Invoke(inner, [expression])!; } - public IQueryable CreateQuery(Expression expression) - => new TestAsyncEnumerable(expression); - public IQueryable CreateQuery(Expression expression) - => new TestAsyncEnumerable(expression); + { + return new TestAsyncEnumerable(inner.CreateQuery(expression)); + } public object? Execute(Expression expression) - => _inner.Execute(expression); + => inner.Execute(expression); public TResult Execute(Expression expression) - => _inner.Execute(expression); + => inner.Execute(expression); - public TResult ExecuteAsync(Expression expression, CancellationToken cancellationToken) - => _inner.Execute(expression); + public TResult ExecuteAsync(Expression expression, CancellationToken cancellationToken = default) + { + var resultType = typeof(TResult); + + if (resultType.IsGenericType && resultType.GetGenericTypeDefinition() == typeof(Task<>)) + { + var taskResultType = resultType.GetGenericArguments()[0]; + var syncResult = inner.Execute(expression); + + // Create Task from the result using reflection + var taskFromResult = typeof(Task) + .GetMethod(nameof(Task.FromResult))! + .MakeGenericMethod(taskResultType) + .Invoke(null, [syncResult]); + + return (TResult)taskFromResult!; + } + + if (resultType == typeof(Task)) + { + return (TResult)(object)Task.CompletedTask; + } + + return (TResult)inner.Execute(expression)!; + } } public class TestAsyncEnumerable : EnumerableQuery, IAsyncEnumerable, IQueryable { - public TestAsyncEnumerable(IEnumerable enumerable) - : base(enumerable) { } + public TestAsyncEnumerable(IEnumerable enumerable) : base(enumerable) { } - public TestAsyncEnumerable(Expression expression) - : base(expression) { } + public TestAsyncEnumerable(Expression expression) : base(expression) { } public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - => new TestAsyncEnumerator(this.AsEnumerable().GetEnumerator()); + { + return new TestAsyncEnumerator(this.AsEnumerable().GetEnumerator()); + } - IQueryProvider IQueryable.Provider - => new TestAsyncQueryProvider(this); + IQueryProvider IQueryable.Provider => new TestAsyncQueryProvider(this); } -public class TestAsyncEnumerator : IAsyncEnumerator +public class TestAsyncEnumerator(IEnumerator inner) : IAsyncEnumerator { - private readonly IEnumerator _inner; + public T Current => inner.Current; - public TestAsyncEnumerator(IEnumerator inner) - => _inner = inner; - - public T Current => _inner.Current; + public ValueTask MoveNextAsync() + { + return ValueTask.FromResult(inner.MoveNext()); + } public ValueTask DisposeAsync() { - _inner.Dispose(); + inner.Dispose(); return ValueTask.CompletedTask; } - - public ValueTask MoveNextAsync() - => ValueTask.FromResult(_inner.MoveNext()); } \ No newline at end of file diff --git a/backend/ECondo.Application/Authorization/BillAuthorizationHandler.cs b/backend/ECondo.Application/Authorization/BillAuthorizationHandler.cs new file mode 100644 index 0000000..3e75a9a --- /dev/null +++ b/backend/ECondo.Application/Authorization/BillAuthorizationHandler.cs @@ -0,0 +1,54 @@ +using ECondo.Application.Extensions; +using ECondo.Application.Repositories; +using ECondo.Domain.Authorization; +using ECondo.Domain.Payments; +using Microsoft.EntityFrameworkCore; + +namespace ECondo.Application.Authorization; + +public sealed class BillAuthorizationHandler + (IApplicationDbContext dbContext) + : IResourceAuthorizationHandler +{ + public async Task GetAccessLevelAsync(Guid userId, Guid? resourceId, CancellationToken cancellationToken = default) + { + if (await dbContext + .UserRoles + .IsAdminAsync(userId, cancellationToken)) + return AccessLevel.All; + + if (!resourceId.HasValue) + return AccessLevel.None; + + var authData = await dbContext + .Bills + .AsNoTracking() + .Where(e => e.Id == resourceId) + .Select(b => new + { + IsManager = b.Entrance.ManagerId == userId, + IsOccupant = b.Entrance.Properties.Any(p => p.PropertyOccupants.Any(po => po.UserId == userId)) + }) + .FirstOrDefaultAsync(cancellationToken: cancellationToken); + + if (authData is null) + return AccessLevel.None; + + if (authData.IsManager) + return AccessLevel.All; + + return authData.IsOccupant ? AccessLevel.Read : AccessLevel.None; + } + + public async Task> ApplyDataFilterAsync(IQueryable query, Guid userId, CancellationToken cancellationToken = default) + { + if (await dbContext + .UserRoles + .IsAdminAsync(userId, cancellationToken)) + return query; + + return query.Where(b => + b.Entrance.ManagerId == userId || + b.Entrance.Properties.Any(p => p.PropertyOccupants.Any(po => po.UserId == userId))); + } +} diff --git a/backend/ECondo.Application/Authorization/DefaultAuthorizationHandler.cs b/backend/ECondo.Application/Authorization/DefaultAuthorizationHandler.cs new file mode 100644 index 0000000..afb98ec --- /dev/null +++ b/backend/ECondo.Application/Authorization/DefaultAuthorizationHandler.cs @@ -0,0 +1,16 @@ +using ECondo.Domain.Authorization; + +namespace ECondo.Application.Authorization; + +public sealed class DefaultAuthorizationHandler : IResourceAuthorizationHandler where T : class +{ + public Task> ApplyDataFilterAsync(IQueryable query, Guid userId, CancellationToken cancellationToken = default) + { + return Task.FromResult(query); + } + + public Task GetAccessLevelAsync(Guid userId, Guid? resourceId, CancellationToken cancellationToken = default) + { + return Task.FromResult(AccessLevel.None); + } +} diff --git a/backend/ECondo.Application/Authorization/EntranceAuthorizationHandler.cs b/backend/ECondo.Application/Authorization/EntranceAuthorizationHandler.cs new file mode 100644 index 0000000..4535d96 --- /dev/null +++ b/backend/ECondo.Application/Authorization/EntranceAuthorizationHandler.cs @@ -0,0 +1,52 @@ +using ECondo.Application.Extensions; +using ECondo.Application.Repositories; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; +using Microsoft.EntityFrameworkCore; + +namespace ECondo.Application.Authorization; + +public sealed class EntranceAuthorizationHandler + (IApplicationDbContext dbContext) : + IResourceAuthorizationHandler +{ + public async Task GetAccessLevelAsync(Guid userId, + Guid? resourceId, + CancellationToken cancellationToken = default) + { + if (await dbContext + .UserRoles + .IsAdminAsync(userId, cancellationToken)) + return AccessLevel.All; + + if (!resourceId.HasValue) + return AccessLevel.Read; + + var isManager = await dbContext + .Entrances + .AsNoTracking() + .AnyAsync(e => + e.Id == resourceId && + e.ManagerId == userId, + cancellationToken: cancellationToken); + + if (isManager) + return AccessLevel.All; + + return AccessLevel.None; + } + + public async Task> ApplyDataFilterAsync( + IQueryable query, + Guid userId, + CancellationToken cancellationToken = default) + { + if (await dbContext + .UserRoles + .IsAdminAsync(userId, cancellationToken)) + return query; + + return query.Where(e => + e.ManagerId == userId); + } +} \ No newline at end of file diff --git a/backend/ECondo.Application/Authorization/IResourceAuthorizationHandler.cs b/backend/ECondo.Application/Authorization/IResourceAuthorizationHandler.cs new file mode 100644 index 0000000..bb02498 --- /dev/null +++ b/backend/ECondo.Application/Authorization/IResourceAuthorizationHandler.cs @@ -0,0 +1,14 @@ +using ECondo.Domain.Authorization; + +namespace ECondo.Application.Authorization; + +public interface IResourceAuthorizationHandler where T : class +{ + Task GetAccessLevelAsync(Guid userId, + Guid? resourceId, + CancellationToken cancellationToken = default); + + Task> ApplyDataFilterAsync(IQueryable query, + Guid userId, + CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/backend/ECondo.Application/Authorization/OccupantAuthorizationHandler.cs b/backend/ECondo.Application/Authorization/OccupantAuthorizationHandler.cs new file mode 100644 index 0000000..81cf720 --- /dev/null +++ b/backend/ECondo.Application/Authorization/OccupantAuthorizationHandler.cs @@ -0,0 +1,64 @@ +using ECondo.Application.Extensions; +using ECondo.Application.Repositories; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; +using Microsoft.EntityFrameworkCore; + +namespace ECondo.Application.Authorization; + +public sealed class OccupantAuthorizationHandler + (IApplicationDbContext dbContext) + : IResourceAuthorizationHandler +{ + public async Task GetAccessLevelAsync(Guid userId, Guid? resourceId, CancellationToken cancellationToken = default) + { + if (await dbContext + .UserRoles + .IsAdminAsync(userId, cancellationToken)) + return AccessLevel.All; + + if (!resourceId.HasValue) + return AccessLevel.None; + + var authData = await dbContext + .PropertyOccupants + .AsNoTracking() + .Where(p => p.Id == resourceId) + .Select(po => new + { + IsManager = po.Property.Entrance.ManagerId == userId, + TypeName = po.Property + .PropertyOccupants + .Where(po2 => po2.UserId == userId) + .Select(po2 => po2.OccupantType.Name) + .FirstOrDefault() + }) + .FirstOrDefaultAsync(cancellationToken: cancellationToken); + + if (authData is null) + return AccessLevel.None; + + if (authData.IsManager) + return AccessLevel.All; + + if (authData.TypeName is null) + return AccessLevel.None; + + return authData.TypeName == OccupantType.OwnerType ? AccessLevel.All : AccessLevel.Read; + } + + public async Task> ApplyDataFilterAsync(IQueryable query, Guid userId, CancellationToken cancellationToken = default) + { + if (await dbContext + .UserRoles + .IsAdminAsync(userId, cancellationToken)) + return query; + + return query.Where(po => + po.Property.Entrance.ManagerId == userId || // User manages the entrance + po.Property.PropertyOccupants.Any(po2 => + po2.UserId == userId && po2.OccupantType.Name == OccupantType.OwnerType) || // User owns the property + po.UserId == userId // User's own occupancy record + ); + } +} diff --git a/backend/ECondo.Application/Authorization/PropertyAuthorizationHandler.cs b/backend/ECondo.Application/Authorization/PropertyAuthorizationHandler.cs new file mode 100644 index 0000000..9ce3b6d --- /dev/null +++ b/backend/ECondo.Application/Authorization/PropertyAuthorizationHandler.cs @@ -0,0 +1,54 @@ +using ECondo.Application.Extensions; +using ECondo.Application.Repositories; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; +using Microsoft.EntityFrameworkCore; + +namespace ECondo.Application.Authorization; + +public sealed class PropertyAuthorizationHandler + (IApplicationDbContext dbContext) + : IResourceAuthorizationHandler +{ + public async Task GetAccessLevelAsync(Guid userId, Guid? resourceId, CancellationToken cancellationToken = default) + { + if (await dbContext + .UserRoles + .IsAdminAsync(userId, cancellationToken)) + return AccessLevel.All; + + if (!resourceId.HasValue) + return AccessLevel.Read; + + var authData = await dbContext + .Properties + .Where(p => p.Id == resourceId) + .Select(p => new + { + IsManager = p.Entrance.ManagerId == userId, + IsOccupant = p.PropertyOccupants.Any(po => po.UserId == userId) + }) + .AsNoTracking() + .FirstOrDefaultAsync(cancellationToken: cancellationToken); + + if (authData is null) + return AccessLevel.None; + + if (authData.IsManager) + return AccessLevel.All; + + return authData.IsOccupant ? AccessLevel.Read : AccessLevel.None; + } + + public async Task> ApplyDataFilterAsync(IQueryable query, Guid userId, CancellationToken cancellationToken = default) + { + if (await dbContext + .UserRoles + .IsAdminAsync(userId, cancellationToken)) + return query; + + return query.Where(p => + p.Entrance.ManagerId == userId || + p.PropertyOccupants.Any(po => po.UserId == userId)); + } +} \ No newline at end of file diff --git a/backend/ECondo.Application/Authorization/UserAuthorizationHandler.cs b/backend/ECondo.Application/Authorization/UserAuthorizationHandler.cs new file mode 100644 index 0000000..13c1b57 --- /dev/null +++ b/backend/ECondo.Application/Authorization/UserAuthorizationHandler.cs @@ -0,0 +1,17 @@ +using ECondo.Domain.Authorization; +using ECondo.Domain.Users; + +namespace ECondo.Application.Authorization; + +internal sealed class UserAuthorizationHandler : IResourceAuthorizationHandler +{ + public Task GetAccessLevelAsync(Guid userId, Guid? resourceId, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public Task> ApplyDataFilterAsync(IQueryable query, Guid userId, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/backend/ECondo.Application/Behaviours/AccessPropertyAuthorizationPipelineBehaviour.cs b/backend/ECondo.Application/Behaviours/AccessPropertyAuthorizationPipelineBehaviour.cs deleted file mode 100644 index 25e6c6e..0000000 --- a/backend/ECondo.Application/Behaviours/AccessPropertyAuthorizationPipelineBehaviour.cs +++ /dev/null @@ -1,53 +0,0 @@ -using ECondo.Application.Extensions; -using ECondo.Application.Policies; -using ECondo.Application.Repositories; -using ECondo.Application.Services; -using ECondo.Application.Shared; -using ECondo.Domain.Buildings; -using ECondo.Domain.Exceptions; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace ECondo.Application.Behaviours; - -internal sealed class AccessPropertyAuthorizationPipelineBehaviour - - (IUserContext userContext, IApplicationDbContext dbContext) - : IPipelineBehavior - where TRequest : ICanSeeProperty -{ - public async Task Handle( - TRequest request, - RequestHandlerDelegate next, - CancellationToken cancellationToken) - { - var isAdmin = await dbContext - .UserRoles - .IsAdminAsync(userContext.UserId, cancellationToken: cancellationToken); - - var canSee = await dbContext - .Properties - .AsNoTracking() - .Where(p => - (p.Id == request.PropertyId && - (p.Entrance.ManagerId == userContext.UserId || - p.PropertyOccupants.Any(po => po.UserId == userContext.UserId))) || - isAdmin) - .AnyAsync(cancellationToken: cancellationToken); - - if (canSee) - return await next(); - - if (Utils.IsTypeResultType()) - { - var res = Utils.InvokeResultFail( - [PropertyErrors.Forbidden(request.PropertyId)]); - - if (res is not null) - return res; - } - - throw new ForbiddenException(); - } - -} \ No newline at end of file diff --git a/backend/ECondo.Application/Behaviours/AccessTenantAuthorizationPipelineBehaviour.cs b/backend/ECondo.Application/Behaviours/AccessTenantAuthorizationPipelineBehaviour.cs deleted file mode 100644 index 623da2d..0000000 --- a/backend/ECondo.Application/Behaviours/AccessTenantAuthorizationPipelineBehaviour.cs +++ /dev/null @@ -1,44 +0,0 @@ -using ECondo.Application.Policies; -using ECondo.Application.Repositories; -using ECondo.Application.Services; -using ECondo.Application.Shared; -using ECondo.Domain.Buildings; -using ECondo.Domain.Exceptions; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace ECondo.Application.Behaviours; - -internal sealed class AccessTenantAuthorizationPipelineBehaviour - - (IUserContext userContext, IApplicationDbContext dbContext) - : IPipelineBehavior - where TRequest : ICanSeeTenants -{ - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) - { - var canSee = await dbContext - .Properties - .AsNoTracking() - .Where(p => - p.Id == request.PropertyId && - p.PropertyOccupants.Any(po => - po.UserId == userContext.UserId && - po.OccupantType.Name == "Собственик")) - .AnyAsync(cancellationToken: cancellationToken); - - if (canSee) - return await next(); - - if (Utils.IsTypeResultType()) - { - var res = Utils.InvokeResultFail( - [PropertyErrors.Forbidden(request.PropertyId)]); - - if (res is not null) - return res; - } - - throw new ForbiddenException(); - } -} \ No newline at end of file diff --git a/backend/ECondo.Application/Behaviours/AddOccupantAuthorizationPipelineBehaviour.cs b/backend/ECondo.Application/Behaviours/AddOccupantAuthorizationPipelineBehaviour.cs deleted file mode 100644 index f72c30f..0000000 --- a/backend/ECondo.Application/Behaviours/AddOccupantAuthorizationPipelineBehaviour.cs +++ /dev/null @@ -1,46 +0,0 @@ -using ECondo.Application.Policies; -using ECondo.Application.Repositories; -using ECondo.Application.Services; -using ECondo.Application.Shared; -using ECondo.Domain.Buildings; -using ECondo.Domain.Exceptions; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace ECondo.Application.Behaviours; - -internal sealed class AddOccupantAuthorizationPipelineBehaviour - - (IUserContext userContext, IApplicationDbContext dbContext) - : IPipelineBehavior - where TRequest : ICanAddOccupant -{ - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) - { - var canAdd = await dbContext - .Properties - .AsNoTracking() - .Where(p => - p.Id == request.PropertyId && - (p.Entrance.ManagerId == userContext.UserId || - (p.PropertyOccupants.Any(po => - po.UserId == userContext.UserId && - po.OccupantType.Name == "Собственик") && - request.OccupantType != "Собственик"))) - .AnyAsync(cancellationToken: cancellationToken); - - if (canAdd) - return await next(); - - if (Utils.IsTypeResultType()) - { - var res = Utils.InvokeResultFail( - [PropertyErrors.Forbidden(request.PropertyId)]); - - if (res is not null) - return res; - } - - throw new ForbiddenException(); - } -} \ No newline at end of file diff --git a/backend/ECondo.Application/Behaviours/AdminAuthorizationPipelineBehaviour.cs b/backend/ECondo.Application/Behaviours/AdminAuthorizationPipelineBehaviour.cs deleted file mode 100644 index b8210d8..0000000 --- a/backend/ECondo.Application/Behaviours/AdminAuthorizationPipelineBehaviour.cs +++ /dev/null @@ -1,44 +0,0 @@ -using ECondo.Application.Policies; -using ECondo.Application.Repositories; -using ECondo.Application.Services; -using ECondo.Application.Shared; -using ECondo.Domain.Exceptions; -using ECondo.Domain.Users; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace ECondo.Application.Behaviours; - -internal sealed class AdminAuthorizationPipelineBehaviour - - (IUserContext userContext, IApplicationDbContext dbContext) - : IPipelineBehavior - where TRequest : IIsAdmin -{ - public async Task Handle( - TRequest request, - RequestHandlerDelegate next, - CancellationToken cancellationToken) - { - var isAdmin = await dbContext - .UserRoles - .Where(ur => - ur.UserId == userContext.UserId && - ur.Role.Name == "admin") - .AnyAsync(cancellationToken: cancellationToken); - - if (isAdmin) - return await next(); - - if (Utils.IsTypeResultType()) - { - var res = Utils.InvokeResultFail( - [UserErrors.Forbidden(userContext.UserId)]); - - if (res is not null) - return res; - } - - throw new ForbiddenException(); - } -} \ No newline at end of file diff --git a/backend/ECondo.Application/Behaviours/AuthorizationPipelineBehaviour.cs b/backend/ECondo.Application/Behaviours/AuthorizationPipelineBehaviour.cs new file mode 100644 index 0000000..7310469 --- /dev/null +++ b/backend/ECondo.Application/Behaviours/AuthorizationPipelineBehaviour.cs @@ -0,0 +1,45 @@ +using System.Reflection; +using ECondo.Application.Services; +using ECondo.Domain.Authorization; +using ECondo.Domain.Exceptions; +using ECondo.SharedKernel.Extensions; +using ECondo.SharedKernel.Result; +using MediatR; + +namespace ECondo.Application.Behaviours; + +internal sealed class AuthorizationPipelineBehaviour + + (IAuthorizationService authorizationService, IUserContext userContext) + : IPipelineBehavior + where TRequest : IResourcePolicy +{ + public async Task Handle(TRequest request, + RequestHandlerDelegate next, + CancellationToken cancellationToken) + { + var canPerformActionMethod = GetCanPerformActionMethod(request); + var canPerformAction = (Task)canPerformActionMethod + .Invoke(authorizationService, + [userContext.UserId, request.ResourceId, + request.ResourceAction, cancellationToken])!; + + if (await canPerformAction) + return await next(); + + if(typeof(TResponse).IsResultType()) + return ResultHelper.InvokeResultFail( + [CreateForbiddenError()]); + + throw new ForbiddenException(); + } + + private static Error CreateForbiddenError() => + Error.Forbidden("Resource.Forbidden", + "The user does not have the needed permission"); + + private static MethodInfo GetCanPerformActionMethod(TRequest request) => + typeof(IAuthorizationService) + .GetMethod(nameof(IAuthorizationService.CanPerformActionAsync))! + .MakeGenericMethod(request.ResourceType); +} \ No newline at end of file diff --git a/backend/ECondo.Application/Behaviours/DeleteOccupantAuthorizationPipelineBehaviour.cs b/backend/ECondo.Application/Behaviours/DeleteOccupantAuthorizationPipelineBehaviour.cs deleted file mode 100644 index cacb521..0000000 --- a/backend/ECondo.Application/Behaviours/DeleteOccupantAuthorizationPipelineBehaviour.cs +++ /dev/null @@ -1,52 +0,0 @@ -using ECondo.Application.Extensions; -using ECondo.Application.Policies; -using ECondo.Application.Repositories; -using ECondo.Application.Services; -using ECondo.Application.Shared; -using ECondo.Domain.Buildings; -using ECondo.Domain.Exceptions; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace ECondo.Application.Behaviours; - -internal sealed class DeleteOccupantAuthorizationPipelineBehaviour - - (IUserContext userContext, IApplicationDbContext dbContext) - : IPipelineBehavior - where TRequest : ICanDeleteOccupant -{ - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) - { - var isAdmin = await dbContext - .UserRoles - .IsAdminAsync(userContext.UserId, cancellationToken: cancellationToken); - - var canDelete = await dbContext - .PropertyOccupants - .AsNoTracking() - .Where(p => - (p.Id == request.OccupantId && - (p.Property.Entrance.ManagerId == userContext.UserId || - (p.Property.PropertyOccupants.Any(po => - po.UserId == userContext.UserId && - po.OccupantType.Name == "Собственик") && - p.OccupantType.Name != "Собственик"))) || - isAdmin) - .AnyAsync(cancellationToken: cancellationToken); - - if (canDelete) - return await next(); - - if (Utils.IsTypeResultType()) - { - var res = Utils.InvokeResultFail( - [PropertyOccupantError.Forbidden(request.OccupantId)]); - - if (res is not null) - return res; - } - - throw new ForbiddenException(); - } -} \ No newline at end of file diff --git a/backend/ECondo.Application/Behaviours/EditBuildingEntranceAuthorizationPipelineBehaviour.cs b/backend/ECondo.Application/Behaviours/EditBuildingEntranceAuthorizationPipelineBehaviour.cs deleted file mode 100644 index cf7a5b5..0000000 --- a/backend/ECondo.Application/Behaviours/EditBuildingEntranceAuthorizationPipelineBehaviour.cs +++ /dev/null @@ -1,50 +0,0 @@ -using ECondo.Application.Extensions; -using ECondo.Application.Policies; -using ECondo.Application.Repositories; -using ECondo.Application.Services; -using ECondo.Application.Shared; -using ECondo.Domain.Buildings; -using ECondo.Domain.Exceptions; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace ECondo.Application.Behaviours; - -internal sealed class EditBuildingEntranceAuthorizationPipelineBehaviour - - (IUserContext userContext, IApplicationDbContext dbContext) - : IPipelineBehavior - where TRequest : ICanEditEntrance -{ - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) - { - var isAdmin = await dbContext - .UserRoles - .IsAdminAsync(userContext.UserId, - cancellationToken: cancellationToken); - - var canDelete = await dbContext - .Entrances - .AsNoTracking() - .Where(e => - (e.BuildingId == request.BuildingId && - e.Number == request.EntranceNumber && - e.ManagerId == userContext.UserId) || - isAdmin) - .AnyAsync(cancellationToken: cancellationToken); - - if (canDelete) - return await next(); - - if (Utils.IsTypeResultType()) - { - var res = Utils.InvokeResultFail( - [EntranceErrors.Forbidden(request.BuildingId, request.EntranceNumber)]); - - if (res is not null) - return res; - } - - throw new ForbiddenException(); - } -} \ No newline at end of file diff --git a/backend/ECondo.Application/Behaviours/EditOccupantAuthorizationPipelineBehaviour.cs b/backend/ECondo.Application/Behaviours/EditOccupantAuthorizationPipelineBehaviour.cs deleted file mode 100644 index 7ee67ed..0000000 --- a/backend/ECondo.Application/Behaviours/EditOccupantAuthorizationPipelineBehaviour.cs +++ /dev/null @@ -1,53 +0,0 @@ -using ECondo.Application.Extensions; -using ECondo.Application.Policies; -using ECondo.Application.Repositories; -using ECondo.Application.Services; -using ECondo.Application.Shared; -using ECondo.Domain.Buildings; -using ECondo.Domain.Exceptions; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace ECondo.Application.Behaviours; - -internal sealed class EditOccupantAuthorizationPipelineBehaviour - - (IUserContext userContext, IApplicationDbContext dbContext) - : IPipelineBehavior - where TRequest : ICanEditOccupant -{ - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) - { - var isAdmin = await dbContext - .UserRoles - .IsAdminAsync(userContext.UserId, cancellationToken: cancellationToken); - - var canEdit = await dbContext - .PropertyOccupants - .AsNoTracking() - .Where(p => - (p.Id == request.OccupantId && - (p.Property.Entrance.ManagerId == userContext.UserId || - (p.Property.PropertyOccupants.Any(po => - po.UserId == userContext.UserId && - po.OccupantType.Name == "Собственик") && - request.Type != "Собственик" && - p.OccupantType.Name != "Собственик"))) || - isAdmin) - .AnyAsync(cancellationToken: cancellationToken); - - if (canEdit) - return await next(); - - if (Utils.IsTypeResultType()) - { - var res = Utils.InvokeResultFail( - [PropertyOccupantError.Forbidden(request.OccupantId)]); - - if (res is not null) - return res; - } - - throw new ForbiddenException(); - } -} \ No newline at end of file diff --git a/backend/ECondo.Application/Behaviours/EditPropertyAuthorizationPipelineBehaviour.cs b/backend/ECondo.Application/Behaviours/EditPropertyAuthorizationPipelineBehaviour.cs deleted file mode 100644 index 9b98b98..0000000 --- a/backend/ECondo.Application/Behaviours/EditPropertyAuthorizationPipelineBehaviour.cs +++ /dev/null @@ -1,53 +0,0 @@ -using ECondo.Application.Extensions; -using ECondo.Application.Policies; -using ECondo.Application.Repositories; -using ECondo.Application.Services; -using ECondo.Application.Shared; -using ECondo.Domain.Buildings; -using ECondo.Domain.Exceptions; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace ECondo.Application.Behaviours; - -internal sealed class EditPropertyAuthorizationPipelineBehaviour - - (IUserContext userContext, IApplicationDbContext dbContext) - : IPipelineBehavior - where TRequest : ICanEditProperty -{ - public async Task Handle( - TRequest request, - RequestHandlerDelegate next, - CancellationToken cancellationToken) - { - var isAdmin = await dbContext - .UserRoles - .IsAdminAsync(userContext.UserId, - cancellationToken: cancellationToken); - - var canEdit = await dbContext - .Properties - .AsNoTracking() - .Where(p => - (p.Id == request.PropertyId && - p.Entrance.ManagerId == userContext.UserId) || - isAdmin) - .AnyAsync(cancellationToken: cancellationToken); - - if (canEdit) - return await next(); - - if (Utils.IsTypeResultType()) - { - var res = Utils.InvokeResultFail( - [PropertyErrors.Forbidden(request.PropertyId)]); - - if (res is not null) - return res; - } - - throw new ForbiddenException(); - } - -} \ No newline at end of file diff --git a/backend/ECondo.Application/Behaviours/EntranceManagerAuthorizationPipelineBehaviour.cs b/backend/ECondo.Application/Behaviours/EntranceManagerAuthorizationPipelineBehaviour.cs deleted file mode 100644 index 50f9115..0000000 --- a/backend/ECondo.Application/Behaviours/EntranceManagerAuthorizationPipelineBehaviour.cs +++ /dev/null @@ -1,47 +0,0 @@ -using ECondo.Application.Policies; -using ECondo.Application.Repositories; -using ECondo.Application.Services; -using ECondo.Application.Shared; -using ECondo.Domain.Exceptions; -using ECondo.Domain.Shared; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace ECondo.Application.Behaviours; - -internal sealed class EntranceManagerAuthorizationPipelineBehaviour - - (IUserContext userContext, IApplicationDbContext dbContext) - : IPipelineBehavior - where TRequest : IRequireEntranceManager - -{ - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) - { - var isManager = await dbContext - .Entrances - .AsNoTracking() - .AnyAsync(e => - e.BuildingId == request.BuildingId && - e.Number == request.EntranceNumber && - e.ManagerId == userContext.UserId, - cancellationToken: cancellationToken); - - if (isManager) - return await next(); - - if (Utils.IsTypeResultType()) - { - var res = Utils.InvokeResultFail( - [CreateForbiddenError()]); - - if (res is not null) - return res; - } - - throw new ForbiddenException(); - } - - private static Error CreateForbiddenError() => - Error.Forbidden("Entrance.Forbidden", "The User can not access the entrance"); -} \ No newline at end of file diff --git a/backend/ECondo.Application/Behaviours/ValidationPipelineBehaviour.cs b/backend/ECondo.Application/Behaviours/ValidationPipelineBehaviour.cs index 3ffb06b..0d98f66 100644 --- a/backend/ECondo.Application/Behaviours/ValidationPipelineBehaviour.cs +++ b/backend/ECondo.Application/Behaviours/ValidationPipelineBehaviour.cs @@ -1,4 +1,5 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Extensions; +using ECondo.SharedKernel.Result; using FluentValidation.Results; using FluentValidation; using MediatR; @@ -18,26 +19,10 @@ public async Task Handle( ValidationFailure[] validationFailures = await ValidateAsync(request); if (validationFailures.Length == 0) - { return await next(); - } - - if (typeof(TResponse).IsGenericType && - typeof(TResponse).GetGenericTypeDefinition() == typeof(Result<,>)) - { - Type resultType = typeof(TResponse).GetGenericArguments()[0]; - var failMethodInfo = typeof(Result<,>) - .MakeGenericType(resultType, typeof(Error)) - .GetMethod(nameof(Result.Fail)); - object? res = failMethodInfo?.Invoke( - null, - [CreateValidationError(validationFailures)]); - - if(res is not null) - return (TResponse)res; - - } + if (typeof(TResponse).IsResultType()) + return ResultHelper.InvokeResultFail([CreateValidationError(validationFailures)]); throw new ValidationException(validationFailures); } diff --git a/backend/ECondo.Application/Commands/Buildings/Delete/DeleteBuildingEntranceCommand.cs b/backend/ECondo.Application/Commands/Buildings/Delete/DeleteBuildingEntranceCommand.cs index 5dbd7ab..7581305 100644 --- a/backend/ECondo.Application/Commands/Buildings/Delete/DeleteBuildingEntranceCommand.cs +++ b/backend/ECondo.Application/Commands/Buildings/Delete/DeleteBuildingEntranceCommand.cs @@ -1,6 +1,11 @@ -using ECondo.Application.Policies; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; namespace ECondo.Application.Commands.Buildings.Delete; -public record DeleteBuildingEntranceCommand(Guid BuildingId, string EntranceNumber) : - ICommand, ICanEditEntrance; \ No newline at end of file +public record DeleteBuildingEntranceCommand( + Guid EntranceId) : + ICommand, ICanUpdate +{ + Guid? IResourcePolicy.ResourceId => EntranceId; +} \ No newline at end of file diff --git a/backend/ECondo.Application/Commands/Buildings/Delete/DeleteBuildingEntranceCommandHandler.cs b/backend/ECondo.Application/Commands/Buildings/Delete/DeleteBuildingEntranceCommandHandler.cs index e3c287b..f70a5c2 100644 --- a/backend/ECondo.Application/Commands/Buildings/Delete/DeleteBuildingEntranceCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Buildings/Delete/DeleteBuildingEntranceCommandHandler.cs @@ -1,5 +1,5 @@ using ECondo.Application.Repositories; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.Buildings.Delete; @@ -17,7 +17,7 @@ public async Task> Handle( .Include(e => e.Properties) .ThenInclude(e => e.PropertyOccupants) .FirstAsync(e => - e.BuildingId == request.BuildingId && e.Number == request.EntranceNumber, + e.Id == request.EntranceId, cancellationToken: cancellationToken); foreach (var property in entrance.Properties) diff --git a/backend/ECondo.Application/Commands/Buildings/RegisterEntrance/RegisterBuildingEntranceCommandHandler.cs b/backend/ECondo.Application/Commands/Buildings/RegisterEntrance/RegisterBuildingEntranceCommandHandler.cs index 7a228fa..83374d6 100644 --- a/backend/ECondo.Application/Commands/Buildings/RegisterEntrance/RegisterBuildingEntranceCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Buildings/RegisterEntrance/RegisterBuildingEntranceCommandHandler.cs @@ -2,7 +2,7 @@ using ECondo.Application.Services; using ECondo.Domain.Buildings; using ECondo.Domain.Provinces; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.Buildings.RegisterEntrance; diff --git a/backend/ECondo.Application/Commands/Buildings/Update/UpdateBuildingCommandHandler.cs b/backend/ECondo.Application/Commands/Buildings/Update/UpdateBuildingCommandHandler.cs index 0098b2e..8d6889f 100644 --- a/backend/ECondo.Application/Commands/Buildings/Update/UpdateBuildingCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Buildings/Update/UpdateBuildingCommandHandler.cs @@ -1,7 +1,7 @@ using ECondo.Application.Repositories; using ECondo.Domain.Buildings; using ECondo.Domain.Provinces; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.Buildings.Update; diff --git a/backend/ECondo.Application/Commands/ICommand.cs b/backend/ECondo.Application/Commands/ICommand.cs index bebf736..6e863a2 100644 --- a/backend/ECondo.Application/Commands/ICommand.cs +++ b/backend/ECondo.Application/Commands/ICommand.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using MediatR; namespace ECondo.Application.Commands; diff --git a/backend/ECondo.Application/Commands/ICommandHandler.cs b/backend/ECondo.Application/Commands/ICommandHandler.cs index 6d2e541..43fae39 100644 --- a/backend/ECondo.Application/Commands/ICommandHandler.cs +++ b/backend/ECondo.Application/Commands/ICommandHandler.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using MediatR; namespace ECondo.Application.Commands; diff --git a/backend/ECondo.Application/Commands/Identity/ConfirmEmail/ConfirmEmailCommandHandler.cs b/backend/ECondo.Application/Commands/Identity/ConfirmEmail/ConfirmEmailCommandHandler.cs index 388ffc8..97f170d 100644 --- a/backend/ECondo.Application/Commands/Identity/ConfirmEmail/ConfirmEmailCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Identity/ConfirmEmail/ConfirmEmailCommandHandler.cs @@ -1,6 +1,6 @@ using ECondo.Application.Extensions; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using Microsoft.AspNetCore.Identity; namespace ECondo.Application.Commands.Identity.ConfirmEmail; diff --git a/backend/ECondo.Application/Commands/Identity/Delete/DeleteUserCommand.cs b/backend/ECondo.Application/Commands/Identity/Delete/DeleteUserCommand.cs index c3af7d1..3e0c025 100644 --- a/backend/ECondo.Application/Commands/Identity/Delete/DeleteUserCommand.cs +++ b/backend/ECondo.Application/Commands/Identity/Delete/DeleteUserCommand.cs @@ -1,5 +1,9 @@ -using ECondo.Application.Policies; +using ECondo.Domain.Authorization; +using ECondo.Domain.Users; namespace ECondo.Application.Commands.Identity.Delete; -public record DeleteUserCommand(string Email) : ICommand, IIsAdmin; \ No newline at end of file +public record DeleteUserCommand(Guid UserId) : ICommand, ICanDelete +{ + Guid? IResourcePolicy.ResourceId => UserId; +} \ No newline at end of file diff --git a/backend/ECondo.Application/Commands/Identity/Delete/DeleteUserCommandHandler.cs b/backend/ECondo.Application/Commands/Identity/Delete/DeleteUserCommandHandler.cs index c62301d..4194e11 100644 --- a/backend/ECondo.Application/Commands/Identity/Delete/DeleteUserCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Identity/Delete/DeleteUserCommandHandler.cs @@ -1,6 +1,6 @@ using ECondo.Application.Repositories; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.Identity.Delete; @@ -15,11 +15,11 @@ public async Task> Handle( { var user = await dbContext .Users - .FirstOrDefaultAsync(u => u.Email == request.Email, + .FirstOrDefaultAsync(u => u.Id == request.UserId, cancellationToken: cancellationToken); if(user is null) - return Result.Fail(UserErrors.InvalidUser(request.Email)); + return Result.Fail(UserErrors.InvalidUser(request.UserId)); dbContext.Users.Remove(user); await dbContext.SaveChangesAsync(cancellationToken); diff --git a/backend/ECondo.Application/Commands/Identity/ForgotPassword/ForgotPasswordCommandHandler.cs b/backend/ECondo.Application/Commands/Identity/ForgotPassword/ForgotPasswordCommandHandler.cs index 712ae27..603597c 100644 --- a/backend/ECondo.Application/Commands/Identity/ForgotPassword/ForgotPasswordCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Identity/ForgotPassword/ForgotPasswordCommandHandler.cs @@ -1,6 +1,6 @@ using ECondo.Application.Services; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.WebUtilities; diff --git a/backend/ECondo.Application/Commands/Identity/GenerateAccessToken/GenerateAccessTokenCommandHandler.cs b/backend/ECondo.Application/Commands/Identity/GenerateAccessToken/GenerateAccessTokenCommandHandler.cs index af8815e..425ad07 100644 --- a/backend/ECondo.Application/Commands/Identity/GenerateAccessToken/GenerateAccessTokenCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Identity/GenerateAccessToken/GenerateAccessTokenCommandHandler.cs @@ -2,6 +2,7 @@ using ECondo.Application.Services; using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using Microsoft.AspNetCore.Identity; namespace ECondo.Application.Commands.Identity.GenerateAccessToken; diff --git a/backend/ECondo.Application/Commands/Identity/InvalidateRefreshToken/InvalidateRefreshTokenCommandHandler.cs b/backend/ECondo.Application/Commands/Identity/InvalidateRefreshToken/InvalidateRefreshTokenCommandHandler.cs index cdbde1a..9e723fc 100644 --- a/backend/ECondo.Application/Commands/Identity/InvalidateRefreshToken/InvalidateRefreshTokenCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Identity/InvalidateRefreshToken/InvalidateRefreshTokenCommandHandler.cs @@ -1,6 +1,6 @@ using ECondo.Application.Services; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; namespace ECondo.Application.Commands.Identity.InvalidateRefreshToken; diff --git a/backend/ECondo.Application/Commands/Identity/Login/LoginCommandHandler.cs b/backend/ECondo.Application/Commands/Identity/Login/LoginCommandHandler.cs index 9618cb1..83711a3 100644 --- a/backend/ECondo.Application/Commands/Identity/Login/LoginCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Identity/Login/LoginCommandHandler.cs @@ -3,6 +3,7 @@ using ECondo.Application.Services; using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using Microsoft.AspNetCore.Identity; namespace ECondo.Application.Commands.Identity.Login; diff --git a/backend/ECondo.Application/Commands/Identity/Register/RegisterCommandHandler.cs b/backend/ECondo.Application/Commands/Identity/Register/RegisterCommandHandler.cs index 7d37c16..d7e02af 100644 --- a/backend/ECondo.Application/Commands/Identity/Register/RegisterCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Identity/Register/RegisterCommandHandler.cs @@ -2,8 +2,8 @@ using ECondo.Application.Events.Identity; using ECondo.Application.Extensions; using ECondo.Application.Repositories; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using MediatR; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; diff --git a/backend/ECondo.Application/Commands/Identity/ResetPassword/ResetPasswordCommandHandler.cs b/backend/ECondo.Application/Commands/Identity/ResetPassword/ResetPasswordCommandHandler.cs index a7ac810..80f588b 100644 --- a/backend/ECondo.Application/Commands/Identity/ResetPassword/ResetPasswordCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Identity/ResetPassword/ResetPasswordCommandHandler.cs @@ -1,6 +1,6 @@ using ECondo.Application.Extensions; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using Microsoft.AspNetCore.Identity; namespace ECondo.Application.Commands.Identity.ResetPassword; diff --git a/backend/ECondo.Application/Commands/Identity/UpdatePassword/UpdatePasswordCommandHandler.cs b/backend/ECondo.Application/Commands/Identity/UpdatePassword/UpdatePasswordCommandHandler.cs index efbdfe7..2d4f3ce 100644 --- a/backend/ECondo.Application/Commands/Identity/UpdatePassword/UpdatePasswordCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Identity/UpdatePassword/UpdatePasswordCommandHandler.cs @@ -1,7 +1,7 @@ using ECondo.Application.Extensions; using ECondo.Application.Services; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using Microsoft.AspNetCore.Identity; namespace ECondo.Application.Commands.Identity.UpdatePassword; diff --git a/backend/ECondo.Application/Commands/Payment/ConnectStripeAccount/ConnectStripeAccountCommand.cs b/backend/ECondo.Application/Commands/Payment/ConnectStripeAccount/ConnectStripeAccountCommand.cs index b68c306..dd6bcd7 100644 --- a/backend/ECondo.Application/Commands/Payment/ConnectStripeAccount/ConnectStripeAccountCommand.cs +++ b/backend/ECondo.Application/Commands/Payment/ConnectStripeAccount/ConnectStripeAccountCommand.cs @@ -1,9 +1,12 @@ -using ECondo.Application.Policies; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; namespace ECondo.Application.Commands.Payment.ConnectStripeAccount; public record ConnectStripeAccountCommand( - Guid BuildingId, - string EntranceNumber, - string ReturnUri) - : ICommand, IRequireEntranceManager; \ No newline at end of file + Guid EntranceId, + string ReturnUri) + : ICommand, ICanUpdate +{ + Guid? IResourcePolicy.ResourceId => EntranceId; +} \ No newline at end of file diff --git a/backend/ECondo.Application/Commands/Payment/ConnectStripeAccount/ConnectStripeAccountCommandHandler.cs b/backend/ECondo.Application/Commands/Payment/ConnectStripeAccount/ConnectStripeAccountCommandHandler.cs index cff1eb0..b1f28b7 100644 --- a/backend/ECondo.Application/Commands/Payment/ConnectStripeAccount/ConnectStripeAccountCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Payment/ConnectStripeAccount/ConnectStripeAccountCommandHandler.cs @@ -1,6 +1,6 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.Payment.ConnectStripeAccount; @@ -16,8 +16,7 @@ public async Task> Handle( var entrance = await dbContext .Entrances .FirstAsync(e => - e.BuildingId == request.BuildingId && - e.Number == request.EntranceNumber, + e.Id == request.EntranceId, cancellationToken: cancellationToken); string accountId = await stripeService.CreateExpressAccount(); diff --git a/backend/ECondo.Application/Commands/Payment/CreateBill/CreateBillCommand.cs b/backend/ECondo.Application/Commands/Payment/CreateBill/CreateBillCommand.cs index ed99389..92e8f54 100644 --- a/backend/ECondo.Application/Commands/Payment/CreateBill/CreateBillCommand.cs +++ b/backend/ECondo.Application/Commands/Payment/CreateBill/CreateBillCommand.cs @@ -1,16 +1,20 @@ -using ECondo.Application.Policies; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; using ECondo.Domain.Payments; namespace ECondo.Application.Commands.Payment.CreateBill; public sealed record CreateBillCommand( - Guid BuildingId, - string EntranceNumber, - string Title, - string? Description, + Guid EntranceId, + string Title, + string? Description, decimal Amount, bool IsRecurring, RecurringInterval? RecurringInterval, DateTimeOffset StartDate, DateTimeOffset? EndDate) - : ICommand, IRequireEntranceManager; \ No newline at end of file + : ICommand, ICanUpdate +{ + Guid? IResourcePolicy.ResourceId => EntranceId; +} + \ No newline at end of file diff --git a/backend/ECondo.Application/Commands/Payment/CreateBill/CreateBillCommandHandler.cs b/backend/ECondo.Application/Commands/Payment/CreateBill/CreateBillCommandHandler.cs index 18017c3..671a52c 100644 --- a/backend/ECondo.Application/Commands/Payment/CreateBill/CreateBillCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Payment/CreateBill/CreateBillCommandHandler.cs @@ -1,7 +1,7 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; using ECondo.Domain.Payments; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.Payment.CreateBill; @@ -15,8 +15,7 @@ public async Task> Handle(CreateBillCommand request, Cancell var entrance = await dbContext .Entrances .FirstAsync(e => - e.BuildingId == request.BuildingId && - e.Number == request.EntranceNumber, + e.Id == request.EntranceId, cancellationToken: cancellationToken); var bill = new Bill diff --git a/backend/ECondo.Application/Commands/Payment/CreateIntent/CreatePaymentIntentCommandHandler.cs b/backend/ECondo.Application/Commands/Payment/CreateIntent/CreatePaymentIntentCommandHandler.cs index daa2acf..c56fbaf 100644 --- a/backend/ECondo.Application/Commands/Payment/CreateIntent/CreatePaymentIntentCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Payment/CreateIntent/CreatePaymentIntentCommandHandler.cs @@ -1,7 +1,7 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; using ECondo.Domain.Payments; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.Payment.CreateIntent; diff --git a/backend/ECondo.Application/Commands/Profiles/Create/CreateProfileCommandHandler.cs b/backend/ECondo.Application/Commands/Profiles/Create/CreateProfileCommandHandler.cs index 1656736..159be49 100644 --- a/backend/ECondo.Application/Commands/Profiles/Create/CreateProfileCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Profiles/Create/CreateProfileCommandHandler.cs @@ -1,8 +1,8 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; using ECondo.Domain.Profiles; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.Profiles.Create; diff --git a/backend/ECondo.Application/Commands/Profiles/Update/UpdateProfileCommandHandler.cs b/backend/ECondo.Application/Commands/Profiles/Update/UpdateProfileCommandHandler.cs index 5d0dee2..ca453f5 100644 --- a/backend/ECondo.Application/Commands/Profiles/Update/UpdateProfileCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Profiles/Update/UpdateProfileCommandHandler.cs @@ -1,7 +1,7 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; using ECondo.Domain.Profiles; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.Profiles.Update; diff --git a/backend/ECondo.Application/Commands/Properties/Create/CreatePropertyCommand.cs b/backend/ECondo.Application/Commands/Properties/Create/CreatePropertyCommand.cs index e372ea6..a0528f4 100644 --- a/backend/ECondo.Application/Commands/Properties/Create/CreatePropertyCommand.cs +++ b/backend/ECondo.Application/Commands/Properties/Create/CreatePropertyCommand.cs @@ -1,12 +1,15 @@ -using ECondo.Application.Policies; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; namespace ECondo.Application.Commands.Properties.Create; public sealed record CreatePropertyCommand( - Guid BuildingId, - string EntranceNumber, + Guid EntranceId, string PropertyType, string Floor, string Number, int BuiltArea, - int IdealParts) : ICommand, IRequireEntranceManager; + int IdealParts) : ICommand, ICanUpdate +{ + Guid? IResourcePolicy.ResourceId => EntranceId; +} diff --git a/backend/ECondo.Application/Commands/Properties/Create/CreatePropertyCommandHandler.cs b/backend/ECondo.Application/Commands/Properties/Create/CreatePropertyCommandHandler.cs index 7a04fdf..5471090 100644 --- a/backend/ECondo.Application/Commands/Properties/Create/CreatePropertyCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Properties/Create/CreatePropertyCommandHandler.cs @@ -1,7 +1,6 @@ using ECondo.Application.Repositories; -using ECondo.Domain; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.Properties.Create; @@ -17,15 +16,13 @@ public async Task> Handle( var entrance = await dbContext .Entrances .FirstOrDefaultAsync(e => - e.BuildingId == request.BuildingId && - e.Number == request.EntranceNumber, + e.Id == request.EntranceId, cancellationToken: cancellationToken); if (entrance is null) return Result.Fail( EntranceErrors.InvalidEntrance( - request.BuildingId, - request.EntranceNumber)); + request.EntranceId)); var propertyType = await dbContext .PropertyTypes diff --git a/backend/ECondo.Application/Commands/Properties/Delete/DeletePropertyCommand.cs b/backend/ECondo.Application/Commands/Properties/Delete/DeletePropertyCommand.cs index 083f690..f5eda4a 100644 --- a/backend/ECondo.Application/Commands/Properties/Delete/DeletePropertyCommand.cs +++ b/backend/ECondo.Application/Commands/Properties/Delete/DeletePropertyCommand.cs @@ -1,7 +1,11 @@ -using ECondo.Application.Policies; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; namespace ECondo.Application.Commands.Properties.Delete; public sealed record DeletePropertyCommand( Guid PropertyId) - : ICommand, ICanEditProperty; + : ICommand, ICanDelete +{ + Guid? IResourcePolicy.ResourceId => PropertyId; +} diff --git a/backend/ECondo.Application/Commands/Properties/Delete/DeletePropertyCommandHandler.cs b/backend/ECondo.Application/Commands/Properties/Delete/DeletePropertyCommandHandler.cs index a0180cc..efd41c4 100644 --- a/backend/ECondo.Application/Commands/Properties/Delete/DeletePropertyCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Properties/Delete/DeletePropertyCommandHandler.cs @@ -1,6 +1,6 @@ using ECondo.Application.Repositories; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.Properties.Delete; diff --git a/backend/ECondo.Application/Commands/Properties/Update/UpdatePropertyCommand.cs b/backend/ECondo.Application/Commands/Properties/Update/UpdatePropertyCommand.cs index e2ef76f..0ccb64b 100644 --- a/backend/ECondo.Application/Commands/Properties/Update/UpdatePropertyCommand.cs +++ b/backend/ECondo.Application/Commands/Properties/Update/UpdatePropertyCommand.cs @@ -1,4 +1,5 @@ -using ECondo.Application.Policies; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; namespace ECondo.Application.Commands.Properties.Update; @@ -8,4 +9,7 @@ public sealed record UpdatePropertyCommand( string Number, string PropertyType, int BuiltArea, - int IdealParts) : ICommand, ICanEditProperty; \ No newline at end of file + int IdealParts) : ICommand, ICanUpdate +{ + Guid? IResourcePolicy.ResourceId => PropertyId; +} \ No newline at end of file diff --git a/backend/ECondo.Application/Commands/Properties/Update/UpdatePropertyCommandHandler.cs b/backend/ECondo.Application/Commands/Properties/Update/UpdatePropertyCommandHandler.cs index 5e7ec04..7309cc4 100644 --- a/backend/ECondo.Application/Commands/Properties/Update/UpdatePropertyCommandHandler.cs +++ b/backend/ECondo.Application/Commands/Properties/Update/UpdatePropertyCommandHandler.cs @@ -1,7 +1,6 @@ using ECondo.Application.Repositories; -using ECondo.Domain; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.Properties.Update; diff --git a/backend/ECondo.Application/Commands/PropertyOccupants/AcceptInvitation/AcceptPropertyInvitationCommandHandler.cs b/backend/ECondo.Application/Commands/PropertyOccupants/AcceptInvitation/AcceptPropertyInvitationCommandHandler.cs index eee5c04..bc99d5c 100644 --- a/backend/ECondo.Application/Commands/PropertyOccupants/AcceptInvitation/AcceptPropertyInvitationCommandHandler.cs +++ b/backend/ECondo.Application/Commands/PropertyOccupants/AcceptInvitation/AcceptPropertyInvitationCommandHandler.cs @@ -1,8 +1,8 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.PropertyOccupants.AcceptInvitation; diff --git a/backend/ECondo.Application/Commands/PropertyOccupants/AddToProperty/AddOccupantToPropertyCommand.cs b/backend/ECondo.Application/Commands/PropertyOccupants/AddToProperty/AddOccupantToPropertyCommand.cs index b7b5697..0e1918c 100644 --- a/backend/ECondo.Application/Commands/PropertyOccupants/AddToProperty/AddOccupantToPropertyCommand.cs +++ b/backend/ECondo.Application/Commands/PropertyOccupants/AddToProperty/AddOccupantToPropertyCommand.cs @@ -1,4 +1,5 @@ -using ECondo.Application.Policies; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; namespace ECondo.Application.Commands.PropertyOccupants.AddToProperty; @@ -10,4 +11,7 @@ public sealed record AddOccupantToPropertyCommand( string OccupantType, string? Email, string ReturnUri) - : ICommand, ICanAddOccupant; + : ICommand, ICanCreate +{ + Guid? IResourcePolicy.ResourceId => PropertyId; +} diff --git a/backend/ECondo.Application/Commands/PropertyOccupants/AddToProperty/AddOccupantToPropertyCommandHandler.cs b/backend/ECondo.Application/Commands/PropertyOccupants/AddToProperty/AddOccupantToPropertyCommandHandler.cs index 0d74fe5..aac2f06 100644 --- a/backend/ECondo.Application/Commands/PropertyOccupants/AddToProperty/AddOccupantToPropertyCommandHandler.cs +++ b/backend/ECondo.Application/Commands/PropertyOccupants/AddToProperty/AddOccupantToPropertyCommandHandler.cs @@ -1,7 +1,7 @@ using ECondo.Application.Events.PropertyOccupant; using ECondo.Application.Repositories; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using MediatR; using Microsoft.EntityFrameworkCore; diff --git a/backend/ECondo.Application/Commands/PropertyOccupants/Delete/DeletePropertyOccupantCommand.cs b/backend/ECondo.Application/Commands/PropertyOccupants/Delete/DeletePropertyOccupantCommand.cs index f0877be..059f5f9 100644 --- a/backend/ECondo.Application/Commands/PropertyOccupants/Delete/DeletePropertyOccupantCommand.cs +++ b/backend/ECondo.Application/Commands/PropertyOccupants/Delete/DeletePropertyOccupantCommand.cs @@ -1,6 +1,10 @@ -using ECondo.Application.Policies; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; namespace ECondo.Application.Commands.PropertyOccupants.Delete; public sealed record DeletePropertyOccupantCommand( - Guid OccupantId) : ICommand, ICanDeleteOccupant; + Guid OccupantId) : ICommand, ICanDelete +{ + Guid? IResourcePolicy.ResourceId => OccupantId; +} diff --git a/backend/ECondo.Application/Commands/PropertyOccupants/Delete/DeletePropertyOccupantCommandHandler.cs b/backend/ECondo.Application/Commands/PropertyOccupants/Delete/DeletePropertyOccupantCommandHandler.cs index 667991f..c2ae539 100644 --- a/backend/ECondo.Application/Commands/PropertyOccupants/Delete/DeletePropertyOccupantCommandHandler.cs +++ b/backend/ECondo.Application/Commands/PropertyOccupants/Delete/DeletePropertyOccupantCommandHandler.cs @@ -1,5 +1,5 @@ using ECondo.Application.Repositories; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Commands.PropertyOccupants.Delete; diff --git a/backend/ECondo.Application/Commands/PropertyOccupants/Update/UpdatePropertyOccupantCommand.cs b/backend/ECondo.Application/Commands/PropertyOccupants/Update/UpdatePropertyOccupantCommand.cs index bd767b8..29a1865 100644 --- a/backend/ECondo.Application/Commands/PropertyOccupants/Update/UpdatePropertyOccupantCommand.cs +++ b/backend/ECondo.Application/Commands/PropertyOccupants/Update/UpdatePropertyOccupantCommand.cs @@ -1,4 +1,5 @@ -using ECondo.Application.Policies; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; namespace ECondo.Application.Commands.PropertyOccupants.Update; @@ -9,4 +10,7 @@ public sealed record UpdatePropertyOccupantCommand( string LastName, string Type, string? Email, - string ReturnUri) : ICommand, ICanEditOccupant; + string ReturnUri) : ICommand, ICanUpdate +{ + Guid? IResourcePolicy.ResourceId => OccupantId; +} diff --git a/backend/ECondo.Application/Commands/PropertyOccupants/Update/UpdatePropertyOccupantCommandHandler.cs b/backend/ECondo.Application/Commands/PropertyOccupants/Update/UpdatePropertyOccupantCommandHandler.cs index 7c1c062..a6d1a94 100644 --- a/backend/ECondo.Application/Commands/PropertyOccupants/Update/UpdatePropertyOccupantCommandHandler.cs +++ b/backend/ECondo.Application/Commands/PropertyOccupants/Update/UpdatePropertyOccupantCommandHandler.cs @@ -1,7 +1,7 @@ using ECondo.Application.Events.PropertyOccupant; using ECondo.Application.Repositories; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using MediatR; using Microsoft.EntityFrameworkCore; diff --git a/backend/ECondo.Application/Data/BuldingResult.cs b/backend/ECondo.Application/Data/BuldingResult.cs index 218fb1e..9590a00 100644 --- a/backend/ECondo.Application/Data/BuldingResult.cs +++ b/backend/ECondo.Application/Data/BuldingResult.cs @@ -11,4 +11,5 @@ public sealed record BuildingResult( string Street, string StreetNumber, string BuildingNumber, - string EntranceNumber); + string EntranceNumber, + Guid EntranceId); diff --git a/backend/ECondo.Application/Extensions/DbSetExtension.cs b/backend/ECondo.Application/Extensions/DbSetExtension.cs index 83881c8..af74c5b 100644 --- a/backend/ECondo.Application/Extensions/DbSetExtension.cs +++ b/backend/ECondo.Application/Extensions/DbSetExtension.cs @@ -8,7 +8,8 @@ public static class DbSetExtension public static Task IsAdminAsync(this DbSet userRoles, Guid userId, CancellationToken cancellationToken = default) { return userRoles - .Where(ur => ur.UserId == userId && ur.Role.Name == "admin") + .Where(ur => ur.UserId == userId && ur.Role.Name == Role.Admin) + .AsNoTracking() .AnyAsync(cancellationToken: cancellationToken); } } \ No newline at end of file diff --git a/backend/ECondo.Application/Extensions/IQueryableExtension.cs b/backend/ECondo.Application/Extensions/IQueryableExtension.cs index 2f2c9da..8dec631 100644 --- a/backend/ECondo.Application/Extensions/IQueryableExtension.cs +++ b/backend/ECondo.Application/Extensions/IQueryableExtension.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Collections; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Extensions; diff --git a/backend/ECondo.Application/Extensions/IdentityErrorExtension.cs b/backend/ECondo.Application/Extensions/IdentityErrorExtension.cs index 13f6f51..6f018d9 100644 --- a/backend/ECondo.Application/Extensions/IdentityErrorExtension.cs +++ b/backend/ECondo.Application/Extensions/IdentityErrorExtension.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.AspNetCore.Identity; namespace ECondo.Application.Extensions; diff --git a/backend/ECondo.Application/Extensions/ServiceCollectionExtension.cs b/backend/ECondo.Application/Extensions/ServiceCollectionExtension.cs new file mode 100644 index 0000000..f661c6e --- /dev/null +++ b/backend/ECondo.Application/Extensions/ServiceCollectionExtension.cs @@ -0,0 +1,45 @@ +using System.Reflection; +using ECondo.Application.Authorization; +using Microsoft.Extensions.DependencyInjection; + +namespace ECondo.Application.Extensions; + +public static class ServiceCollectionExtension +{ + public static IServiceCollection AddAuthorizersFromAssembly( + this IServiceCollection services, Assembly assembly, + ServiceLifetime lifetime = ServiceLifetime.Scoped) + { + var authorizerInterfaceType = typeof(IResourceAuthorizationHandler<>); + var authorizers = assembly.DefinedTypes.Where(t => + t is { IsClass: true, IsAbstract: false } && + t != authorizerInterfaceType && + t.ImplementedInterfaces.Any(i => + i.IsGenericType && + i.GetGenericTypeDefinition() == authorizerInterfaceType)) + .Except([typeof(DefaultAuthorizationHandler<>)]) + .ToList(); + + services.AddScoped(typeof(DefaultAuthorizationHandler<>)); + foreach (var authorizer in authorizers) + { + foreach (var implementedInterface in authorizer.GetInterfaces()) + { + switch (lifetime) + { + case ServiceLifetime.Singleton: + services.AddSingleton(implementedInterface, authorizer); + break; + case ServiceLifetime.Scoped: + services.AddScoped(implementedInterface, authorizer); + break; + case ServiceLifetime.Transient: + services.AddTransient(implementedInterface, authorizer); + break; + } + } + } + + return services; + } +} diff --git a/backend/ECondo.Application/Extensions/ServiceConfiguration.cs b/backend/ECondo.Application/Extensions/ServiceConfiguration.cs index a7c7cbe..b1af505 100644 --- a/backend/ECondo.Application/Extensions/ServiceConfiguration.cs +++ b/backend/ECondo.Application/Extensions/ServiceConfiguration.cs @@ -15,19 +15,11 @@ public static IServiceCollection AddApplication(this IServiceCollection services configuration.RegisterServicesFromAssembly(currentAssembly); configuration.AddOpenBehavior(typeof(ValidationPipelineBehavior<,>)); - configuration.AddOpenBehavior(typeof(EntranceManagerAuthorizationPipelineBehaviour<,>)); - configuration.AddOpenBehavior(typeof(AccessPropertyAuthorizationPipelineBehaviour<,>)); - configuration.AddOpenBehavior(typeof(EditPropertyAuthorizationPipelineBehaviour<,>)); - configuration.AddOpenBehavior(typeof(EditOccupantAuthorizationPipelineBehaviour<,>)); - configuration.AddOpenBehavior(typeof(AddOccupantAuthorizationPipelineBehaviour<,>)); - configuration.AddOpenBehavior(typeof(AccessTenantAuthorizationPipelineBehaviour<,>)); - configuration.AddOpenBehavior(typeof(DeleteOccupantAuthorizationPipelineBehaviour<,>)); - configuration.AddOpenBehavior(typeof(AdminAuthorizationPipelineBehaviour<,>)); - configuration.AddOpenBehavior(typeof(EditBuildingEntranceAuthorizationPipelineBehaviour<,>)); + configuration.AddOpenBehavior(typeof(AuthorizationPipelineBehaviour<,>)); }); services.AddValidatorsFromAssembly(currentAssembly, includeInternalTypes: true); - + services.AddAuthorizersFromAssembly(currentAssembly); return services; } } diff --git a/backend/ECondo.Application/Policies/AdminPolicy.cs b/backend/ECondo.Application/Policies/AdminPolicy.cs deleted file mode 100644 index 178bcd0..0000000 --- a/backend/ECondo.Application/Policies/AdminPolicy.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace ECondo.Application.Policies; - -public interface IIsAdmin; \ No newline at end of file diff --git a/backend/ECondo.Application/Policies/BuildingPolicies.cs b/backend/ECondo.Application/Policies/BuildingPolicies.cs deleted file mode 100644 index 97875a5..0000000 --- a/backend/ECondo.Application/Policies/BuildingPolicies.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ECondo.Application.Policies; - -public interface ICanEditEntrance -{ - public Guid BuildingId { get; init; } - public string EntranceNumber { get; init; } -} diff --git a/backend/ECondo.Application/Policies/IRequireEntranceManager.cs b/backend/ECondo.Application/Policies/IRequireEntranceManager.cs deleted file mode 100644 index 20990de..0000000 --- a/backend/ECondo.Application/Policies/IRequireEntranceManager.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ECondo.Application.Policies; - -internal interface IRequireEntranceManager -{ - Guid BuildingId { get; init; } - string EntranceNumber { get; init; } -} diff --git a/backend/ECondo.Application/Policies/OccupantPolicies.cs b/backend/ECondo.Application/Policies/OccupantPolicies.cs deleted file mode 100644 index 0abe742..0000000 --- a/backend/ECondo.Application/Policies/OccupantPolicies.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace ECondo.Application.Policies; - -public interface ICanEditOccupant -{ - public Guid OccupantId { get; init; } - public string Type { get; init; } -} - -public interface ICanDeleteOccupant -{ - public Guid OccupantId { get; init; } -} - -public interface ICanAddOccupant -{ - public Guid PropertyId { get; init; } - public string OccupantType { get; init; } -} - -public interface ICanSeeTenants -{ - public Guid PropertyId { get; init; } -} diff --git a/backend/ECondo.Application/Policies/PropertyPolicies.cs b/backend/ECondo.Application/Policies/PropertyPolicies.cs deleted file mode 100644 index 461df2c..0000000 --- a/backend/ECondo.Application/Policies/PropertyPolicies.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace ECondo.Application.Policies; - -public interface ICanSeeProperty -{ - public Guid PropertyId { get; init; } -} - -public interface ICanEditProperty -{ - public Guid PropertyId { get; init; } -} - -// public interface ICanCreateProperty -// { -// public Guid BuildingId { get; init; } -// public string EntranceNumber { get; init; } -// } diff --git a/backend/ECondo.Application/Queries/Buildings/GetAll/GetAllBuildingsQuery.cs b/backend/ECondo.Application/Queries/Buildings/GetAll/GetAllBuildingsQuery.cs index 97564ed..8c85c74 100644 --- a/backend/ECondo.Application/Queries/Buildings/GetAll/GetAllBuildingsQuery.cs +++ b/backend/ECondo.Application/Queries/Buildings/GetAll/GetAllBuildingsQuery.cs @@ -1,8 +1,12 @@ using ECondo.Application.Data; -using ECondo.Application.Policies; -using ECondo.Domain.Shared; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; +using ECondo.SharedKernel.Collections; namespace ECondo.Application.Queries.Buildings.GetAll; -public sealed record GetAllBuildingsQuery(int Page, int PageSize) : - IQuery>, IIsAdmin; +public sealed record GetAllBuildingsQuery(int Page, int PageSize) : + IQuery>, ICanRead +{ + Guid? IResourcePolicy.ResourceId => null; +} diff --git a/backend/ECondo.Application/Queries/Buildings/GetAll/GetAllBuildingsQueryHandler.cs b/backend/ECondo.Application/Queries/Buildings/GetAll/GetAllBuildingsQueryHandler.cs index 9a1fa24..76508e7 100644 --- a/backend/ECondo.Application/Queries/Buildings/GetAll/GetAllBuildingsQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Buildings/GetAll/GetAllBuildingsQueryHandler.cs @@ -1,7 +1,8 @@ using ECondo.Application.Data; using ECondo.Application.Extensions; using ECondo.Application.Repositories; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Collections; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Buildings.GetAll; @@ -29,7 +30,8 @@ public async Task, Error>> Handle( e.Building.Street, e.Building.StreetNumber, e.Building.BuildingNumber, - e.Number) + e.Number, + e.Id) ).ToPagedListAsync( request.Page, request.PageSize, diff --git a/backend/ECondo.Application/Queries/Buildings/GetForUser/GetBuildingsForUserQuery.cs b/backend/ECondo.Application/Queries/Buildings/GetForUser/GetBuildingsForUserQuery.cs index e357941..24066f1 100644 --- a/backend/ECondo.Application/Queries/Buildings/GetForUser/GetBuildingsForUserQuery.cs +++ b/backend/ECondo.Application/Queries/Buildings/GetForUser/GetBuildingsForUserQuery.cs @@ -1,7 +1,8 @@ using ECondo.Application.Data; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Collections; namespace ECondo.Application.Queries.Buildings.GetForUser; -public sealed record GetBuildingsForUserQuery(int Page, int PageSize, string? BuildingName) +public sealed record GetBuildingsForUserQuery( + int Page, int PageSize, string? BuildingName) : IQuery>; diff --git a/backend/ECondo.Application/Queries/Buildings/GetForUser/GetBuildingsForUserQueryHandler.cs b/backend/ECondo.Application/Queries/Buildings/GetForUser/GetBuildingsForUserQueryHandler.cs index ccc6b6a..cb36745 100644 --- a/backend/ECondo.Application/Queries/Buildings/GetForUser/GetBuildingsForUserQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Buildings/GetForUser/GetBuildingsForUserQueryHandler.cs @@ -2,7 +2,8 @@ using ECondo.Application.Extensions; using ECondo.Application.Repositories; using ECondo.Application.Services; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Collections; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Buildings.GetForUser; @@ -41,7 +42,8 @@ public async Task, Error>> e.Building.Street, e.Building.StreetNumber, e.Building.BuildingNumber, - e.Number)) + e.Number, + e.Id)) .ToPagedListAsync( request.Page, request.PageSize, diff --git a/backend/ECondo.Application/Queries/Buildings/IsUserIn/IsUserEntranceManagerQuery.cs b/backend/ECondo.Application/Queries/Buildings/IsUserIn/IsUserEntranceManagerQuery.cs index 35ca467..1096075 100644 --- a/backend/ECondo.Application/Queries/Buildings/IsUserIn/IsUserEntranceManagerQuery.cs +++ b/backend/ECondo.Application/Queries/Buildings/IsUserIn/IsUserEntranceManagerQuery.cs @@ -1,4 +1,3 @@ namespace ECondo.Application.Queries.Buildings.IsUserIn; -public sealed record IsUserEntranceManagerQuery(Guid BuildingId, string EntranceNumber) - : IQuery; +public sealed record IsUserEntranceManagerQuery(Guid EntranceId) : IQuery; diff --git a/backend/ECondo.Application/Queries/Buildings/IsUserIn/IsUserEntranceManagerQueryHandler.cs b/backend/ECondo.Application/Queries/Buildings/IsUserIn/IsUserEntranceManagerQueryHandler.cs index 828a791..0e5b80c 100644 --- a/backend/ECondo.Application/Queries/Buildings/IsUserIn/IsUserEntranceManagerQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Buildings/IsUserIn/IsUserEntranceManagerQueryHandler.cs @@ -1,7 +1,7 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Buildings.IsUserIn; @@ -21,8 +21,7 @@ public async Task> .AsNoTracking() .AnyAsync(e => e.ManagerId == userContext.UserId && - e.BuildingId == request.BuildingId && - e.Number == request.EntranceNumber, + e.Id == request.EntranceId, cancellationToken: cancellationToken); if(!entrance) diff --git a/backend/ECondo.Application/Queries/IQuery.cs b/backend/ECondo.Application/Queries/IQuery.cs index fa36d5f..d7a0ac6 100644 --- a/backend/ECondo.Application/Queries/IQuery.cs +++ b/backend/ECondo.Application/Queries/IQuery.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using MediatR; namespace ECondo.Application.Queries; diff --git a/backend/ECondo.Application/Queries/IQueryHandler.cs b/backend/ECondo.Application/Queries/IQueryHandler.cs index 3a80acd..a643619 100644 --- a/backend/ECondo.Application/Queries/IQueryHandler.cs +++ b/backend/ECondo.Application/Queries/IQueryHandler.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using MediatR; namespace ECondo.Application.Queries; diff --git a/backend/ECondo.Application/Queries/Identity/IsInRole/IsUserInRoleQuery.cs b/backend/ECondo.Application/Queries/Identity/IsInRole/IsUserInRoleQuery.cs index 71daae9..53cede4 100644 --- a/backend/ECondo.Application/Queries/Identity/IsInRole/IsUserInRoleQuery.cs +++ b/backend/ECondo.Application/Queries/Identity/IsInRole/IsUserInRoleQuery.cs @@ -1,3 +1,3 @@ namespace ECondo.Application.Queries.Identity.IsInRole; -public record IsUserInRoleQuery(string RoleName): IQuery; \ No newline at end of file +public record IsUserInRoleQuery(string RoleName): IQuery; diff --git a/backend/ECondo.Application/Queries/Identity/IsInRole/IsUserInRoleQueryHandler.cs b/backend/ECondo.Application/Queries/Identity/IsInRole/IsUserInRoleQueryHandler.cs index 2b15b39..375630c 100644 --- a/backend/ECondo.Application/Queries/Identity/IsInRole/IsUserInRoleQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Identity/IsInRole/IsUserInRoleQueryHandler.cs @@ -1,7 +1,7 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Identity.IsInRole; diff --git a/backend/ECondo.Application/Queries/OccupantTypes/GetAll/GetAllOccupantTypesQueryHandler.cs b/backend/ECondo.Application/Queries/OccupantTypes/GetAll/GetAllOccupantTypesQueryHandler.cs index f7791c2..595a064 100644 --- a/backend/ECondo.Application/Queries/OccupantTypes/GetAll/GetAllOccupantTypesQueryHandler.cs +++ b/backend/ECondo.Application/Queries/OccupantTypes/GetAll/GetAllOccupantTypesQueryHandler.cs @@ -1,5 +1,5 @@ using ECondo.Application.Repositories; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.OccupantTypes.GetAll; diff --git a/backend/ECondo.Application/Queries/Payment/CheckStripeStatus/CheckEntranceStripeStatusQuery.cs b/backend/ECondo.Application/Queries/Payment/CheckStripeStatus/CheckEntranceStripeStatusQuery.cs index ab00ad8..31fe94e 100644 --- a/backend/ECondo.Application/Queries/Payment/CheckStripeStatus/CheckEntranceStripeStatusQuery.cs +++ b/backend/ECondo.Application/Queries/Payment/CheckStripeStatus/CheckEntranceStripeStatusQuery.cs @@ -1,9 +1,12 @@ -using ECondo.Application.Policies; -using ECondo.Application.Services; +using ECondo.Application.Services; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; namespace ECondo.Application.Queries.Payment.CheckStripeStatus; public record CheckEntranceStripeStatusQuery( - Guid BuildingId, - string EntranceNumber): - IQuery, IRequireEntranceManager; \ No newline at end of file + Guid EntranceId) : + IQuery, ICanRead +{ + Guid? IResourcePolicy.ResourceId => EntranceId; +} \ No newline at end of file diff --git a/backend/ECondo.Application/Queries/Payment/CheckStripeStatus/CheckEntranceStripeStatusQueryHandler.cs b/backend/ECondo.Application/Queries/Payment/CheckStripeStatus/CheckEntranceStripeStatusQueryHandler.cs index f440acf..fda099c 100644 --- a/backend/ECondo.Application/Queries/Payment/CheckStripeStatus/CheckEntranceStripeStatusQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Payment/CheckStripeStatus/CheckEntranceStripeStatusQueryHandler.cs @@ -1,6 +1,6 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Payment.CheckStripeStatus; @@ -16,8 +16,7 @@ public async Task> Handle( var entrance = await dbContext .Entrances .FirstAsync(e => - e.BuildingId == request.BuildingId && - e.Number == request.EntranceNumber, + e.Id == request.EntranceId, cancellationToken: cancellationToken); if(entrance.StripeAccountId is null) diff --git a/backend/ECondo.Application/Queries/Payment/GetBillsForEntrance/GetBillsForEntranceQuery.cs b/backend/ECondo.Application/Queries/Payment/GetBillsForEntrance/GetBillsForEntranceQuery.cs index 92fc98a..a282335 100644 --- a/backend/ECondo.Application/Queries/Payment/GetBillsForEntrance/GetBillsForEntranceQuery.cs +++ b/backend/ECondo.Application/Queries/Payment/GetBillsForEntrance/GetBillsForEntranceQuery.cs @@ -1,6 +1,7 @@ -using ECondo.Application.Policies; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; using ECondo.Domain.Payments; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Collections; namespace ECondo.Application.Queries.Payment.GetBillsForEntrance; @@ -12,6 +13,9 @@ public sealed record BillResult( DateTimeOffset StartDate, DateTimeOffset? EndDate); -public sealed record GetBillsForEntranceQuery(Guid BuildingId, string EntranceNumber, int Page, int PageSize) : - IQuery>, - IRequireEntranceManager; \ No newline at end of file +public sealed record GetBillsForEntranceQuery( + Guid EntranceId, int Page, int PageSize) : + IQuery>, ICanRead +{ + Guid? IResourcePolicy.ResourceId => EntranceId; +} \ No newline at end of file diff --git a/backend/ECondo.Application/Queries/Payment/GetBillsForEntrance/GetBillsForEntranceQueryHandler.cs b/backend/ECondo.Application/Queries/Payment/GetBillsForEntrance/GetBillsForEntranceQueryHandler.cs index d471a60..153f8f5 100644 --- a/backend/ECondo.Application/Queries/Payment/GetBillsForEntrance/GetBillsForEntranceQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Payment/GetBillsForEntrance/GetBillsForEntranceQueryHandler.cs @@ -1,6 +1,7 @@ using ECondo.Application.Extensions; using ECondo.Application.Repositories; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Collections; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Payment.GetBillsForEntrance; @@ -14,10 +15,10 @@ public async Task, Error>> Handle(GetBillsForEntran var bills = await dbContext .Bills .AsNoTracking() - .Where(b => b.Entrance.BuildingId == request.BuildingId && b.Entrance.Number == request.EntranceNumber) + .Where(b => b.Entrance.Id == request.EntranceId) .Select(e => new BillResult(e.Title, e.Description, e.Amount, e.RecurringInterval, e.StartDate, e.EndDate)) .ToPagedListAsync(request.Page, request.PageSize, cancellationToken: cancellationToken); return Result, Error>.Ok(bills); } -} \ No newline at end of file +} diff --git a/backend/ECondo.Application/Queries/Payment/GetById/GetPaymentByIdQueryHandler.cs b/backend/ECondo.Application/Queries/Payment/GetById/GetPaymentByIdQueryHandler.cs index 1ae813a..257a72b 100644 --- a/backend/ECondo.Application/Queries/Payment/GetById/GetPaymentByIdQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Payment/GetById/GetPaymentByIdQueryHandler.cs @@ -1,7 +1,7 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; using ECondo.Domain.Payments; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Payment.GetById; diff --git a/backend/ECondo.Application/Queries/Payment/GetForProperty/GetPaymentForPropertyQuery.cs b/backend/ECondo.Application/Queries/Payment/GetForProperty/GetPaymentForPropertyQuery.cs index 35d37a5..4d3e035 100644 --- a/backend/ECondo.Application/Queries/Payment/GetForProperty/GetPaymentForPropertyQuery.cs +++ b/backend/ECondo.Application/Queries/Payment/GetForProperty/GetPaymentForPropertyQuery.cs @@ -1,6 +1,5 @@ -using ECondo.Application.Policies; -using ECondo.Application.Queries.Payment.GetById; -using ECondo.Domain.Shared; +using ECondo.Application.Queries.Payment.GetById; +using ECondo.SharedKernel.Collections; namespace ECondo.Application.Queries.Payment.GetForProperty; diff --git a/backend/ECondo.Application/Queries/Payment/GetForProperty/GetPaymentForPropertyQueryHandler.cs b/backend/ECondo.Application/Queries/Payment/GetForProperty/GetPaymentForPropertyQueryHandler.cs index 3eae26c..70d3004 100644 --- a/backend/ECondo.Application/Queries/Payment/GetForProperty/GetPaymentForPropertyQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Payment/GetForProperty/GetPaymentForPropertyQueryHandler.cs @@ -2,7 +2,8 @@ using ECondo.Application.Queries.Payment.GetById; using ECondo.Application.Repositories; using ECondo.Application.Services; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Collections; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Payment.GetForProperty; diff --git a/backend/ECondo.Application/Queries/Payment/GetStripeLoginLink/GetEntranceStripeLoginLinkQuery.cs b/backend/ECondo.Application/Queries/Payment/GetStripeLoginLink/GetEntranceStripeLoginLinkQuery.cs index c7a2efc..a6eff96 100644 --- a/backend/ECondo.Application/Queries/Payment/GetStripeLoginLink/GetEntranceStripeLoginLinkQuery.cs +++ b/backend/ECondo.Application/Queries/Payment/GetStripeLoginLink/GetEntranceStripeLoginLinkQuery.cs @@ -1,8 +1,11 @@ -using ECondo.Application.Policies; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; namespace ECondo.Application.Queries.Payment.GetStripeLoginLink; public sealed record GetEntranceStripeLoginLinkQuery( - Guid BuildingId, - string EntranceNumber) : - IQuery, IRequireEntranceManager; \ No newline at end of file + Guid EntranceId) : + IQuery, ICanRead +{ + Guid? IResourcePolicy.ResourceId => EntranceId; +} \ No newline at end of file diff --git a/backend/ECondo.Application/Queries/Payment/GetStripeLoginLink/GetStripeLoginLinkQueryHandler.cs b/backend/ECondo.Application/Queries/Payment/GetStripeLoginLink/GetStripeLoginLinkQueryHandler.cs index ba0e113..41b8bdf 100644 --- a/backend/ECondo.Application/Queries/Payment/GetStripeLoginLink/GetStripeLoginLinkQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Payment/GetStripeLoginLink/GetStripeLoginLinkQueryHandler.cs @@ -1,7 +1,7 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; using ECondo.Domain.Payments; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Payment.GetStripeLoginLink; @@ -15,8 +15,7 @@ public async Task> Handle(GetEntranceStripeLoginLinkQuery var entrance = await dbContext .Entrances .FirstAsync(e => - e.BuildingId == request.BuildingId && - e.Number == request.EntranceNumber, + e.Id == request.EntranceId, cancellationToken: cancellationToken); if(entrance.StripeAccountId is null) diff --git a/backend/ECondo.Application/Queries/Profiles/GetAll/GetAllProfilesQuery.cs b/backend/ECondo.Application/Queries/Profiles/GetAll/GetAllProfilesQuery.cs index 72c0997..947f9e5 100644 --- a/backend/ECondo.Application/Queries/Profiles/GetAll/GetAllProfilesQuery.cs +++ b/backend/ECondo.Application/Queries/Profiles/GetAll/GetAllProfilesQuery.cs @@ -1,9 +1,13 @@ -using ECondo.Application.Policies; -using ECondo.Domain.Shared; +using ECondo.Domain.Authorization; +using ECondo.Domain.Users; +using ECondo.SharedKernel.Collections; namespace ECondo.Application.Queries.Profiles.GetAll; public record UserProfileResult(string FirstName, string MiddleName, string LastName, string Email); -public record GetAllProfilesQuery(int Page, int PageSize) : - IQuery>, IIsAdmin; \ No newline at end of file +public record GetAllProfilesQuery(int Page, int PageSize) : + IQuery>, ICanRead +{ + Guid? IResourcePolicy.ResourceId => null; +} \ No newline at end of file diff --git a/backend/ECondo.Application/Queries/Profiles/GetAll/GetAllProfilesQueryHandler.cs b/backend/ECondo.Application/Queries/Profiles/GetAll/GetAllProfilesQueryHandler.cs index 367bcbb..fbb8a58 100644 --- a/backend/ECondo.Application/Queries/Profiles/GetAll/GetAllProfilesQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Profiles/GetAll/GetAllProfilesQueryHandler.cs @@ -1,6 +1,8 @@ using ECondo.Application.Extensions; using ECondo.Application.Repositories; -using ECondo.Domain.Shared; +using ECondo.Domain.Users; +using ECondo.SharedKernel.Collections; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Profiles.GetAll; @@ -17,7 +19,7 @@ public async Task, Error>> Handle( .UserDetails .Include(ud => ud.User) .AsNoTracking() - .Where(ud => ud.User.UserRoles.All(ur => ur.Role.Name != "admin")) + .Where(ud => ud.User.UserRoles.All(ur => ur.Role.Name != Role.Admin)) .Select(ud => new UserProfileResult( ud.FirstName, diff --git a/backend/ECondo.Application/Queries/Profiles/GetBrief/GetBriefProfileQueryHandler.cs b/backend/ECondo.Application/Queries/Profiles/GetBrief/GetBriefProfileQueryHandler.cs index 5a4028b..8b4add6 100644 --- a/backend/ECondo.Application/Queries/Profiles/GetBrief/GetBriefProfileQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Profiles/GetBrief/GetBriefProfileQueryHandler.cs @@ -2,8 +2,8 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; using ECondo.Domain.Profiles; -using ECondo.Domain.Shared; using ECondo.Domain.Users; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Profiles.GetBrief; diff --git a/backend/ECondo.Application/Queries/Profiles/GetForUser/GetProfileQueryHandler.cs b/backend/ECondo.Application/Queries/Profiles/GetForUser/GetProfileQueryHandler.cs index 1269679..9127988 100644 --- a/backend/ECondo.Application/Queries/Profiles/GetForUser/GetProfileQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Profiles/GetForUser/GetProfileQueryHandler.cs @@ -2,7 +2,7 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; using ECondo.Domain.Profiles; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Profiles.GetForUser; diff --git a/backend/ECondo.Application/Queries/Properties/GetAll/GetAllPropertiesQuery.cs b/backend/ECondo.Application/Queries/Properties/GetAll/GetAllPropertiesQuery.cs index b7c6611..afb3c93 100644 --- a/backend/ECondo.Application/Queries/Properties/GetAll/GetAllPropertiesQuery.cs +++ b/backend/ECondo.Application/Queries/Properties/GetAll/GetAllPropertiesQuery.cs @@ -1,13 +1,17 @@ -using ECondo.Application.Data; -using ECondo.Application.Data.Property; -using ECondo.Application.Policies; -using ECondo.Domain.Shared; +using ECondo.Application.Data.Property; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; +using ECondo.SharedKernel.Collections; namespace ECondo.Application.Queries.Properties.GetAll; public sealed record EntranceFilter(Guid BuildingId, string EntranceNumber); + public sealed record GetAllPropertiesQuery( - int Page, - int PageSize, - EntranceFilter? EntranceFilter) - : IQuery>, IIsAdmin; \ No newline at end of file + int Page, + int PageSize, + EntranceFilter? EntranceFilter) + : IQuery>, ICanRead +{ + Guid? IResourcePolicy.ResourceId => null; +} \ No newline at end of file diff --git a/backend/ECondo.Application/Queries/Properties/GetAll/GetAllPropertiesQueryHandler.cs b/backend/ECondo.Application/Queries/Properties/GetAll/GetAllPropertiesQueryHandler.cs index b043729..3d1f68e 100644 --- a/backend/ECondo.Application/Queries/Properties/GetAll/GetAllPropertiesQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Properties/GetAll/GetAllPropertiesQueryHandler.cs @@ -1,9 +1,9 @@ -using ECondo.Application.Data; -using ECondo.Application.Data.Occupant; +using ECondo.Application.Data.Occupant; using ECondo.Application.Data.Property; using ECondo.Application.Extensions; using ECondo.Application.Repositories; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Collections; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Properties.GetAll; diff --git a/backend/ECondo.Application/Queries/Properties/GetById/GetPropertyByIdQuery.cs b/backend/ECondo.Application/Queries/Properties/GetById/GetPropertyByIdQuery.cs index 3325bd2..e254900 100644 --- a/backend/ECondo.Application/Queries/Properties/GetById/GetPropertyByIdQuery.cs +++ b/backend/ECondo.Application/Queries/Properties/GetById/GetPropertyByIdQuery.cs @@ -1,8 +1,11 @@ -using ECondo.Application.Data; -using ECondo.Application.Data.Property; -using ECondo.Application.Policies; +using ECondo.Application.Data.Property; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; namespace ECondo.Application.Queries.Properties.GetById; public sealed record GetPropertyByIdQuery( - Guid PropertyId) : IQuery, ICanSeeProperty; \ No newline at end of file + Guid PropertyId) : IQuery, ICanRead +{ + Guid? IResourcePolicy.ResourceId => PropertyId; +} \ No newline at end of file diff --git a/backend/ECondo.Application/Queries/Properties/GetById/GetPropertyByIdQueryHandler.cs b/backend/ECondo.Application/Queries/Properties/GetById/GetPropertyByIdQueryHandler.cs index d87c806..d8785c7 100644 --- a/backend/ECondo.Application/Queries/Properties/GetById/GetPropertyByIdQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Properties/GetById/GetPropertyByIdQueryHandler.cs @@ -1,7 +1,6 @@ -using ECondo.Application.Data; -using ECondo.Application.Data.Property; +using ECondo.Application.Data.Property; using ECondo.Application.Repositories; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Properties.GetById; diff --git a/backend/ECondo.Application/Queries/Properties/GetForUser/GetPropertiesForUserQuery.cs b/backend/ECondo.Application/Queries/Properties/GetForUser/GetPropertiesForUserQuery.cs index 0b49ff5..ae6be14 100644 --- a/backend/ECondo.Application/Queries/Properties/GetForUser/GetPropertiesForUserQuery.cs +++ b/backend/ECondo.Application/Queries/Properties/GetForUser/GetPropertiesForUserQuery.cs @@ -1,6 +1,5 @@ -using ECondo.Application.Data; -using ECondo.Application.Data.Property; -using ECondo.Domain.Shared; +using ECondo.Application.Data.Property; +using ECondo.SharedKernel.Collections; namespace ECondo.Application.Queries.Properties.GetForUser; diff --git a/backend/ECondo.Application/Queries/Properties/GetForUser/GetPropertiesForUserQueryHandler.cs b/backend/ECondo.Application/Queries/Properties/GetForUser/GetPropertiesForUserQueryHandler.cs index be382a2..1012055 100644 --- a/backend/ECondo.Application/Queries/Properties/GetForUser/GetPropertiesForUserQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Properties/GetForUser/GetPropertiesForUserQueryHandler.cs @@ -1,10 +1,10 @@ -using ECondo.Application.Data; -using ECondo.Application.Data.Occupant; +using ECondo.Application.Data.Occupant; using ECondo.Application.Data.Property; using ECondo.Application.Extensions; using ECondo.Application.Repositories; using ECondo.Application.Services; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Collections; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Properties.GetForUser; diff --git a/backend/ECondo.Application/Queries/Properties/GetInBuilding/GetPropertiesInBuildingQuery.cs b/backend/ECondo.Application/Queries/Properties/GetInBuilding/GetPropertiesInBuildingQuery.cs deleted file mode 100644 index 2b48786..0000000 --- a/backend/ECondo.Application/Queries/Properties/GetInBuilding/GetPropertiesInBuildingQuery.cs +++ /dev/null @@ -1,12 +0,0 @@ -using ECondo.Application.Data; -using ECondo.Application.Data.Property; -using ECondo.Domain.Shared; - -namespace ECondo.Application.Queries.Properties.GetInBuilding; - -public sealed record GetPropertiesInBuildingQuery( - Guid BuildingId, - string EntranceNumber, - int Page, - int PageSize) - : IQuery>; diff --git a/backend/ECondo.Application/Queries/Properties/GetInEntrance/GetPropertiesInEntranceQuery.cs b/backend/ECondo.Application/Queries/Properties/GetInEntrance/GetPropertiesInEntranceQuery.cs new file mode 100644 index 0000000..138c871 --- /dev/null +++ b/backend/ECondo.Application/Queries/Properties/GetInEntrance/GetPropertiesInEntranceQuery.cs @@ -0,0 +1,15 @@ +using ECondo.Application.Data.Property; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; +using ECondo.SharedKernel.Collections; + +namespace ECondo.Application.Queries.Properties.GetInEntrance; + +public sealed record GetPropertiesInEntranceQuery( + Guid EntranceId, + int Page, + int PageSize) + : IQuery>, ICanRead +{ + Guid? IResourcePolicy.ResourceId => EntranceId; +} diff --git a/backend/ECondo.Application/Queries/Properties/GetInBuilding/GetPropertiesInBuildingQueryHandler.cs b/backend/ECondo.Application/Queries/Properties/GetInEntrance/GetPropertiesInEntranceQueryHandler.cs similarity index 77% rename from backend/ECondo.Application/Queries/Properties/GetInBuilding/GetPropertiesInBuildingQueryHandler.cs rename to backend/ECondo.Application/Queries/Properties/GetInEntrance/GetPropertiesInEntranceQueryHandler.cs index de8f394..5a975c2 100644 --- a/backend/ECondo.Application/Queries/Properties/GetInBuilding/GetPropertiesInBuildingQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Properties/GetInEntrance/GetPropertiesInEntranceQueryHandler.cs @@ -1,19 +1,19 @@ -using ECondo.Application.Data; -using ECondo.Application.Data.Occupant; +using ECondo.Application.Data.Occupant; using ECondo.Application.Data.Property; using ECondo.Application.Extensions; using ECondo.Application.Repositories; using ECondo.Application.Services; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Collections; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; -namespace ECondo.Application.Queries.Properties.GetInBuilding; +namespace ECondo.Application.Queries.Properties.GetInEntrance; -internal sealed class GetPropertiesInBuildingQueryHandler +internal sealed class GetPropertiesInEntranceQueryHandler (IApplicationDbContext dbContext, IUserContext userContext) - : IQueryHandler> + : IQueryHandler> { - public async Task, Error>> Handle(GetPropertiesInBuildingQuery request, CancellationToken cancellationToken) + public async Task, Error>> Handle(GetPropertiesInEntranceQuery request, CancellationToken cancellationToken) { var properties = await dbContext.Entrances .Include(e => e.Properties) @@ -22,8 +22,7 @@ public async Task, Error>> Handle(GetPr .ThenInclude(p => p.PropertyOccupants) .AsNoTracking() .Where(e => - e.BuildingId == request.BuildingId && - e.Number == request.EntranceNumber && + e.Id == request.EntranceId && e.ManagerId == userContext.UserId) .SelectMany(e => e.Properties diff --git a/backend/ECondo.Application/Queries/PropertyOccupants/GetInProperty/GetOccupantsInPropertyQuery.cs b/backend/ECondo.Application/Queries/PropertyOccupants/GetInProperty/GetOccupantsInPropertyQuery.cs index 558fb73..769d535 100644 --- a/backend/ECondo.Application/Queries/PropertyOccupants/GetInProperty/GetOccupantsInPropertyQuery.cs +++ b/backend/ECondo.Application/Queries/PropertyOccupants/GetInProperty/GetOccupantsInPropertyQuery.cs @@ -1,8 +1,12 @@ using ECondo.Application.Data.Occupant; -using ECondo.Application.Policies; +using ECondo.Domain.Authorization; +using ECondo.Domain.Buildings; namespace ECondo.Application.Queries.PropertyOccupants.GetInProperty; // TODO: make paged list public sealed record GetOccupantsInPropertyQuery(Guid PropertyId) - : IQuery>, ICanEditProperty; + : IQuery>, ICanRead +{ + Guid? IResourcePolicy.ResourceId => PropertyId; +} diff --git a/backend/ECondo.Application/Queries/PropertyOccupants/GetInProperty/GetOccupantsInPropertyQueryHandler.cs b/backend/ECondo.Application/Queries/PropertyOccupants/GetInProperty/GetOccupantsInPropertyQueryHandler.cs index 24d8a67..02a15c0 100644 --- a/backend/ECondo.Application/Queries/PropertyOccupants/GetInProperty/GetOccupantsInPropertyQueryHandler.cs +++ b/backend/ECondo.Application/Queries/PropertyOccupants/GetInProperty/GetOccupantsInPropertyQueryHandler.cs @@ -1,6 +1,6 @@ using ECondo.Application.Data.Occupant; using ECondo.Application.Repositories; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.PropertyOccupants.GetInProperty; diff --git a/backend/ECondo.Application/Queries/PropertyOccupants/GetTenantsInProperty/GetTenantsInPropertyQuery.cs b/backend/ECondo.Application/Queries/PropertyOccupants/GetTenantsInProperty/GetTenantsInPropertyQuery.cs index 908b861..acffb61 100644 --- a/backend/ECondo.Application/Queries/PropertyOccupants/GetTenantsInProperty/GetTenantsInPropertyQuery.cs +++ b/backend/ECondo.Application/Queries/PropertyOccupants/GetTenantsInProperty/GetTenantsInPropertyQuery.cs @@ -1,5 +1,5 @@ using ECondo.Application.Data.Occupant; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Collections; namespace ECondo.Application.Queries.PropertyOccupants.GetTenantsInProperty; diff --git a/backend/ECondo.Application/Queries/PropertyOccupants/GetTenantsInProperty/GetTenantsInPropertyQueryHandler.cs b/backend/ECondo.Application/Queries/PropertyOccupants/GetTenantsInProperty/GetTenantsInPropertyQueryHandler.cs index 9fe0bdb..ff40af5 100644 --- a/backend/ECondo.Application/Queries/PropertyOccupants/GetTenantsInProperty/GetTenantsInPropertyQueryHandler.cs +++ b/backend/ECondo.Application/Queries/PropertyOccupants/GetTenantsInProperty/GetTenantsInPropertyQueryHandler.cs @@ -1,7 +1,9 @@ using ECondo.Application.Data.Occupant; using ECondo.Application.Extensions; using ECondo.Application.Repositories; -using ECondo.Domain.Shared; +using ECondo.Domain.Buildings; +using ECondo.SharedKernel.Collections; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.PropertyOccupants.GetTenantsInProperty; @@ -18,7 +20,7 @@ public async Task, Error>> Handle(GetTenantsInP .AsNoTracking() .Where(po => po.PropertyId == request.PropertyId && - po.OccupantType.Name != "Собственик") + po.OccupantType.Name != OccupantType.OwnerType) .Select(po => new OccupantResult( po.Id, diff --git a/backend/ECondo.Application/Queries/PropertyOccupants/IsUser/IsUserPropertyOccupantQueryHandler.cs b/backend/ECondo.Application/Queries/PropertyOccupants/IsUser/IsUserPropertyOccupantQueryHandler.cs index 4e83b4d..899921b 100644 --- a/backend/ECondo.Application/Queries/PropertyOccupants/IsUser/IsUserPropertyOccupantQueryHandler.cs +++ b/backend/ECondo.Application/Queries/PropertyOccupants/IsUser/IsUserPropertyOccupantQueryHandler.cs @@ -1,7 +1,7 @@ using ECondo.Application.Repositories; using ECondo.Application.Services; using ECondo.Domain.Buildings; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.PropertyOccupants.IsUser; diff --git a/backend/ECondo.Application/Queries/PropertyTypes/GetAll/GetAllPropertyTypesQueryHandler.cs b/backend/ECondo.Application/Queries/PropertyTypes/GetAll/GetAllPropertyTypesQueryHandler.cs index 137d2d3..775d2b9 100644 --- a/backend/ECondo.Application/Queries/PropertyTypes/GetAll/GetAllPropertyTypesQueryHandler.cs +++ b/backend/ECondo.Application/Queries/PropertyTypes/GetAll/GetAllPropertyTypesQueryHandler.cs @@ -1,6 +1,6 @@ using ECondo.Application.Commands; using ECondo.Application.Repositories; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.PropertyTypes.GetAll; diff --git a/backend/ECondo.Application/Queries/Provinces/GetAll/GetProvincesQueryHandler.cs b/backend/ECondo.Application/Queries/Provinces/GetAll/GetProvincesQueryHandler.cs index 28bbf42..b1cb236 100644 --- a/backend/ECondo.Application/Queries/Provinces/GetAll/GetProvincesQueryHandler.cs +++ b/backend/ECondo.Application/Queries/Provinces/GetAll/GetProvincesQueryHandler.cs @@ -1,5 +1,5 @@ using ECondo.Application.Repositories; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; using Microsoft.EntityFrameworkCore; namespace ECondo.Application.Queries.Provinces.GetAll; diff --git a/backend/ECondo.Application/Repositories/ICacheRepository.cs b/backend/ECondo.Application/Repositories/ICacheRepository.cs index 412a9e5..f427b34 100644 --- a/backend/ECondo.Application/Repositories/ICacheRepository.cs +++ b/backend/ECondo.Application/Repositories/ICacheRepository.cs @@ -8,3 +8,4 @@ public interface ICacheRepository Task StoreAsync(string key, T value, DistributedCacheEntryOptions? entryOptions = null, CancellationToken cancellationToken = default) where T : class; Task RemoveAsync(string key, CancellationToken cancellationToken = default); } + \ No newline at end of file diff --git a/backend/ECondo.Application/Services/IAuthorizationService.cs b/backend/ECondo.Application/Services/IAuthorizationService.cs new file mode 100644 index 0000000..e73ea90 --- /dev/null +++ b/backend/ECondo.Application/Services/IAuthorizationService.cs @@ -0,0 +1,18 @@ +using ECondo.Domain.Authorization; + +namespace ECondo.Application.Services; + +public interface IAuthorizationService +{ + Task CanPerformActionAsync(Guid userId, + Guid? resourceId, + AccessLevel resourceAccess, + CancellationToken cancellationToken = default) + where T : class; + + + Task> ApplyDataFilterAsync(IQueryable query, + Guid userId, + CancellationToken cancellationToken = default) + where T : class; +} \ No newline at end of file diff --git a/backend/ECondo.Application/Shared/Utils.cs b/backend/ECondo.Application/Shared/Utils.cs deleted file mode 100644 index 520c75b..0000000 --- a/backend/ECondo.Application/Shared/Utils.cs +++ /dev/null @@ -1,27 +0,0 @@ -using ECondo.Domain.Shared; - -namespace ECondo.Application.Shared; - -internal static class Utils -{ - public static bool IsTypeResultType() - => typeof(T).IsGenericType && - typeof(T).GetGenericTypeDefinition() == typeof(Result<,>); - - public static T? InvokeResultFail(object?[]? parameters) - { - Type resultType = typeof(T).GetGenericArguments()[0]; - var failMethodInfo = typeof(Result<,>) - .MakeGenericType(resultType, typeof(Error)) - .GetMethod(nameof(Result.Fail)); - - object? res = failMethodInfo?.Invoke( - null, - parameters); - - if (res is not null) - return (T)res; - - return default; - } -} \ No newline at end of file diff --git a/backend/ECondo.Domain/Authorization/AccessLevel.cs b/backend/ECondo.Domain/Authorization/AccessLevel.cs new file mode 100644 index 0000000..dd8d48e --- /dev/null +++ b/backend/ECondo.Domain/Authorization/AccessLevel.cs @@ -0,0 +1,15 @@ +namespace ECondo.Domain.Authorization; + +[Flags] +public enum AccessLevel +{ + None = 0, + Create = 1 << 0, + Read = 1 << 1, + Update = 1 << 2, + Delete = 1 << 3, + Write = Create | Update, + ReadWrite = Read | Write, + ReadUpdate = Read | Update, + All = Read | Write | Delete, +} diff --git a/backend/ECondo.Domain/Authorization/ICanCreate.cs b/backend/ECondo.Domain/Authorization/ICanCreate.cs new file mode 100644 index 0000000..5b8df44 --- /dev/null +++ b/backend/ECondo.Domain/Authorization/ICanCreate.cs @@ -0,0 +1,7 @@ +namespace ECondo.Domain.Authorization; + +public interface ICanCreate : IResourcePolicy + where T : class +{ + AccessLevel IResourcePolicy.ResourceAction => AccessLevel.Create; +} \ No newline at end of file diff --git a/backend/ECondo.Domain/Authorization/ICanDelete.cs b/backend/ECondo.Domain/Authorization/ICanDelete.cs new file mode 100644 index 0000000..38ec3f2 --- /dev/null +++ b/backend/ECondo.Domain/Authorization/ICanDelete.cs @@ -0,0 +1,7 @@ +namespace ECondo.Domain.Authorization; + +public interface ICanDelete : IResourcePolicy + where T : class +{ + AccessLevel IResourcePolicy.ResourceAction => AccessLevel.Delete; +} \ No newline at end of file diff --git a/backend/ECondo.Domain/Authorization/ICanRead.cs b/backend/ECondo.Domain/Authorization/ICanRead.cs new file mode 100644 index 0000000..4faac1b --- /dev/null +++ b/backend/ECondo.Domain/Authorization/ICanRead.cs @@ -0,0 +1,7 @@ +namespace ECondo.Domain.Authorization; + +public interface ICanRead : IResourcePolicy + where T : class +{ + AccessLevel IResourcePolicy.ResourceAction => AccessLevel.Read; +} \ No newline at end of file diff --git a/backend/ECondo.Domain/Authorization/ICanUpdate.cs b/backend/ECondo.Domain/Authorization/ICanUpdate.cs new file mode 100644 index 0000000..3ed9e79 --- /dev/null +++ b/backend/ECondo.Domain/Authorization/ICanUpdate.cs @@ -0,0 +1,7 @@ +namespace ECondo.Domain.Authorization; + +public interface ICanUpdate : IResourcePolicy + where T : class +{ + AccessLevel IResourcePolicy.ResourceAction => AccessLevel.Update; +} \ No newline at end of file diff --git a/backend/ECondo.Domain/Authorization/IResourcePolicy.cs b/backend/ECondo.Domain/Authorization/IResourcePolicy.cs new file mode 100644 index 0000000..90b90e4 --- /dev/null +++ b/backend/ECondo.Domain/Authorization/IResourcePolicy.cs @@ -0,0 +1,13 @@ +namespace ECondo.Domain.Authorization; + +public interface IResourcePolicy : IResourcePolicy where T : class +{ + Type IResourcePolicy.ResourceType => typeof(T); +} + +public interface IResourcePolicy +{ + Type ResourceType { get; } + Guid? ResourceId { get; } + AccessLevel ResourceAction { get; } +} diff --git a/backend/ECondo.Domain/Authorization/PermissionScope.cs b/backend/ECondo.Domain/Authorization/PermissionScope.cs new file mode 100644 index 0000000..07007de --- /dev/null +++ b/backend/ECondo.Domain/Authorization/PermissionScope.cs @@ -0,0 +1,7 @@ +namespace ECondo.Domain.Authorization; + +public enum PermissionScope +{ + Resource = 0, + Global +} \ No newline at end of file diff --git a/backend/ECondo.Domain/Buildings/BuildingErrors.cs b/backend/ECondo.Domain/Buildings/BuildingErrors.cs index 7837fd2..3aeabba 100644 --- a/backend/ECondo.Domain/Buildings/BuildingErrors.cs +++ b/backend/ECondo.Domain/Buildings/BuildingErrors.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; namespace ECondo.Domain.Buildings; diff --git a/backend/ECondo.Domain/Buildings/EntranceErrors.cs b/backend/ECondo.Domain/Buildings/EntranceErrors.cs index f8c7924..2b99907 100644 --- a/backend/ECondo.Domain/Buildings/EntranceErrors.cs +++ b/backend/ECondo.Domain/Buildings/EntranceErrors.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; namespace ECondo.Domain.Buildings; @@ -8,9 +8,9 @@ public static Error AlreadyExists(Guid buildingId, string entranceNumber) => Error.Conflict("Entrance.AlreadyExists", $"The entrance {entranceNumber} for building {buildingId} already exists"); - public static Error InvalidEntrance(Guid buildingId, string entranceNumber) => + public static Error InvalidEntrance(Guid entranceId) => Error.NotFound("Entrance.Invalid", - $"The entrance {entranceNumber} for building {buildingId} is invalid"); + $"The entrance with id = {entranceId} is invalid"); public static Error Forbidden(Guid buildingId, string entranceNumber) => Error.Forbidden("Entrance.Forbidden", diff --git a/backend/ECondo.Domain/Buildings/OccupantType.cs b/backend/ECondo.Domain/Buildings/OccupantType.cs index 6f37645..f99496a 100644 --- a/backend/ECondo.Domain/Buildings/OccupantType.cs +++ b/backend/ECondo.Domain/Buildings/OccupantType.cs @@ -3,7 +3,12 @@ public sealed class OccupantType { public Guid Id { get; set; } = Guid.NewGuid(); - public string Name { get; set; } = null!; + public required string Name { get; set; } = null!; public HashSet PropertyOccupants { get; set; } = []; + + public const string TenantType = "tennant"; + public const string OwnerType = "owner"; + public const string UserType = "user"; + public const string RepresentativeType = "representative"; } diff --git a/backend/ECondo.Domain/Buildings/OccupantTypeErrors.cs b/backend/ECondo.Domain/Buildings/OccupantTypeErrors.cs index 4c76e64..1f90535 100644 --- a/backend/ECondo.Domain/Buildings/OccupantTypeErrors.cs +++ b/backend/ECondo.Domain/Buildings/OccupantTypeErrors.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; namespace ECondo.Domain.Buildings; diff --git a/backend/ECondo.Domain/Buildings/PropertyErrors.cs b/backend/ECondo.Domain/Buildings/PropertyErrors.cs index 6c13dc3..0e6cd9b 100644 --- a/backend/ECondo.Domain/Buildings/PropertyErrors.cs +++ b/backend/ECondo.Domain/Buildings/PropertyErrors.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; namespace ECondo.Domain.Buildings; diff --git a/backend/ECondo.Domain/Buildings/PropertyOccupantError.cs b/backend/ECondo.Domain/Buildings/PropertyOccupantError.cs index 0b9ae15..0ec4776 100644 --- a/backend/ECondo.Domain/Buildings/PropertyOccupantError.cs +++ b/backend/ECondo.Domain/Buildings/PropertyOccupantError.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; namespace ECondo.Domain.Buildings; diff --git a/backend/ECondo.Domain/PropertyTypeErrors.cs b/backend/ECondo.Domain/Buildings/PropertyTypeErrors.cs similarity index 77% rename from backend/ECondo.Domain/PropertyTypeErrors.cs rename to backend/ECondo.Domain/Buildings/PropertyTypeErrors.cs index 59889a8..d55b2ed 100644 --- a/backend/ECondo.Domain/PropertyTypeErrors.cs +++ b/backend/ECondo.Domain/Buildings/PropertyTypeErrors.cs @@ -1,6 +1,6 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; -namespace ECondo.Domain; +namespace ECondo.Domain.Buildings; public static class PropertyTypeErrors { diff --git a/backend/ECondo.Domain/ECondo.Domain.csproj b/backend/ECondo.Domain/ECondo.Domain.csproj index f05d832..a39c381 100644 --- a/backend/ECondo.Domain/ECondo.Domain.csproj +++ b/backend/ECondo.Domain/ECondo.Domain.csproj @@ -10,4 +10,8 @@ + + + + diff --git a/backend/ECondo.Domain/Payments/Bill.cs b/backend/ECondo.Domain/Payments/Bill.cs index 14d35f6..0ee4e0d 100644 --- a/backend/ECondo.Domain/Payments/Bill.cs +++ b/backend/ECondo.Domain/Payments/Bill.cs @@ -9,17 +9,17 @@ public sealed class Bill public string Title { get; set; } = null!; public string? Description { get; set; } public decimal Amount { get; set; } - + public Guid EntranceId { get; set; } public Entrance Entrance { get; set; } = null!; - + public bool IsRecurring { get; set; } public RecurringInterval? RecurringInterval { get; set; } - + public DateTimeOffset StartDate { get; set; } public DateTimeOffset? EndDate { get; set; } public DateTimeOffset CreatedAt { get; set; } - + public Guid CreatedByUserId { get; set; } public User CreatedByUser { get; set; } = null!; @@ -40,4 +40,5 @@ public enum BillStatus Pending, Paid, Cancelled, -} \ No newline at end of file +} + diff --git a/backend/ECondo.Domain/Payments/PaymentErrors.cs b/backend/ECondo.Domain/Payments/PaymentErrors.cs index d5eaf25..1518fca 100644 --- a/backend/ECondo.Domain/Payments/PaymentErrors.cs +++ b/backend/ECondo.Domain/Payments/PaymentErrors.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; namespace ECondo.Domain.Payments; diff --git a/backend/ECondo.Domain/Profiles/ProfileErrors.cs b/backend/ECondo.Domain/Profiles/ProfileErrors.cs index 492acaa..ee7ce7f 100644 --- a/backend/ECondo.Domain/Profiles/ProfileErrors.cs +++ b/backend/ECondo.Domain/Profiles/ProfileErrors.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; namespace ECondo.Domain.Profiles; public static class ProfileErrors diff --git a/backend/ECondo.Domain/Provinces/ProvinceErrors.cs b/backend/ECondo.Domain/Provinces/ProvinceErrors.cs index 618a411..e91fc28 100644 --- a/backend/ECondo.Domain/Provinces/ProvinceErrors.cs +++ b/backend/ECondo.Domain/Provinces/ProvinceErrors.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; namespace ECondo.Domain.Provinces; diff --git a/backend/ECondo.Domain/Users/Role.cs b/backend/ECondo.Domain/Users/Role.cs index 5a0f609..2a00b10 100644 --- a/backend/ECondo.Domain/Users/Role.cs +++ b/backend/ECondo.Domain/Users/Role.cs @@ -6,4 +6,6 @@ public class Role : IdentityRole { public HashSet UserRoles { get; set; } = null!; public HashSet RoleClaims { get; set; } = null!; + + public const string Admin = "admin"; } diff --git a/backend/ECondo.Domain/Users/RoleErrors.cs b/backend/ECondo.Domain/Users/RoleErrors.cs index 422fc39..f067364 100644 --- a/backend/ECondo.Domain/Users/RoleErrors.cs +++ b/backend/ECondo.Domain/Users/RoleErrors.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; namespace ECondo.Domain.Users; diff --git a/backend/ECondo.Domain/Users/UserErrors.cs b/backend/ECondo.Domain/Users/UserErrors.cs index 085b6c4..456d4b0 100644 --- a/backend/ECondo.Domain/Users/UserErrors.cs +++ b/backend/ECondo.Domain/Users/UserErrors.cs @@ -1,4 +1,4 @@ -using ECondo.Domain.Shared; +using ECondo.SharedKernel.Result; namespace ECondo.Domain.Users; public static class UserErrors diff --git a/backend/ECondo.Infrastructure/Data/BuildingSeedData.cs b/backend/ECondo.Infrastructure/Data/BuildingSeedData.cs index 49ef9b1..aad7079 100644 --- a/backend/ECondo.Infrastructure/Data/BuildingSeedData.cs +++ b/backend/ECondo.Infrastructure/Data/BuildingSeedData.cs @@ -1,4 +1,4 @@ -namespace ECondo.Infrastructure.Shared; +namespace ECondo.Infrastructure.Data; internal static class BuildingSeedData { diff --git a/backend/ECondo.Infrastructure/Data/EntranceSeedData.cs b/backend/ECondo.Infrastructure/Data/EntranceSeedData.cs index fac961f..fe134cf 100644 --- a/backend/ECondo.Infrastructure/Data/EntranceSeedData.cs +++ b/backend/ECondo.Infrastructure/Data/EntranceSeedData.cs @@ -1,5 +1,4 @@ using ECondo.Domain.Buildings; -using ECondo.Infrastructure.Shared; namespace ECondo.Infrastructure.Data; diff --git a/backend/ECondo.Infrastructure/Data/OccupantSeedData.cs b/backend/ECondo.Infrastructure/Data/OccupantSeedData.cs index 935bda2..c27e9ce 100644 --- a/backend/ECondo.Infrastructure/Data/OccupantSeedData.cs +++ b/backend/ECondo.Infrastructure/Data/OccupantSeedData.cs @@ -1,11 +1,10 @@ using ECondo.Domain.Buildings; -using ECondo.Infrastructure.Shared; namespace ECondo.Infrastructure.Data; internal static class OccupantSeedData { - public static readonly PropertyOccupant BasicTenantApartmentOccupant = new PropertyOccupant + private static readonly PropertyOccupant BasicTenantApartmentOccupant = new PropertyOccupant { Id = Guid.Parse("d594e8ac-b4d0-4d85-a9d4-4fe944157d48"), PropertyId = PropertySeedData.ApartmentProperty.Id, @@ -17,8 +16,8 @@ internal static class OccupantSeedData OccupantTypeId = OccupantTypeSeedData.ТenantType.Id, InvitationStatus = InvitationStatus.Accepted, }; - - public static readonly PropertyOccupant BasicTenantStudioOccupant = new PropertyOccupant + + private static readonly PropertyOccupant BasicTenantStudioOccupant = new PropertyOccupant { Id = Guid.Parse("92fb9a2a-2df4-4eb0-878e-b216d1b4196b"), PropertyId = PropertySeedData.StudioProperty.Id, @@ -30,8 +29,8 @@ internal static class OccupantSeedData OccupantTypeId = OccupantTypeSeedData.ТenantType.Id, InvitationStatus = InvitationStatus.Accepted, }; - - public static readonly PropertyOccupant BasicTenantOfficeOccupant = new PropertyOccupant + + private static readonly PropertyOccupant BasicTenantOfficeOccupant = new PropertyOccupant { Id = Guid.Parse("724221fb-b21a-40da-8721-299a0299e860"), PropertyId = PropertySeedData.OfficeProperty.Id, @@ -50,8 +49,8 @@ internal static class OccupantSeedData BasicTenantStudioOccupant, BasicTenantOfficeOccupant, ]; - - public static readonly PropertyOccupant BasicOwnerApartmentOccupant = new PropertyOccupant + + private static readonly PropertyOccupant BasicOwnerApartmentOccupant = new PropertyOccupant { Id = Guid.Parse("b14afc55-02b6-4eeb-a08e-6ce1d14e0308"), PropertyId = PropertySeedData.ApartmentProperty.Id, @@ -63,8 +62,8 @@ internal static class OccupantSeedData OccupantTypeId = OccupantTypeSeedData.OwnerType.Id, InvitationStatus = InvitationStatus.Accepted, }; - - public static readonly PropertyOccupant BasicOwnerStudioOccupant = new PropertyOccupant + + private static readonly PropertyOccupant BasicOwnerStudioOccupant = new PropertyOccupant { Id = Guid.Parse("c323652c-6493-47bd-b2d0-60210ea7b762"), PropertyId = PropertySeedData.StudioProperty.Id, @@ -76,8 +75,8 @@ internal static class OccupantSeedData OccupantTypeId = OccupantTypeSeedData.OwnerType.Id, InvitationStatus = InvitationStatus.Accepted, }; - - public static readonly PropertyOccupant BasicOwnerOfficeOccupant = new PropertyOccupant + + private static readonly PropertyOccupant BasicOwnerOfficeOccupant = new PropertyOccupant { Id = Guid.Parse("933d23ab-96a2-4ac5-8d6b-0a9f607f0920"), PropertyId = PropertySeedData.OfficeProperty.Id, diff --git a/backend/ECondo.Infrastructure/Data/OccupantTypeSeedData.cs b/backend/ECondo.Infrastructure/Data/OccupantTypeSeedData.cs index 34b22d3..cf12a2a 100644 --- a/backend/ECondo.Infrastructure/Data/OccupantTypeSeedData.cs +++ b/backend/ECondo.Infrastructure/Data/OccupantTypeSeedData.cs @@ -7,25 +7,25 @@ internal static class OccupantTypeSeedData public static readonly OccupantType ТenantType = new OccupantType { Id = Guid.Parse("bfe5e4d5-3720-4205-b02c-8ca416cf9aa2"), - Name = "Наемател", + Name = OccupantType.TenantType, }; public static readonly OccupantType OwnerType = new OccupantType { Id = Guid.Parse("cd0a8523-212f-4ed7-b6cf-cc779f4aabde"), - Name = "Собственик", + Name = OccupantType.OwnerType, }; public static readonly OccupantType UserType = new OccupantType { Id = Guid.Parse("566f8ad5-4f03-4662-b690-3d88e929f7e9"), - Name = "Ползвател", + Name = OccupantType.UserType, }; public static readonly OccupantType RepresentativeType = new OccupantType { Id = Guid.Parse("67cbf878-01b6-4800-87c9-a4ced25aad35"), - Name = "Представител", + Name = OccupantType.RepresentativeType, }; public static readonly IEnumerable OccupantTypes = diff --git a/backend/ECondo.Infrastructure/Data/PropertySeedData.cs b/backend/ECondo.Infrastructure/Data/PropertySeedData.cs index 161077c..4b0a0f1 100644 --- a/backend/ECondo.Infrastructure/Data/PropertySeedData.cs +++ b/backend/ECondo.Infrastructure/Data/PropertySeedData.cs @@ -1,5 +1,4 @@ using ECondo.Domain.Buildings; -using ECondo.Infrastructure.Shared; namespace ECondo.Infrastructure.Data; diff --git a/backend/ECondo.Infrastructure/Data/RoleSeedData.cs b/backend/ECondo.Infrastructure/Data/RoleSeedData.cs index 286865b..8f60f67 100644 --- a/backend/ECondo.Infrastructure/Data/RoleSeedData.cs +++ b/backend/ECondo.Infrastructure/Data/RoleSeedData.cs @@ -7,7 +7,7 @@ public static class RoleSeedData public static readonly Role AdminRole = new() { Id = Guid.Parse("0e052fa5-fedb-4ce1-a4fd-599b8725e244"), - Name = "admin", + Name = Role.Admin, }; public static readonly Role[] Roles = diff --git a/backend/ECondo.Infrastructure/Data/UserSeedData.cs b/backend/ECondo.Infrastructure/Data/UserSeedData.cs index d264c26..719824d 100644 --- a/backend/ECondo.Infrastructure/Data/UserSeedData.cs +++ b/backend/ECondo.Infrastructure/Data/UserSeedData.cs @@ -53,7 +53,7 @@ internal record UserSeedInfo(User User, string Password, string[] Roles); PhoneNumber = "0881231231", EmailConfirmed = true, }, - Password: "testPass@T1", ["admin"] + Password: "testPass@T1", [Role.Admin] ); public static readonly ProfileDetails BasicUserProfile = diff --git a/backend/ECondo.Infrastructure/Extensions/Seeders/BuildingSeederConfiguration.cs b/backend/ECondo.Infrastructure/Extensions/Seeders/BuildingSeederConfiguration.cs index 4ffb6a2..4aedea1 100644 --- a/backend/ECondo.Infrastructure/Extensions/Seeders/BuildingSeederConfiguration.cs +++ b/backend/ECondo.Infrastructure/Extensions/Seeders/BuildingSeederConfiguration.cs @@ -1,7 +1,7 @@ using ECondo.Application.Repositories; using ECondo.Domain.Buildings; using ECondo.Domain.Provinces; -using ECondo.Infrastructure.Shared; +using ECondo.Infrastructure.Data; using Microsoft.AspNetCore.Builder; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; diff --git a/backend/ECondo.Infrastructure/Extensions/Seeders/EntranceSeederConfiguration.cs b/backend/ECondo.Infrastructure/Extensions/Seeders/EntranceSeederConfiguration.cs index d149a9a..24b58e0 100644 --- a/backend/ECondo.Infrastructure/Extensions/Seeders/EntranceSeederConfiguration.cs +++ b/backend/ECondo.Infrastructure/Extensions/Seeders/EntranceSeederConfiguration.cs @@ -1,6 +1,5 @@ using ECondo.Application.Repositories; using ECondo.Infrastructure.Data; -using ECondo.Infrastructure.Shared; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/backend/ECondo.Infrastructure/Extensions/Seeders/OccupantSeederConfiguration.cs b/backend/ECondo.Infrastructure/Extensions/Seeders/OccupantSeederConfiguration.cs index fe186e4..b1d8f48 100644 --- a/backend/ECondo.Infrastructure/Extensions/Seeders/OccupantSeederConfiguration.cs +++ b/backend/ECondo.Infrastructure/Extensions/Seeders/OccupantSeederConfiguration.cs @@ -1,6 +1,5 @@ using ECondo.Application.Repositories; using ECondo.Infrastructure.Data; -using ECondo.Infrastructure.Shared; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/backend/ECondo.Infrastructure/Extensions/Seeders/OccupantTypeSeederConfiguration.cs b/backend/ECondo.Infrastructure/Extensions/Seeders/OccupantTypeSeederConfiguration.cs index d4288e0..f1f51bc 100644 --- a/backend/ECondo.Infrastructure/Extensions/Seeders/OccupantTypeSeederConfiguration.cs +++ b/backend/ECondo.Infrastructure/Extensions/Seeders/OccupantTypeSeederConfiguration.cs @@ -1,6 +1,5 @@ using ECondo.Application.Repositories; using ECondo.Infrastructure.Data; -using ECondo.Infrastructure.Shared; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/backend/ECondo.Infrastructure/Extensions/Seeders/PropertySeederConfiguration.cs b/backend/ECondo.Infrastructure/Extensions/Seeders/PropertySeederConfiguration.cs index e6edf90..1f57d80 100644 --- a/backend/ECondo.Infrastructure/Extensions/Seeders/PropertySeederConfiguration.cs +++ b/backend/ECondo.Infrastructure/Extensions/Seeders/PropertySeederConfiguration.cs @@ -1,6 +1,5 @@ using ECondo.Application.Repositories; using ECondo.Infrastructure.Data; -using ECondo.Infrastructure.Shared; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/backend/ECondo.Infrastructure/Extensions/Seeders/PropertyTypeSeederConfiguration.cs b/backend/ECondo.Infrastructure/Extensions/Seeders/PropertyTypeSeederConfiguration.cs index 6e238d8..f1a8975 100644 --- a/backend/ECondo.Infrastructure/Extensions/Seeders/PropertyTypeSeederConfiguration.cs +++ b/backend/ECondo.Infrastructure/Extensions/Seeders/PropertyTypeSeederConfiguration.cs @@ -1,6 +1,5 @@ using ECondo.Application.Repositories; using ECondo.Infrastructure.Data; -using ECondo.Infrastructure.Shared; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/backend/ECondo.Infrastructure/Extensions/Seeders/ProvinceSeederConfiguration.cs b/backend/ECondo.Infrastructure/Extensions/Seeders/ProvinceSeederConfiguration.cs index 4186315..e5a36c5 100644 --- a/backend/ECondo.Infrastructure/Extensions/Seeders/ProvinceSeederConfiguration.cs +++ b/backend/ECondo.Infrastructure/Extensions/Seeders/ProvinceSeederConfiguration.cs @@ -1,7 +1,6 @@ using ECondo.Application.Repositories; using ECondo.Domain.Provinces; using ECondo.Infrastructure.Data; -using ECondo.Infrastructure.Shared; using Microsoft.AspNetCore.Builder; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; diff --git a/backend/ECondo.Infrastructure/Extensions/Seeders/RoleSeederConfiguration.cs b/backend/ECondo.Infrastructure/Extensions/Seeders/RoleSeederConfiguration.cs index 76b0973..4ef39f3 100644 --- a/backend/ECondo.Infrastructure/Extensions/Seeders/RoleSeederConfiguration.cs +++ b/backend/ECondo.Infrastructure/Extensions/Seeders/RoleSeederConfiguration.cs @@ -1,5 +1,4 @@ -using ECondo.Application.Repositories; -using ECondo.Domain.Users; +using ECondo.Domain.Users; using ECondo.Infrastructure.Data; using ECondo.Infrastructure.Shared; using Microsoft.AspNetCore.Builder; @@ -24,9 +23,6 @@ public static async Task SeedRoles(this IApplicationBuilder appBuilder) var logger = services .GetRequiredService>(); - var dbContext = services - .GetRequiredService(); - using (logger.BeginScope("Role creation")) { foreach (var role in RoleSeedData.Roles) diff --git a/backend/ECondo.Infrastructure/Extensions/Seeders/UserSeederConfiguration.cs b/backend/ECondo.Infrastructure/Extensions/Seeders/UserSeederConfiguration.cs index 05e7bbf..97d0d9c 100644 --- a/backend/ECondo.Infrastructure/Extensions/Seeders/UserSeederConfiguration.cs +++ b/backend/ECondo.Infrastructure/Extensions/Seeders/UserSeederConfiguration.cs @@ -49,7 +49,6 @@ public static async Task SeedUsers(this IApplicationBuilder if (!userRoleRes.Succeeded) { logger.LogIdentityErrors(userRoleRes.Errors); - continue; } } diff --git a/backend/ECondo.Infrastructure/Extensions/ServiceConfiguration.cs b/backend/ECondo.Infrastructure/Extensions/ServiceConfiguration.cs index e745f4b..d128c11 100644 --- a/backend/ECondo.Infrastructure/Extensions/ServiceConfiguration.cs +++ b/backend/ECondo.Infrastructure/Extensions/ServiceConfiguration.cs @@ -32,6 +32,7 @@ public static IServiceCollection AddInfrastructure(this IServiceCollection servi services.AddSingleton(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); diff --git a/backend/ECondo.Infrastructure/Extensions/SettingsConfiguration.cs b/backend/ECondo.Infrastructure/Extensions/SettingsConfiguration.cs index f722fc9..e19fd4b 100644 --- a/backend/ECondo.Infrastructure/Extensions/SettingsConfiguration.cs +++ b/backend/ECondo.Infrastructure/Extensions/SettingsConfiguration.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using ECondo.Domain.Shared; +using ECondo.Domain.Shared; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; diff --git a/backend/ECondo.Infrastructure/Services/AuthorizationService.cs b/backend/ECondo.Infrastructure/Services/AuthorizationService.cs new file mode 100644 index 0000000..fe38d36 --- /dev/null +++ b/backend/ECondo.Infrastructure/Services/AuthorizationService.cs @@ -0,0 +1,59 @@ +using ECondo.Application.Authorization; +using ECondo.Application.Services; +using ECondo.Domain.Authorization; +using Microsoft.Extensions.DependencyInjection; + +namespace ECondo.Infrastructure.Services; + +public sealed class AuthorizationService + (IServiceProvider serviceProvider) + : IAuthorizationService +{ + public async Task CanPerformActionAsync(Guid userId, + Guid? resourceId, + AccessLevel resourceAccess, + CancellationToken cancellationToken = default) + where T : class + { + var accessLevel = await GetAccessLevelAsync(userId, + resourceId, cancellationToken); + + return (resourceAccess & accessLevel) != 0; + } + + public Task GetAccessLevelAsync(Guid userId, + Guid? resourceId, + CancellationToken cancellationToken = default) + where T : class + { + try + { + var handler = GetHandler(); + return handler.GetAccessLevelAsync(userId, resourceId, cancellationToken); + } + catch (InvalidOperationException) + { + return Task.FromResult(AccessLevel.None); + } + } + + public Task> ApplyDataFilterAsync( + IQueryable query, + Guid userId, + CancellationToken cancellationToken = default) + where T : class + { + var handler = GetHandler(); + return handler.ApplyDataFilterAsync(query, userId, cancellationToken); + } + + private IResourceAuthorizationHandler GetHandler() where T : class + { + var handler = serviceProvider.GetService>(); + + if (handler is null) + return serviceProvider.GetRequiredService>(); + + return handler; + } +} \ No newline at end of file diff --git a/backend/ECondo.Domain/Shared/PagedList.cs b/backend/ECondo.SharedKernel/Collections/PagedList.cs similarity index 91% rename from backend/ECondo.Domain/Shared/PagedList.cs rename to backend/ECondo.SharedKernel/Collections/PagedList.cs index 94b7539..541144c 100644 --- a/backend/ECondo.Domain/Shared/PagedList.cs +++ b/backend/ECondo.SharedKernel/Collections/PagedList.cs @@ -1,4 +1,4 @@ -namespace ECondo.Domain.Shared; +namespace ECondo.SharedKernel.Collections; public class PagedList(IEnumerable items, int totalItemCount, int pageNumber, int pageSize) : List(items) diff --git a/backend/ECondo.SharedKernel/ECondo.SharedKernel.csproj b/backend/ECondo.SharedKernel/ECondo.SharedKernel.csproj new file mode 100644 index 0000000..3a63532 --- /dev/null +++ b/backend/ECondo.SharedKernel/ECondo.SharedKernel.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/backend/ECondo.SharedKernel/Extensions/TypeExtensions.cs b/backend/ECondo.SharedKernel/Extensions/TypeExtensions.cs new file mode 100644 index 0000000..4dd8fc4 --- /dev/null +++ b/backend/ECondo.SharedKernel/Extensions/TypeExtensions.cs @@ -0,0 +1,10 @@ +using ECondo.SharedKernel.Result; + +namespace ECondo.SharedKernel.Extensions; + +public static class TypeExtensions +{ + public static bool IsResultType(this Type type) + => type.IsGenericType && + type.GetGenericTypeDefinition() == typeof(Result<,>); +} \ No newline at end of file diff --git a/backend/ECondo.Domain/Shared/Error.cs b/backend/ECondo.SharedKernel/Result/Error.cs similarity index 94% rename from backend/ECondo.Domain/Shared/Error.cs rename to backend/ECondo.SharedKernel/Result/Error.cs index 8649fb0..a123006 100644 --- a/backend/ECondo.Domain/Shared/Error.cs +++ b/backend/ECondo.SharedKernel/Result/Error.cs @@ -1,4 +1,4 @@ -namespace ECondo.Domain.Shared; +namespace ECondo.SharedKernel.Result; public record Error(string Code, string Description, ErrorType Type) { public static Error Failure(string code, string description) => diff --git a/backend/ECondo.Domain/Shared/ErrorType.cs b/backend/ECondo.SharedKernel/Result/ErrorType.cs similarity index 76% rename from backend/ECondo.Domain/Shared/ErrorType.cs rename to backend/ECondo.SharedKernel/Result/ErrorType.cs index 9052321..02996c2 100644 --- a/backend/ECondo.Domain/Shared/ErrorType.cs +++ b/backend/ECondo.SharedKernel/Result/ErrorType.cs @@ -1,4 +1,4 @@ -namespace ECondo.Domain.Shared; +namespace ECondo.SharedKernel.Result; public enum ErrorType { diff --git a/backend/ECondo.Domain/Shared/Result.cs b/backend/ECondo.SharedKernel/Result/Result.cs similarity index 63% rename from backend/ECondo.Domain/Shared/Result.cs rename to backend/ECondo.SharedKernel/Result/Result.cs index 983acbf..bcb473b 100644 --- a/backend/ECondo.Domain/Shared/Result.cs +++ b/backend/ECondo.SharedKernel/Result/Result.cs @@ -1,4 +1,4 @@ -namespace ECondo.Domain.Shared; +namespace ECondo.SharedKernel.Result; public abstract record Result { @@ -26,4 +26,21 @@ public static Result.Success ToSuccess(this public static Result.Error ToError(this Result result) => (Result.Error)result; + + public static T InvokeResultFail(object?[]? parameters) + { + Type resultType = typeof(T).GetGenericArguments()[0]; + var failMethodInfo = typeof(Result<,>) + .MakeGenericType(resultType, typeof(Error)) + .GetMethod(nameof(Result.Fail)); + + object? res = failMethodInfo?.Invoke( + null, + parameters); + + if (res is not null) + return (T)res; + + return default!; + } } diff --git a/backend/ECondo.Domain/Shared/ValidationError.cs b/backend/ECondo.SharedKernel/Result/ValidationError.cs similarity index 83% rename from backend/ECondo.Domain/Shared/ValidationError.cs rename to backend/ECondo.SharedKernel/Result/ValidationError.cs index a1f2c39..9c9a532 100644 --- a/backend/ECondo.Domain/Shared/ValidationError.cs +++ b/backend/ECondo.SharedKernel/Result/ValidationError.cs @@ -1,4 +1,4 @@ -namespace ECondo.Domain.Shared; +namespace ECondo.SharedKernel.Result; public sealed record ValidationError(Error[] Errors) : Error("Validation.General", diff --git a/backend/ECondo.sln b/backend/ECondo.sln index 3b6461d..c4f2969 100644 --- a/backend/ECondo.sln +++ b/backend/ECondo.sln @@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ECondo.Application.UnitTest EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ECondo.Application.IntegrationTests", "ECondo.Application.IntegrationTests\ECondo.Application.IntegrationTests.csproj", "{C70CFF9E-0433-4097-85D4-D0A5DA4384F7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ECondo.SharedKernel", "ECondo.SharedKernel\ECondo.SharedKernel.csproj", "{640CF724-5526-4183-9910-4979E796B698}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -55,6 +57,10 @@ Global {C70CFF9E-0433-4097-85D4-D0A5DA4384F7}.Debug|Any CPU.Build.0 = Debug|Any CPU {C70CFF9E-0433-4097-85D4-D0A5DA4384F7}.Release|Any CPU.ActiveCfg = Release|Any CPU {C70CFF9E-0433-4097-85D4-D0A5DA4384F7}.Release|Any CPU.Build.0 = Release|Any CPU + {640CF724-5526-4183-9910-4979E796B698}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {640CF724-5526-4183-9910-4979E796B698}.Debug|Any CPU.Build.0 = Debug|Any CPU + {640CF724-5526-4183-9910-4979E796B698}.Release|Any CPU.ActiveCfg = Release|Any CPU + {640CF724-5526-4183-9910-4979E796B698}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -66,6 +72,7 @@ Global {E567D4A2-F808-4E66-814F-CEEE5DC0087E} = {51FAD893-9652-4751-AE25-2682DD7B83DB} {92EC01BF-60E9-4951-84DC-9D4E89D52410} = {5844E686-BEBE-40AB-A57B-E4CA5874A882} {C70CFF9E-0433-4097-85D4-D0A5DA4384F7} = {5844E686-BEBE-40AB-A57B-E4CA5874A882} + {640CF724-5526-4183-9910-4979E796B698} = {51FAD893-9652-4751-AE25-2682DD7B83DB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {29376348-8E26-4C7C-A441-8B922F1FAC87} diff --git a/frontend/econdo.client/next.config.ts b/frontend/econdo.client/next.config.ts index d698841..eb45ac4 100644 --- a/frontend/econdo.client/next.config.ts +++ b/frontend/econdo.client/next.config.ts @@ -4,7 +4,6 @@ const nextConfig: NextConfig = { reactStrictMode: false, experimental: { optimizePackageImports: ['@mantine/core', '@mantine/hooks'], - ppr: 'incremental', }, }; diff --git a/frontend/econdo.client/package-lock.json b/frontend/econdo.client/package-lock.json index fe2afa9..9f93f02 100644 --- a/frontend/econdo.client/package-lock.json +++ b/frontend/econdo.client/package-lock.json @@ -28,6 +28,7 @@ "react-dom": "19.1.0", "react-error-boundary": "^5.0.0", "react-hook-form": "^7.54.2", + "server-only": "^0.0.1", "zod": "^3.24.2" }, "devDependencies": { @@ -50,6 +51,7 @@ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -58,30 +60,53 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz", + "integrity": "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, + "node_modules/@emnapi/core": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", + "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.4", + "tslib": "^2.4.0" + } + }, "node_modules/@emnapi/runtime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.1.tgz", - "integrity": "sha512-LMshMVP0ZhACNjQNYXiU1iZJ6QCcv0lUdPDPugqGvCGXt5xtRVBPdtA0qU12pEXZzpWAhWlZYptfdAFq10DOVQ==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", + "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz", + "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==", + "dev": true, + "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.4.3" }, @@ -95,34 +120,24 @@ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/@eslint-community/regexpp": { "version": "4.12.1", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/config-array": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", - "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.5", + "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -130,11 +145,22 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/core": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", - "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" }, @@ -143,10 +169,11 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", - "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -166,30 +193,36 @@ } }, "node_modules/@eslint/js": { - "version": "9.19.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", - "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.33.0.tgz", + "integrity": "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", - "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", - "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.10.0", + "@eslint/core": "^0.15.2", "levn": "^0.4.1" }, "engines": { @@ -197,26 +230,29 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.6.9", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", - "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.9" + "@floating-ui/utils": "^0.2.10" } }, "node_modules/@floating-ui/dom": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", - "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.3.tgz", + "integrity": "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==", + "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.9" + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" } }, "node_modules/@floating-ui/react": { "version": "0.26.28", "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz", "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", + "license": "MIT", "dependencies": { "@floating-ui/react-dom": "^2.1.2", "@floating-ui/utils": "^0.2.8", @@ -228,11 +264,12 @@ } }, "node_modules/@floating-ui/react-dom": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", - "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.5.tgz", + "integrity": "sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==", + "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.0.0" + "@floating-ui/dom": "^1.7.3" }, "peerDependencies": { "react": ">=16.8.0", @@ -240,14 +277,19 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", - "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==" + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" }, "node_modules/@hookform/resolvers": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-4.0.0.tgz", - "integrity": "sha512-93ZueVlTaeMF0pRbrLbcnzrxeb2mGA/xyO3RgfrsKs5OCtcfjoWcdjBJm+N7096Jfg/JYlGPjuyQCgqVEodSTg==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-4.1.3.tgz", + "integrity": "sha512-Jsv6UOWYTrEFJ/01ZrnwVXs7KDvP8XIo115i++5PWvNkNvkrsTfGiLS6w+eJ57CYtUtDQalUWovCZDHFJ8u1VQ==", + "license": "MIT", + "dependencies": { + "@standard-schema/utils": "^0.3.0" + }, "peerDependencies": { "react-hook-form": "^7.0.0" } @@ -257,6 +299,7 @@ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18.0" } @@ -266,6 +309,7 @@ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" @@ -279,6 +323,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -292,6 +337,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -301,10 +347,11 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", - "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -314,12 +361,13 @@ } }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.1.tgz", - "integrity": "sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==", + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz", + "integrity": "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==", "cpu": [ "arm64" ], + "license": "Apache-2.0", "optional": true, "os": [ "darwin" @@ -331,16 +379,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.1.0" + "@img/sharp-libvips-darwin-arm64": "1.2.0" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.1.tgz", - "integrity": "sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==", + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz", + "integrity": "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==", "cpu": [ "x64" ], + "license": "Apache-2.0", "optional": true, "os": [ "darwin" @@ -352,16 +401,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.1.0" + "@img/sharp-libvips-darwin-x64": "1.2.0" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz", - "integrity": "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz", + "integrity": "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==", "cpu": [ "arm64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" @@ -371,12 +421,13 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz", - "integrity": "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz", + "integrity": "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==", "cpu": [ "x64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" @@ -386,12 +437,13 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz", - "integrity": "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.0.tgz", + "integrity": "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==", "cpu": [ "arm" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -401,12 +453,13 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz", - "integrity": "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz", + "integrity": "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==", "cpu": [ "arm64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -416,12 +469,13 @@ } }, "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz", - "integrity": "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.0.tgz", + "integrity": "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==", "cpu": [ "ppc64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -431,12 +485,13 @@ } }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz", - "integrity": "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.0.tgz", + "integrity": "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==", "cpu": [ "s390x" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -446,12 +501,13 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz", - "integrity": "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz", + "integrity": "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==", "cpu": [ "x64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -461,12 +517,13 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz", - "integrity": "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz", + "integrity": "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==", "cpu": [ "arm64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -476,12 +533,13 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz", - "integrity": "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz", + "integrity": "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==", "cpu": [ "x64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -491,12 +549,13 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.1.tgz", - "integrity": "sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==", + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.3.tgz", + "integrity": "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==", "cpu": [ "arm" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -508,16 +567,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.1.0" + "@img/sharp-libvips-linux-arm": "1.2.0" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.1.tgz", - "integrity": "sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==", + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.3.tgz", + "integrity": "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==", "cpu": [ "arm64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -529,16 +589,39 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.1.0" + "@img/sharp-libvips-linux-arm64": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.3.tgz", + "integrity": "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.0" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.1.tgz", - "integrity": "sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==", + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.3.tgz", + "integrity": "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==", "cpu": [ "s390x" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -550,16 +633,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.1.0" + "@img/sharp-libvips-linux-s390x": "1.2.0" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.1.tgz", - "integrity": "sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==", + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.3.tgz", + "integrity": "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==", "cpu": [ "x64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -571,16 +655,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.1.0" + "@img/sharp-libvips-linux-x64": "1.2.0" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.1.tgz", - "integrity": "sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==", + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.3.tgz", + "integrity": "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==", "cpu": [ "arm64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -592,16 +677,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.1.0" + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.1.tgz", - "integrity": "sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==", + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.3.tgz", + "integrity": "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==", "cpu": [ "x64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -613,20 +699,40 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.1.0" + "@img/sharp-libvips-linuxmusl-x64": "1.2.0" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.1.tgz", - "integrity": "sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==", + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.3.tgz", + "integrity": "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==", "cpu": [ "wasm32" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.4.0" + "@emnapi/runtime": "^1.4.4" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz", + "integrity": "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -635,12 +741,13 @@ } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.1.tgz", - "integrity": "sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==", + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.3.tgz", + "integrity": "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==", "cpu": [ "ia32" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" @@ -653,12 +760,13 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.1.tgz", - "integrity": "sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==", + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz", + "integrity": "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==", "cpu": [ "x64" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" @@ -675,6 +783,7 @@ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -688,17 +797,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -706,39 +812,34 @@ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@mantine/core": { - "version": "7.17.5", - "resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.17.5.tgz", - "integrity": "sha512-66g/lr281cDPfucjtPw8gFo/yNS9G5iSKqysvPGuDpUBG2bEw8FsJMIsU0bMXtravToIpa3vJRrFUuPndPGnpQ==", + "version": "7.17.8", + "resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.17.8.tgz", + "integrity": "sha512-42sfdLZSCpsCYmLCjSuntuPcDg3PLbakSmmYfz5Auea8gZYLr+8SS5k647doVu0BRAecqYOytkX2QC5/u/8VHw==", + "license": "MIT", "dependencies": { "@floating-ui/react": "^0.26.28", "clsx": "^2.1.1", @@ -748,41 +849,44 @@ "type-fest": "^4.27.0" }, "peerDependencies": { - "@mantine/hooks": "7.17.5", + "@mantine/hooks": "7.17.8", "react": "^18.x || ^19.x", "react-dom": "^18.x || ^19.x" } }, "node_modules/@mantine/dates": { - "version": "7.17.5", - "resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-7.17.5.tgz", - "integrity": "sha512-8/Qjjb9159rQhxtuHLukNfo3/AEGl7SVSRESN8MkfyP8MCQ7mgm9wqvMADb/9Q75boUA0HIN2pewlzlcd31MHQ==", + "version": "7.17.8", + "resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-7.17.8.tgz", + "integrity": "sha512-KYog/YL83PnsMef7EZagpOFq9I2gfnK0eYSzC8YvV9Mb6t/x9InqRssGWVb0GIr+TNILpEkhKoGaSKZNy10Q1g==", + "license": "MIT", "dependencies": { "clsx": "^2.1.1" }, "peerDependencies": { - "@mantine/core": "7.17.5", - "@mantine/hooks": "7.17.5", + "@mantine/core": "7.17.8", + "@mantine/hooks": "7.17.8", "dayjs": ">=1.0.0", "react": "^18.x || ^19.x", "react-dom": "^18.x || ^19.x" } }, "node_modules/@mantine/hooks": { - "version": "7.17.5", - "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.17.5.tgz", - "integrity": "sha512-Q/3AHI1fjl+W7xQ3jEoMmSoTxLqxMI2gPfxIjd73OPmRpPenYWR1zk/diirXXm2t7JOrAbmpA3/O1gzmgqzc/Q==", + "version": "7.17.8", + "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.17.8.tgz", + "integrity": "sha512-96qygbkTjRhdkzd5HDU8fMziemN/h758/EwrFu7TlWrEP10Vw076u+Ap/sG6OT4RGPZYYoHrTlT+mkCZblWHuw==", + "license": "MIT", "peerDependencies": { "react": "^18.x || ^19.x" } }, "node_modules/@mantine/modals": { - "version": "7.17.5", - "resolved": "https://registry.npmjs.org/@mantine/modals/-/modals-7.17.5.tgz", - "integrity": "sha512-K2rKBkQmndZzL+uPBpQ54qcGwAL1f78ipucQt0Dhf5i252NTBaQVWrRRbPSL0KQQqtK+9TSaV5C8rQ4O9EKUjw==", + "version": "7.17.8", + "resolved": "https://registry.npmjs.org/@mantine/modals/-/modals-7.17.8.tgz", + "integrity": "sha512-7Eylnopjh8b0xIrtXnle8DsNsLghq82uUYMalm54nMaCSD9N/qAuCPGfAE0k2tsWj5cGDC2/uMbU0RSBjGanbA==", + "license": "MIT", "peerDependencies": { - "@mantine/core": "7.17.5", - "@mantine/hooks": "7.17.5", + "@mantine/core": "7.17.8", + "@mantine/hooks": "7.17.8", "react": "^18.x || ^19.x", "react-dom": "^18.x || ^19.x" } @@ -791,6 +895,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@mantinex/mantine-logo/-/mantine-logo-1.1.0.tgz", "integrity": "sha512-POR8TKKl7p1uq4nl/DxH3wBW7ShTVEEkzZ9RUkTbwjfuHR/skjaK2to8aETkxmpl/u2vQyxb325WwDKe5Xby5A==", + "license": "MIT", "peerDependencies": { "@mantine/core": ">=7.0.0", "@mantine/hooks": ">=7.0.0", @@ -798,10 +903,23 @@ "react-dom": "^18.x || ^19.x" } }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, "node_modules/@next/env": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.3.tgz", - "integrity": "sha512-OdiMrzCl2Xi0VTjiQQUK0Xh7bJHnOuET2s+3V+Y40WJBAXrJeGA3f+I8MZJ/YQ3mVGi5XGR1L66oFlgqXhQ4Vw==", + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.2.tgz", + "integrity": "sha512-Qe06ew4zt12LeO6N7j8/nULSOe3fMXE4dM6xgpBQNvdzyK1sv5y4oAP3bq4LamrvGCZtmRYnW8URFCeX5nFgGg==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -809,14 +927,45 @@ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.3.1.tgz", "integrity": "sha512-oEs4dsfM6iyER3jTzMm4kDSbrQJq8wZw5fmT6fg2V3SMo+kgG+cShzLfEV20senZzv8VF+puNLheiGPlBGsv2A==", "dev": true, + "license": "MIT", "dependencies": { "fast-glob": "3.3.1" } }, + "node_modules/@next/eslint-plugin-next/node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.3.tgz", - "integrity": "sha512-WRJERLuH+O3oYB4yZNVahSVFmtxRNjNF1I1c34tYMoJb0Pve+7/RaLAJJizyYiFhjYNGHRAE1Ri2Fd23zgDqhg==", + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.2.tgz", + "integrity": "sha512-8bGt577BXGSd4iqFygmzIfTYizHb0LGWqH+qgIF/2EDxS5JsSdERJKA8WgwDyNBZgTIIA4D8qUtoQHmxIIquoQ==", "cpu": [ "arm64" ], @@ -830,9 +979,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.3.tgz", - "integrity": "sha512-XHdzH/yBc55lu78k/XwtuFR/ZXUTcflpRXcsu0nKmF45U96jt1tsOZhVrn5YH+paw66zOANpOnFQ9i6/j+UYvw==", + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.2.tgz", + "integrity": "sha512-2DjnmR6JHK4X+dgTXt5/sOCu/7yPtqpYt8s8hLkHFK3MGkka2snTv3yRMdHvuRtJVkPwCGsvBSwmoQCHatauFQ==", "cpu": [ "x64" ], @@ -846,9 +995,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.3.tgz", - "integrity": "sha512-VZ3sYL2LXB8znNGcjhocikEkag/8xiLgnvQts41tq6i+wql63SMS1Q6N8RVXHw5pEUjiof+II3HkDd7GFcgkzw==", + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.2.tgz", + "integrity": "sha512-3j7SWDBS2Wov/L9q0mFJtEvQ5miIqfO4l7d2m9Mo06ddsgUK8gWfHGgbjdFlCp2Ek7MmMQZSxpGFqcC8zGh2AA==", "cpu": [ "arm64" ], @@ -862,9 +1011,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.3.tgz", - "integrity": "sha512-h6Y1fLU4RWAp1HPNJWDYBQ+e3G7sLckyBXhmH9ajn8l/RSMnhbuPBV/fXmy3muMcVwoJdHL+UtzRzs0nXOf9SA==", + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.2.tgz", + "integrity": "sha512-s6N8k8dF9YGc5T01UPQ08yxsK6fUow5gG1/axWc1HVVBYQBgOjca4oUZF7s4p+kwhkB1bDSGR8QznWrFZ/Rt5g==", "cpu": [ "arm64" ], @@ -878,9 +1027,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.3.tgz", - "integrity": "sha512-jJ8HRiF3N8Zw6hGlytCj5BiHyG/K+fnTKVDEKvUCyiQ/0r5tgwO7OgaRiOjjRoIx2vwLR+Rz8hQoPrnmFbJdfw==", + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.2.tgz", + "integrity": "sha512-o1RV/KOODQh6dM6ZRJGZbc+MOAHww33Vbs5JC9Mp1gDk8cpEO+cYC/l7rweiEalkSm5/1WGa4zY7xrNwObN4+Q==", "cpu": [ "x64" ], @@ -894,9 +1043,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.3.tgz", - "integrity": "sha512-HrUcTr4N+RgiiGn3jjeT6Oo208UT/7BuTr7K0mdKRBtTbT4v9zJqCDKO97DUqqoBK1qyzP1RwvrWTvU6EPh/Cw==", + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.2.tgz", + "integrity": "sha512-/VUnh7w8RElYZ0IV83nUcP/J4KJ6LLYliiBIri3p3aW2giF+PAVgZb6mk8jbQSB3WlTai8gEmCAr7kptFa1H6g==", "cpu": [ "x64" ], @@ -910,9 +1059,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.3.tgz", - "integrity": "sha512-SxorONgi6K7ZUysMtRF3mIeHC5aA3IQLmKFQzU0OuhuUYwpOBc1ypaLJLP5Bf3M9k53KUUUj4vTPwzGvl/NwlQ==", + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.2.tgz", + "integrity": "sha512-sMPyTvRcNKXseNQ/7qRfVRLa0VhR0esmQ29DD6pqvG71+JdVnESJaHPA8t7bc67KD5spP3+DOCNLhqlEI2ZgQg==", "cpu": [ "arm64" ], @@ -926,9 +1075,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.3.tgz", - "integrity": "sha512-4QZG6F8enl9/S2+yIiOiju0iCTFd93d8VC1q9LZS4p/Xuk81W2QDjCFeoogmrWWkAD59z8ZxepBQap2dKS5ruw==", + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.2.tgz", + "integrity": "sha512-W5VvyZHnxG/2ukhZF/9Ikdra5fdNftxI6ybeVKYvBPDtyx7x4jPPSNduUkfH5fo3zG0JQ0bPxgy41af2JX5D4Q==", "cpu": [ "x64" ], @@ -946,6 +1095,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -959,6 +1109,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -968,6 +1119,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -981,6 +1133,7 @@ "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.4.0" } @@ -990,6 +1143,7 @@ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=14" @@ -999,18 +1153,27 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@rushstack/eslint-patch": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.5.tgz", - "integrity": "sha512-kkKUDVlII2DQiKy7UstOR1ErJP8kUKAQ4oa+SQtM0K+lPdmmjj0YnnxBgtTVYH7mUKtbsxeFC9y0AmK7Yb78/A==", - "dev": true + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.12.0.tgz", + "integrity": "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" }, "node_modules/@stripe/react-stripe-js": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-3.6.0.tgz", - "integrity": "sha512-zEnaUmTOsu7zhl3RWbZ0l1dRiad+QIbcAYzQfF+yYelURJowhAwesRHKWH+qGAIBEpkO6/VCLFHhVLH9DtPlnw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-3.9.0.tgz", + "integrity": "sha512-pN1Re7zUc3m61FFQROok685g3zsBQRzCmZDmTzO8iPU6zhLvu2JnC0LrG0FCzSp6kgGa8AQSzq4rpFSgyhkjKg==", + "license": "MIT", "dependencies": { "prop-types": "^15.7.2" }, @@ -1021,41 +1184,40 @@ } }, "node_modules/@stripe/stripe-js": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-7.2.0.tgz", - "integrity": "sha512-BXlt6BsFE599yOATuz78FiW9z4SyipCH3j1SDyKWe/3OUBdhcOr/BWnBi1xrtcC2kfqrTJjgvfH2PTfMPRmbTw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-7.8.0.tgz", + "integrity": "sha512-DNXRfYUgkZlrniQORbA/wH8CdFRhiBSE0R56gYU0V5vvpJ9WZwvGrz9tBAZmfq2aTgw6SK7mNpmTizGzLWVezw==", + "license": "MIT", "engines": { "node": ">=12.16" } }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" - }, "node_modules/@swc/helpers": { "version": "0.5.15", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.8.0" } }, "node_modules/@tabler/icons": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.30.0.tgz", - "integrity": "sha512-c8OKLM48l00u9TFbh2qhSODMONIzML8ajtCyq95rW8vzkWcBrKRPM61tdkThz2j4kd5u17srPGIjqdeRUZdfdw==", + "version": "3.34.1", + "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.34.1.tgz", + "integrity": "sha512-9gTnUvd7Fd/DmQgr3MKY+oJLa1RfNsQo8c/ir3TJAWghOuZXodbtbVp0QBY2DxWuuvrSZFys0HEbv1CoiI5y6A==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/codecalm" } }, "node_modules/@tabler/icons-react": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/@tabler/icons-react/-/icons-react-3.30.0.tgz", - "integrity": "sha512-9KZ9D1UNAyjlLkkYp2HBPHdf6lAJ2aelDqh8YYAnnmLF3xwprWKxxW8+zw5jlI0IwdfN4XFFuzqePkaw+DpIOg==", + "version": "3.34.1", + "resolved": "https://registry.npmjs.org/@tabler/icons-react/-/icons-react-3.34.1.tgz", + "integrity": "sha512-Ld6g0NqOO05kyyHsfU8h787PdHBm7cFmOycQSIrGp45XcXYDuOK2Bs0VC4T2FWSKZ6bx5g04imfzazf/nqtk1A==", + "license": "MIT", "dependencies": { - "@tabler/icons": "3.30.0" + "@tabler/icons": "3.34.1" }, "funding": { "type": "github", @@ -1066,12 +1228,13 @@ } }, "node_modules/@tanstack/eslint-plugin-query": { - "version": "5.73.3", - "resolved": "https://registry.npmjs.org/@tanstack/eslint-plugin-query/-/eslint-plugin-query-5.73.3.tgz", - "integrity": "sha512-GmUtnOkRzDuNOq96g3eW5ADKC1nWfrM9RI0kRyQVr87rOl6y+PUgkuVaPxh3R2C0EVODxCS07b9aaWphidl/OA==", + "version": "5.83.1", + "resolved": "https://registry.npmjs.org/@tanstack/eslint-plugin-query/-/eslint-plugin-query-5.83.1.tgz", + "integrity": "sha512-tdkpPFfzkTksN9BIlT/qjixSAtKrsW6PUVRwdKWaOcag7DrD1vpki3UzzdfMQGDRGeg1Ue1Dg+rcl5FJGembNg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.18.1" + "@typescript-eslint/utils": "^8.37.0" }, "funding": { "type": "github", @@ -1082,20 +1245,22 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.74.4", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.74.4.tgz", - "integrity": "sha512-YuG0A0+3i9b2Gfo9fkmNnkUWh5+5cFhWBN0pJAHkHilTx6A0nv8kepkk4T4GRt4e5ahbtFj2eTtkiPcVU1xO4A==", + "version": "5.83.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.83.1.tgz", + "integrity": "sha512-OG69LQgT7jSp+5pPuCfzltq/+7l2xoweggjme9vlbCPa/d7D7zaqv5vN/S82SzSYZ4EDLTxNO1PWrv49RAS64Q==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@tanstack/react-query": { - "version": "5.74.4", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.74.4.tgz", - "integrity": "sha512-mAbxw60d4ffQ4qmRYfkO1xzRBPUEf/72Dgo3qqea0J66nIKuDTLEqQt0ku++SDFlMGMnB6uKDnEG1xD/TDse4Q==", + "version": "5.85.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.85.0.tgz", + "integrity": "sha512-t1HMfToVMGfwEJRya6GG7gbK0luZJd+9IySFNePL1BforU1F3LqQ3tBC2Rpvr88bOrlU6PXyMLgJD0Yzn4ztUw==", + "license": "MIT", "dependencies": { - "@tanstack/query-core": "5.74.4" + "@tanstack/query-core": "5.83.1" }, "funding": { "type": "github", @@ -1105,31 +1270,46 @@ "react": "^18 || ^19" } }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", + "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { - "version": "20.17.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.16.tgz", - "integrity": "sha512-vOTpLduLkZXePLxHiHsBLp98mHGnl8RptV4YAO3HfKO5UHjDvySGbxKtpYfy8Sx5+WKcgc45qNreJJRVM3L6mw==", + "version": "20.19.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.10.tgz", + "integrity": "sha512-iAFpG6DokED3roLSP0K+ybeDdIX6Bc0Vd3mLW5uDqThPWtNos3E+EqOM11mPQHKzfWHqEBuLjIlsBQQ8CsISmQ==", "dev": true, + "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.21.0" } }, "node_modules/@types/react": { @@ -1137,6 +1317,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.2.tgz", "integrity": "sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==", "devOptional": true, + "license": "MIT", "dependencies": { "csstype": "^3.0.2" } @@ -1146,25 +1327,27 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.2.tgz", "integrity": "sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==", "dev": true, + "license": "MIT", "peerDependencies": { "@types/react": "^19.0.0" } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.22.0.tgz", - "integrity": "sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.1.tgz", + "integrity": "sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.22.0", - "@typescript-eslint/type-utils": "8.22.0", - "@typescript-eslint/utils": "8.22.0", - "@typescript-eslint/visitor-keys": "8.22.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/type-utils": "8.39.1", + "@typescript-eslint/utils": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1174,21 +1357,32 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "@typescript-eslint/parser": "^8.39.1", "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.22.0.tgz", - "integrity": "sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.39.1.tgz", + "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.22.0", - "@typescript-eslint/types": "8.22.0", - "@typescript-eslint/typescript-estree": "8.22.0", - "@typescript-eslint/visitor-keys": "8.22.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", "debug": "^4.3.4" }, "engines": { @@ -1200,17 +1394,40 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", + "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.39.1", + "@typescript-eslint/types": "^8.39.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.22.0.tgz", - "integrity": "sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", + "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.22.0", - "@typescript-eslint/visitor-keys": "8.22.0" + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1220,16 +1437,35 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", + "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.22.0.tgz", - "integrity": "sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.39.1.tgz", + "integrity": "sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.22.0", - "@typescript-eslint/utils": "8.22.0", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/utils": "8.39.1", "debug": "^4.3.4", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1240,14 +1476,15 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.22.0.tgz", - "integrity": "sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", + "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -1257,19 +1494,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.22.0.tgz", - "integrity": "sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", + "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.22.0", - "@typescript-eslint/visitor-keys": "8.22.0", + "@typescript-eslint/project-service": "8.39.1", + "@typescript-eslint/tsconfig-utils": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1279,106 +1519,365 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8.6.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@typescript-eslint/utils": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", + "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1" }, "engines": { - "node": ">= 6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", + "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "@typescript-eslint/types": "8.39.1", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/utils": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.22.0.tgz", - "integrity": "sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==", + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "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==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.22.0", - "@typescript-eslint/types": "8.22.0", - "@typescript-eslint/typescript-estree": "8.22.0" + "@napi-rs/wasm-runtime": "^0.2.11" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "node": ">=14.0.0" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.22.0.tgz", - "integrity": "sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==", + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@typescript-eslint/types": "8.22.0", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1391,6 +1890,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -1400,6 +1900,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1416,6 +1917,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -1428,6 +1930,7 @@ "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" }, @@ -1442,13 +1945,15 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1461,19 +1966,22 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/argparse": { "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 + "dev": true, + "license": "Python-2.0" }, "node_modules/aria-query": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">= 0.4" } @@ -1483,6 +1991,7 @@ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" @@ -1495,17 +2004,20 @@ } }, "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -1519,6 +2031,7 @@ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -1535,17 +2048,19 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -1559,6 +2074,7 @@ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", @@ -1577,6 +2093,7 @@ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", @@ -1595,6 +2112,7 @@ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -1611,6 +2129,7 @@ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", @@ -1631,13 +2150,15 @@ "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -1645,13 +2166,15 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -1663,21 +2186,23 @@ } }, "node_modules/axe-core": { - "version": "4.10.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", - "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==", + "version": "4.10.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz", + "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==", "dev": true, + "license": "MPL-2.0", "engines": { "node": ">=4" } }, "node_modules/axios": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", - "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", + "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, @@ -1686,6 +2211,7 @@ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">= 0.4" } @@ -1694,13 +2220,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -1709,10 +2237,11 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1723,6 +2252,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -1730,22 +2260,12 @@ "node": ">=8" } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, + "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", @@ -1760,10 +2280,10 @@ } }, "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -1773,13 +2293,14 @@ } }, "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -1793,6 +2314,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1802,14 +2324,15 @@ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001695", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz", - "integrity": "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==", + "version": "1.0.30001734", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001734.tgz", + "integrity": "sha512-uhE1Ye5vgqju6OI71HTQqcBCZrvHugk0MjLak7Q+HfoBgoq5Bi+5YnwjP4fjDgrtYr/l8MVRBvzz9dPD4KyK0A==", "funding": [ { "type": "opencollective", @@ -1823,13 +2346,15 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1846,6 +2371,7 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -1870,6 +2396,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -1880,12 +2407,14 @@ "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -1894,6 +2423,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", "optional": true, "dependencies": { "color-convert": "^2.0.1", @@ -1908,6 +2438,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "devOptional": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -1919,12 +2450,14 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "devOptional": true + "devOptional": true, + "license": "MIT" }, "node_modules/color-string": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", "optional": true, "dependencies": { "color-name": "^1.0.0", @@ -1935,6 +2468,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -1947,6 +2481,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } @@ -1955,13 +2490,15 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1976,6 +2513,7 @@ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, + "license": "MIT", "bin": { "cssesc": "bin/cssesc" }, @@ -1987,19 +2525,22 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "devOptional": true + "devOptional": true, + "license": "MIT" }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -2017,6 +2558,7 @@ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -2034,6 +2576,7 @@ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -2049,13 +2592,15 @@ "node_modules/dayjs": { "version": "1.11.13", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -2072,13 +2617,15 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -2096,6 +2643,7 @@ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -2112,14 +2660,16 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", "optional": true, "engines": { "node": ">=8" @@ -2128,25 +2678,29 @@ "node_modules/detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", - "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -2158,7 +2712,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, + "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", @@ -2172,49 +2726,39 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/enhanced-resolve": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz", - "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==", "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } + "license": "MIT" }, "node_modules/es-abstract": { - "version": "1.23.9", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", - "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "dev": true, + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.0", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", @@ -2226,21 +2770,24 @@ "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", + "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.0", + "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.3", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.3", + "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", @@ -2249,7 +2796,7 @@ "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.18" + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -2262,7 +2809,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -2271,7 +2818,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -2281,6 +2828,7 @@ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -2307,7 +2855,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -2319,7 +2867,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", @@ -2331,12 +2879,16 @@ } }, "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, + "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-to-primitive": { @@ -2344,6 +2896,7 @@ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", @@ -2361,6 +2914,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2369,21 +2923,23 @@ } }, "node_modules/eslint": { - "version": "9.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", - "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.33.0.tgz", + "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.10.0", - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.19.0", - "@eslint/plugin-kit": "^0.2.5", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.33.0", + "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.1", + "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -2391,9 +2947,9 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.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", @@ -2432,6 +2988,7 @@ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.3.1.tgz", "integrity": "sha512-GnmyVd9TE/Ihe3RrvcafFhXErErtr2jS0JDeCSp3vWvy86AXwHsRBt0E3MqP/m8ACS1ivcsi5uaqjbhsG18qKw==", "dev": true, + "license": "MIT", "dependencies": { "@next/eslint-plugin-next": "15.3.1", "@rushstack/eslint-patch": "^1.10.3", @@ -2459,6 +3016,7 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -2470,30 +3028,31 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-import-resolver-typescript": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.7.0.tgz", - "integrity": "sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", "dev": true, + "license": "ISC", "dependencies": { "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.3.7", - "enhanced-resolve": "^5.15.0", - "fast-glob": "^3.3.2", - "get-tsconfig": "^4.7.5", - "is-bun-module": "^1.0.2", - "is-glob": "^4.0.3", - "stable-hash": "^0.0.4" + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + "url": "https://opencollective.com/eslint-import-resolver-typescript" }, "peerDependencies": { "eslint": "*", @@ -2509,39 +3068,12 @@ } } }, - "node_modules/eslint-import-resolver-typescript/node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -2559,34 +3091,36 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-plugin-import": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, + "license": "MIT", "dependencies": { "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", + "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", - "is-core-module": "^2.15.1", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", + "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "engines": { @@ -2601,6 +3135,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -2610,6 +3145,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -2619,6 +3155,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", "dev": true, + "license": "MIT", "dependencies": { "aria-query": "^5.3.2", "array-includes": "^3.1.8", @@ -2644,10 +3181,11 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", - "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", @@ -2659,7 +3197,7 @@ "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.8", + "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", @@ -2676,10 +3214,11 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0.tgz", - "integrity": "sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2692,6 +3231,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -2709,15 +3249,17 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -2730,10 +3272,24 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "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==", + "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -2742,14 +3298,15 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2758,11 +3315,25 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "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==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esquery": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -2775,6 +3346,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -2787,6 +3359,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -2796,6 +3369,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -2804,19 +3378,21 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -2827,6 +3403,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -2838,19 +3415,22 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastq": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", - "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -2860,6 +3440,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, @@ -2872,6 +3453,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2884,6 +3466,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -2900,6 +3483,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" @@ -2909,21 +3493,23 @@ } }, "node_modules/flatted": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", - "dev": true + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -2934,10 +3520,11 @@ } }, "node_modules/for-each": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.4.tgz", - "integrity": "sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.2.7" }, @@ -2949,12 +3536,13 @@ } }, "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, + "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -2965,12 +3553,15 @@ } }, "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -2978,12 +3569,13 @@ } }, "node_modules/framer-motion": { - "version": "12.9.2", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.9.2.tgz", - "integrity": "sha512-R0O3Jdqbfwywpm45obP+8sTgafmdEcUoShQTAV+rB5pi+Y1Px/FYL5qLLRe5tPtBdN1J4jos7M+xN2VV2oEAbQ==", + "version": "12.23.12", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.12.tgz", + "integrity": "sha512-6e78rdVtnBvlEVgu6eFEAgG9v3wLnYEboM8I5O5EXvfKC8gxGQB8wXJdhkMy10iVcn05jl6CNw7/HTsTCfwcWg==", + "license": "MIT", "dependencies": { - "motion-dom": "^12.9.1", - "motion-utils": "^12.8.3", + "motion-dom": "^12.23.12", + "motion-utils": "^12.23.6", "tslib": "^2.4.0" }, "peerDependencies": { @@ -3009,6 +3601,7 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -3021,7 +3614,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3031,6 +3624,7 @@ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -3051,22 +3645,23 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-intrinsic": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", - "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", - "dev": true, + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "get-proto": "^1.0.0", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", @@ -3083,6 +3678,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", "engines": { "node": ">=6" } @@ -3091,7 +3687,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, + "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" @@ -3105,6 +3701,7 @@ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -3118,10 +3715,11 @@ } }, "node_modules/get-tsconfig": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", - "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", "dev": true, + "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" }, @@ -3134,6 +3732,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -3154,6 +3753,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -3162,10 +3762,11 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -3175,6 +3776,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -3190,6 +3792,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -3202,6 +3805,7 @@ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" @@ -3217,7 +3821,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3225,23 +3829,19 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3254,6 +3854,7 @@ "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" } @@ -3263,6 +3864,7 @@ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, @@ -3275,6 +3877,7 @@ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, + "license": "MIT", "dependencies": { "dunder-proto": "^1.0.0" }, @@ -3289,7 +3892,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3301,7 +3904,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, + "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, @@ -3316,7 +3919,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -3329,15 +3932,17 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "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", "resolve-from": "^4.0.0" @@ -3354,6 +3959,7 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -3363,6 +3969,7 @@ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", @@ -3377,6 +3984,7 @@ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -3393,6 +4001,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT", "optional": true }, "node_modules/is-async-function": { @@ -3400,6 +4009,7 @@ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, + "license": "MIT", "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", @@ -3419,6 +4029,7 @@ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, + "license": "MIT", "dependencies": { "has-bigints": "^1.0.2" }, @@ -3434,6 +4045,7 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -3442,12 +4054,13 @@ } }, "node_modules/is-boolean-object": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", - "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", + "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" }, "engines": { @@ -3458,12 +4071,13 @@ } }, "node_modules/is-bun-module": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz", - "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", "dev": true, + "license": "MIT", "dependencies": { - "semver": "^7.6.3" + "semver": "^7.7.1" } }, "node_modules/is-callable": { @@ -3471,6 +4085,7 @@ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3483,6 +4098,7 @@ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, + "license": "MIT", "dependencies": { "hasown": "^2.0.2" }, @@ -3498,6 +4114,7 @@ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", @@ -3515,6 +4132,7 @@ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" @@ -3531,6 +4149,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3540,6 +4159,7 @@ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3" }, @@ -3555,6 +4175,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3564,6 +4185,7 @@ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "get-proto": "^1.0.0", @@ -3582,6 +4204,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -3594,6 +4217,20 @@ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3606,6 +4243,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -3615,6 +4253,7 @@ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" @@ -3631,6 +4270,7 @@ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", @@ -3649,6 +4289,7 @@ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3661,6 +4302,7 @@ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3" }, @@ -3676,6 +4318,7 @@ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" @@ -3692,6 +4335,7 @@ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", @@ -3709,6 +4353,7 @@ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, + "license": "MIT", "dependencies": { "which-typed-array": "^1.1.16" }, @@ -3724,6 +4369,7 @@ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3732,12 +4378,13 @@ } }, "node_modules/is-weakref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", - "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, + "license": "MIT", "dependencies": { - "call-bound": "^1.0.2" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -3751,6 +4398,7 @@ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" @@ -3766,19 +4414,22 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/iterator.prototype": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", @@ -3796,6 +4447,7 @@ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -3811,6 +4463,7 @@ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, + "license": "MIT", "bin": { "jiti": "bin/jiti.js" } @@ -3818,13 +4471,15 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -3836,25 +4491,29 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -3867,6 +4526,7 @@ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -3881,6 +4541,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", "engines": { "node": ">=18" } @@ -3890,6 +4551,7 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -3898,13 +4560,15 @@ "version": "0.3.23", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", - "dev": true + "dev": true, + "license": "CC0-1.0" }, "node_modules/language-tags": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", "dev": true, + "license": "MIT", "dependencies": { "language-subtag-registry": "^0.3.20" }, @@ -3917,6 +4581,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -3926,15 +4591,17 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.11.19", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.19.tgz", - "integrity": "sha512-bW/Yp/9dod6fmyR+XqSUL1N5JE7QRxQ3KrBIbYS1FTv32e5i3SEtQVX+71CYNv8maWNSOgnlCoNp9X78f/cKiA==" + "version": "1.12.10", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.10.tgz", + "integrity": "sha512-E91vHJD61jekHHR/RF/E83T/CMoaLXT7cwYA75T4gim4FZjnM6hbJjVIGg7chqlSqRsSvQ3izGmOjHy1SQzcGQ==", + "license": "MIT" }, "node_modules/lilconfig": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" }, @@ -3946,13 +4613,15 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -3967,12 +4636,14 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -3984,13 +4655,14 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -4000,6 +4672,7 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -4009,6 +4682,7 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -4021,6 +4695,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -4029,6 +4704,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -4041,6 +4717,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4053,6 +4730,7 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4062,34 +4740,39 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/motion-dom": { - "version": "12.9.1", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.9.1.tgz", - "integrity": "sha512-xqXEwRLDYDTzOgXobSoWtytRtGlf7zdkRfFbrrdP7eojaGQZ5Go4OOKtgnx7uF8sAkfr1ZjMvbCJSCIT2h6fkQ==", + "version": "12.23.12", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.12.tgz", + "integrity": "sha512-RcR4fvMCTESQBD/uKQe49D5RUeDOokkGRmz4ceaJKDBgHYtZtntC/s2vLvY38gqGaytinij/yi3hMcWVcEF5Kw==", + "license": "MIT", "dependencies": { - "motion-utils": "^12.8.3" + "motion-utils": "^12.23.6" } }, "node_modules/motion-utils": { - "version": "12.8.3", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.8.3.tgz", - "integrity": "sha512-GYVauZEbca8/zOhEiYOY9/uJeedYQld6co/GJFKOy//0c/4lDqk0zB549sBYqqV2iMuX+uHrY1E5zd8A2L+1Lw==" + "version": "12.23.6", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz", + "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==", + "license": "MIT" }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", "dev": true, + "license": "MIT", "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", @@ -4097,15 +4780,16 @@ } }, "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -4113,22 +4797,37 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-postinstall": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz", + "integrity": "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/next": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/next/-/next-15.3.3.tgz", - "integrity": "sha512-JqNj29hHNmCLtNvd090SyRbXJiivQ+58XjCcrC50Crb5g5u2zi7Y2YivbsEfzk6AtVI80akdOQbaMZwWB1Hthw==", + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.2.tgz", + "integrity": "sha512-H8Otr7abj1glFhbGnvUt3gz++0AF1+QoCXEBmd/6aKbfdFwrn0LpA836Ed5+00va/7HQSDD+mOoVhn3tNy3e/Q==", "license": "MIT", "dependencies": { - "@next/env": "15.3.3", - "@swc/counter": "0.1.3", + "@next/env": "15.5.2", "@swc/helpers": "0.5.15", - "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" @@ -4140,19 +4839,19 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.3.3", - "@next/swc-darwin-x64": "15.3.3", - "@next/swc-linux-arm64-gnu": "15.3.3", - "@next/swc-linux-arm64-musl": "15.3.3", - "@next/swc-linux-x64-gnu": "15.3.3", - "@next/swc-linux-x64-musl": "15.3.3", - "@next/swc-win32-arm64-msvc": "15.3.3", - "@next/swc-win32-x64-msvc": "15.3.3", - "sharp": "^0.34.1" + "@next/swc-darwin-arm64": "15.5.2", + "@next/swc-darwin-x64": "15.5.2", + "@next/swc-linux-arm64-gnu": "15.5.2", + "@next/swc-linux-arm64-musl": "15.5.2", + "@next/swc-linux-x64-gnu": "15.5.2", + "@next/swc-linux-x64-musl": "15.5.2", + "@next/swc-win32-arm64-msvc": "15.5.2", + "@next/swc-win32-x64-msvc": "15.5.2", + "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.41.2", + "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", @@ -4191,6 +4890,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", @@ -4205,6 +4905,7 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -4213,6 +4914,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -4222,15 +4924,17 @@ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -4243,6 +4947,7 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -4252,6 +4957,7 @@ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -4268,14 +4974,16 @@ } }, "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "es-object-atoms": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -4286,6 +4994,7 @@ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -4304,6 +5013,7 @@ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -4318,6 +5028,7 @@ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -4336,6 +5047,7 @@ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -4353,6 +5065,7 @@ "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", @@ -4370,6 +5083,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -4385,6 +5099,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -4399,13 +5114,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true + "dev": true, + "license": "BlueOak-1.0.0" }, "node_modules/parent-module": { "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" }, @@ -4418,6 +5135,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4427,6 +5145,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4435,13 +5154,15 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -4456,13 +5177,15 @@ "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -4475,32 +5198,35 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/postcss": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", - "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -4516,8 +5242,9 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -4530,6 +5257,7 @@ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -4547,6 +5275,7 @@ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", "dev": true, + "license": "MIT", "dependencies": { "camelcase-css": "^2.0.1" }, @@ -4561,10 +5290,10 @@ "postcss": "^8.4.21" } }, - "node_modules/postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "node_modules/postcss-mixins": { + "version": "12.1.2", + "resolved": "https://registry.npmjs.org/postcss-mixins/-/postcss-mixins-12.1.2.tgz", + "integrity": "sha512-90pSxmZVfbX9e5xCv7tI5RV1mnjdf16y89CJKbf/hD7GyOz1FCxcYMl8ZYA8Hc56dbApTKKmU9HfvgfWdCxlwg==", "dev": true, "funding": [ { @@ -4576,52 +5305,24 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-mixins": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/postcss-mixins/-/postcss-mixins-9.0.4.tgz", - "integrity": "sha512-XVq5jwQJDRu5M1XGkdpgASqLk37OqkH4JCFDXl/Dn7janOJjCTEKL+36cnRVy7bMtoBzALfO7bV7nTIsFnUWLA==", - "dev": true, - "dependencies": { - "fast-glob": "^3.2.11", - "postcss-js": "^4.0.0", - "postcss-simple-vars": "^7.0.0", - "sugarss": "^4.0.1" + "postcss-js": "^4.0.1", + "postcss-simple-vars": "^7.0.1", + "sugarss": "^5.0.0", + "tinyglobby": "^0.2.14" }, "engines": { - "node": ">=14.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "node": "^20.0 || ^22.0 || >=24.0" }, "peerDependencies": { "postcss": "^8.2.14" } }, "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-7.0.2.tgz", + "integrity": "sha512-5osppouFc0VR9/VYzYxO03VaDa3e8F23Kfd6/9qcZTUI8P58GIYlArOET2Wq0ywSl2o2PjELhYOFI4W7l5QHKw==", "dev": true, "funding": [ { @@ -4633,34 +5334,37 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.1.1" + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": ">=12.0" + "node": ">=18.0" }, "peerDependencies": { "postcss": "^8.2.14" } }, "node_modules/postcss-preset-mantine": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/postcss-preset-mantine/-/postcss-preset-mantine-1.17.0.tgz", - "integrity": "sha512-ji1PMDBUf2Vsx/HE5faMSs1+ff6qE6YRulTr4Ja+6HD3gop8rSMTCYdpN7KrdsEg079kfBKkO/PaKhG9uR0zwQ==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/postcss-preset-mantine/-/postcss-preset-mantine-1.18.0.tgz", + "integrity": "sha512-sP6/s1oC7cOtBdl4mw/IRKmKvYTuzpRrH/vT6v9enMU/EQEQ31eQnHcWtFghOXLH87AAthjL/Q75rLmin1oZoA==", "dev": true, + "license": "MIT", "dependencies": { - "postcss-mixins": "^9.0.4", - "postcss-nested": "^6.0.1" + "postcss-mixins": "^12.0.0", + "postcss-nested": "^7.0.2" }, "peerDependencies": { "postcss": ">=8.0.0" } }, "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "dev": true, + "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -4674,6 +5378,7 @@ "resolved": "https://registry.npmjs.org/postcss-simple-vars/-/postcss-simple-vars-7.0.1.tgz", "integrity": "sha512-5GLLXaS8qmzHMOjVxqkk1TZPf1jMqesiI7qLhnlyERalG0sMbHIbJqrcnrpmZdKCLglHnRHoEBB61RtGTsj++A==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.0" }, @@ -4689,13 +5394,15 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } @@ -4704,6 +5411,7 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -4713,13 +5421,15 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4742,12 +5452,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/react": { "version": "19.1.0", "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -4756,6 +5468,7 @@ "version": "19.1.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "license": "MIT", "dependencies": { "scheduler": "^0.26.0" }, @@ -4767,6 +5480,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-5.0.0.tgz", "integrity": "sha512-tnjAxG+IkpLephNcePNA7v6F/QpWLH8He65+DmedchDwg162JZqx4NmbXj0mlAYVVEd81OW7aFhmbsScYfiAFQ==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5" }, @@ -4775,9 +5489,10 @@ } }, "node_modules/react-hook-form": { - "version": "7.54.2", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.54.2.tgz", - "integrity": "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==", + "version": "7.62.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.62.0.tgz", + "integrity": "sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -4792,21 +5507,24 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" }, "node_modules/react-number-format": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.3.tgz", - "integrity": "sha512-VCY5hFg/soBighAoGcdE+GagkJq0230qN6jcS5sp8wQX1qy1fYN/RX7/BXkrs0oyzzwqR8/+eSUrqXbGeywdUQ==", + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.4.tgz", + "integrity": "sha512-wOmoNZoOpvMminhifQYiYSTCLUDOiUbBunrMrMjA+dV52sY+vck1S4UhR6PkgnoCquvvMSeJjErXZ4qSaWCliA==", + "license": "MIT", "peerDependencies": { "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/react-remove-scroll": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz", - "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", + "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", + "license": "MIT", "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", @@ -4831,6 +5549,7 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" @@ -4852,6 +5571,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" @@ -4873,6 +5593,7 @@ "version": "8.5.9", "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz", "integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.13", "use-composed-ref": "^1.3.0", @@ -4890,6 +5611,7 @@ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", "dev": true, + "license": "MIT", "dependencies": { "pify": "^2.3.0" } @@ -4899,6 +5621,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -4911,6 +5634,7 @@ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", @@ -4928,16 +5652,12 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", @@ -4958,6 +5678,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", @@ -4978,6 +5699,7 @@ "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" } @@ -4987,15 +5709,17 @@ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -5020,6 +5744,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -5029,6 +5754,7 @@ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", @@ -5048,6 +5774,7 @@ "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" @@ -5064,6 +5791,7 @@ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -5079,13 +5807,15 @@ "node_modules/scheduler": { "version": "0.26.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==" + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" }, "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "devOptional": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -5093,11 +5823,18 @@ "node": ">=10" } }, + "node_modules/server-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", + "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -5115,6 +5852,7 @@ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -5130,6 +5868,7 @@ "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", "dev": true, + "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", @@ -5140,15 +5879,16 @@ } }, "node_modules/sharp": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.1.tgz", - "integrity": "sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==", + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.3.tgz", + "integrity": "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==", "hasInstallScript": true, + "license": "Apache-2.0", "optional": true, "dependencies": { "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.7.1" + "detect-libc": "^2.0.4", + "semver": "^7.7.2" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -5157,26 +5897,28 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.1", - "@img/sharp-darwin-x64": "0.34.1", - "@img/sharp-libvips-darwin-arm64": "1.1.0", - "@img/sharp-libvips-darwin-x64": "1.1.0", - "@img/sharp-libvips-linux-arm": "1.1.0", - "@img/sharp-libvips-linux-arm64": "1.1.0", - "@img/sharp-libvips-linux-ppc64": "1.1.0", - "@img/sharp-libvips-linux-s390x": "1.1.0", - "@img/sharp-libvips-linux-x64": "1.1.0", - "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", - "@img/sharp-libvips-linuxmusl-x64": "1.1.0", - "@img/sharp-linux-arm": "0.34.1", - "@img/sharp-linux-arm64": "0.34.1", - "@img/sharp-linux-s390x": "0.34.1", - "@img/sharp-linux-x64": "0.34.1", - "@img/sharp-linuxmusl-arm64": "0.34.1", - "@img/sharp-linuxmusl-x64": "0.34.1", - "@img/sharp-wasm32": "0.34.1", - "@img/sharp-win32-ia32": "0.34.1", - "@img/sharp-win32-x64": "0.34.1" + "@img/sharp-darwin-arm64": "0.34.3", + "@img/sharp-darwin-x64": "0.34.3", + "@img/sharp-libvips-darwin-arm64": "1.2.0", + "@img/sharp-libvips-darwin-x64": "1.2.0", + "@img/sharp-libvips-linux-arm": "1.2.0", + "@img/sharp-libvips-linux-arm64": "1.2.0", + "@img/sharp-libvips-linux-ppc64": "1.2.0", + "@img/sharp-libvips-linux-s390x": "1.2.0", + "@img/sharp-libvips-linux-x64": "1.2.0", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0", + "@img/sharp-libvips-linuxmusl-x64": "1.2.0", + "@img/sharp-linux-arm": "0.34.3", + "@img/sharp-linux-arm64": "0.34.3", + "@img/sharp-linux-ppc64": "0.34.3", + "@img/sharp-linux-s390x": "0.34.3", + "@img/sharp-linux-x64": "0.34.3", + "@img/sharp-linuxmusl-arm64": "0.34.3", + "@img/sharp-linuxmusl-x64": "0.34.3", + "@img/sharp-wasm32": "0.34.3", + "@img/sharp-win32-arm64": "0.34.3", + "@img/sharp-win32-ia32": "0.34.3", + "@img/sharp-win32-x64": "0.34.3" } }, "node_modules/shebang-command": { @@ -5184,6 +5926,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -5196,6 +5939,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -5205,6 +5949,7 @@ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", @@ -5224,6 +5969,7 @@ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" @@ -5240,6 +5986,7 @@ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -5258,6 +6005,7 @@ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -5277,6 +6025,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -5288,6 +6037,7 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", "optional": true, "dependencies": { "is-arrayish": "^0.3.1" @@ -5297,22 +6047,30 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/stable-hash": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", - "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==", - "dev": true + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" }, - "node_modules/streamsearch": { + "node_modules/stop-iteration-iterator": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, "engines": { - "node": ">=10.0.0" + "node": ">= 0.4" } }, "node_modules/string-width": { @@ -5320,6 +6078,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -5338,6 +6097,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -5352,6 +6112,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -5360,13 +6121,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -5379,6 +6142,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -5393,6 +6157,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -5420,6 +6185,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", "dev": true, + "license": "MIT", "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -5430,6 +6196,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", @@ -5451,6 +6218,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", @@ -5469,6 +6237,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -5486,6 +6255,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -5502,6 +6272,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -5514,6 +6285,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -5523,6 +6295,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -5532,6 +6305,7 @@ "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" }, @@ -5543,6 +6317,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", "dependencies": { "client-only": "0.0.1" }, @@ -5566,6 +6341,7 @@ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", @@ -5584,16 +6360,23 @@ } }, "node_modules/sugarss": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-4.0.1.tgz", - "integrity": "sha512-WCjS5NfuVJjkQzK10s8WOBY+hhDxxNt/N6ZaGwxFZ+wN3/lKKFSaaKUNecULcTTvE4urLcKaZFQD8vO0mOZujw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-5.0.1.tgz", + "integrity": "sha512-ctS5RYCBVvPoZAnzIaX5QSShK8ZiZxD5HUqSxlusvEMC+QZQIPCPOIJg6aceFX+K2rf4+SH89eu++h1Zmsr2nw==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "node": ">=18.0" }, "peerDependencies": { "postcss": "^8.3.3" @@ -5604,6 +6387,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -5616,6 +6400,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -5626,13 +6411,15 @@ "node_modules/tabbable": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "license": "MIT" }, "node_modules/tailwindcss": { "version": "3.4.17", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", "dev": true, + "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -5665,41 +6452,80 @@ "node": ">=14.0.0" } }, - "node_modules/tailwindcss/node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "node_modules/tailwindcss/node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" }, "engines": { - "node": ">=8.6.0" + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/tailwindcss/node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/tailwindcss/node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "postcss-selector-parser": "^6.1.1" }, "engines": { - "node": ">= 6" + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" } }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "node_modules/tailwindcss/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, "engines": { - "node": ">=6" + "node": ">=4" } }, "node_modules/thenify": { @@ -5707,6 +6533,7 @@ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "dev": true, + "license": "MIT", "dependencies": { "any-promise": "^1.0.0" } @@ -5716,6 +6543,7 @@ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "dev": true, + "license": "MIT", "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -5723,11 +6551,57 @@ "node": ">=0.8" } }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -5736,10 +6610,11 @@ } }, "node_modules/ts-api-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", - "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18.12" }, @@ -5751,13 +6626,15 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -5768,13 +6645,15 @@ "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -5783,9 +6662,10 @@ } }, "node_modules/type-fest": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.33.0.tgz", - "integrity": "sha512-s6zVrxuyKbbAsSAD5ZPTB77q4YIdRctkTbJ2/Dqlinwz+8ooH2gd+YA7VA6Pa93KML9GockVvoxjZ2vHP+mu8g==", + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=16" }, @@ -5798,6 +6678,7 @@ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -5812,6 +6693,7 @@ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", @@ -5831,6 +6713,7 @@ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", @@ -5852,6 +6735,7 @@ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -5868,10 +6752,11 @@ } }, "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -5885,6 +6770,7 @@ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", @@ -5899,16 +6785,53 @@ } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -5917,6 +6840,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", "dependencies": { "tslib": "^2.0.0" }, @@ -5937,6 +6861,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz", "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==", + "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, @@ -5947,9 +6872,10 @@ } }, "node_modules/use-isomorphic-layout-effect": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz", - "integrity": "sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz", + "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==", + "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, @@ -5963,6 +6889,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz", "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==", + "license": "MIT", "dependencies": { "use-isomorphic-layout-effect": "^1.1.1" }, @@ -5979,6 +6906,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" @@ -6000,13 +6928,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -6022,6 +6952,7 @@ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, + "license": "MIT", "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", @@ -6041,6 +6972,7 @@ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, + "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", @@ -6068,6 +7000,7 @@ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, + "license": "MIT", "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", @@ -6082,15 +7015,17 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", - "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "for-each": "^0.3.3", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, @@ -6106,6 +7041,7 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6115,6 +7051,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -6133,6 +7070,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -6150,6 +7088,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -6158,13 +7097,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -6179,6 +7120,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -6191,6 +7133,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -6199,15 +7142,16 @@ } }, "node_modules/yaml": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", "dev": true, + "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" + "node": ">= 14.6" } }, "node_modules/yocto-queue": { @@ -6215,6 +7159,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6223,9 +7168,10 @@ } }, "node_modules/zod": { - "version": "3.24.2", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", - "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/frontend/econdo.client/package.json b/frontend/econdo.client/package.json index 598014e..76e54a7 100644 --- a/frontend/econdo.client/package.json +++ b/frontend/econdo.client/package.json @@ -29,6 +29,7 @@ "react-dom": "19.1.0", "react-error-boundary": "^5.0.0", "react-hook-form": "^7.54.2", + "server-only": "^0.0.1", "zod": "^3.24.2" }, "devDependencies": { diff --git a/frontend/econdo.client/src/actions/auth.ts b/frontend/econdo.client/src/actions/auth.ts index 2bf177f..c4f389e 100644 --- a/frontend/econdo.client/src/actions/auth.ts +++ b/frontend/econdo.client/src/actions/auth.ts @@ -1,214 +1,214 @@ -'use server'; - -import axios, { isAxiosError } from 'axios'; -import { ApiError } from '@/types/apiResponses'; -import { cookies } from 'next/headers'; -import { - accessTokenCookieKey, - refreshTokenCookieKey -} from '@/utils/constants'; -import normalInstance, { authInstance } from '@/lib/axiosInstance'; -import { RegisterData, LoginData, TokenResponse } from '@/types/auth'; -import { Result, resultFail, resultOk } from '@/types/result'; -import { cache } from 'react'; - -const backendApiUrl = process.env.NEXT_PRIVATE_BACKEND_URL; - -export async function login(loginData: LoginData): Promise { - - try { - const res = await normalInstance - .post('/api/account/login', loginData) - const cookieStore = await cookies(); - - cookieStore.set( - accessTokenCookieKey, - res.data.accessToken, - { - httpOnly: true, - sameSite: 'strict', - maxAge: res.data.expiresIn * 60 - }); - cookieStore.set( - refreshTokenCookieKey, - res.data.refreshToken, - { - httpOnly: true, - sameSite: 'strict' - }); - - return resultOk(); - } catch(error) { - if(isAxiosError(error) && error.response?.data) - return resultFail(error.response?.data); - } - - throw new Error('Unexpected code flow'); -} - -const baseUrl = process.env.NEXT_PRIVATE_BASE_URL; - -export async function register(registerData: RegisterData): Promise { - try { - await normalInstance.post('/api/account/register', { - email: registerData.email, - username: registerData.username, - password: registerData.password, - returnUri: `${baseUrl}/confirmAccount`, - }); - - return resultOk(); - } catch(error) { - if(isAxiosError(error)) - return resultFail(error.response?.data!); - } - - throw new Error('Unexpected code flow'); -} - -export async function generateAccessToken(): Promise> { - try { - const cookieStore = await cookies(); - - const res = await axios. - post(`${backendApiUrl}/api/account/refresh`, - { - refreshToken: cookieStore - .get(refreshTokenCookieKey)?.value, - }); - - return resultOk(res.data); - } catch(error) { - if(isAxiosError(error)) - return resultFail(error.response?.data!); - } - - throw new Error('Unexpected code flow'); -} - -export async function setAccessTokenCookie(accessToken: string, maxAge: number) { - const cookieStore = await cookies(); - cookieStore.set( - accessTokenCookieKey, - accessToken, - { - httpOnly: true, - sameSite: 'strict', - maxAge: maxAge * 60 - }); -} - -export async function confirmEmail(token: string, email: string): Promise { - try { - await normalInstance.post('/api/account/confirmEmail', { - token: token, - email: email, - }); - - return resultOk(); - } catch(error) { - if(isAxiosError(error)) - return resultFail(error.response?.data!); - } - - throw new Error('Unexpected code flow'); -} - -export async function logout() { - const cookieStore = await cookies(); - const refreshToken = cookieStore.get(refreshTokenCookieKey)?.value; - - await authInstance.post('/api/account/invalidateRefreshToken', { - refreshToken: refreshToken, - }); - - cookieStore.delete(refreshTokenCookieKey); - cookieStore.delete(accessTokenCookieKey); -} - -export async function forgotPassword(email: string): Promise { - try { - await normalInstance.post('/api/account/forgotPassword', { - username: email, - returnUri: `${baseUrl}/resetPassword`, - }); - - return resultOk(); - } catch(error) { - if(isAxiosError(error)) - return resultFail(error.response?.data!); - } - - throw new Error('Unexpected code flow'); -} - -export async function resetPassword(email: string, token: string, password: string): Promise { - try { - await normalInstance.post('/api/account/resetPassword', { - email: email, - token: token, - newPassword: password, - }); - - return resultOk(); - } - catch(error) { - if(isAxiosError(error)) - return resultFail(error.response?.data!); - } - - throw new Error('Unexpected code flow'); -} - -export async function updatePassword(currentPassword: string, newPassword: string): Promise { - - try { - await authInstance.put('/api/account/updatePassword', { - currentPassword: currentPassword, - newPassword: newPassword - }); - - return resultOk(); - } catch(error) { - if(isAxiosError(error)) - return resultFail(error.response?.data!); - } - - throw new Error('Unexpected code flow'); -} - -export const isUserInRole = -cache(async (roleName: string): Promise => { - try { - await authInstance.get('/api/account/isInRole', { - params: { - roleName - }, - }); - - return resultOk(); - } catch(error) { - if(isAxiosError(error)) - return resultFail(error.response?.data!); - } - - throw new Error('Unexpected code flow'); -}); - -export const deleteUser = -cache(async (email: string): Promise => { - try { - await authInstance.delete('/api/account/delete', { - params: { - email, - }, - }); - - return resultOk(); - } catch(error) { - if(isAxiosError(error)) - return resultFail(error.response?.data!); - } - - throw new Error('Unexpected code flow'); -}); +'use server'; + +import axios, { isAxiosError } from 'axios'; +import { ApiError } from '@/types/apiResponses'; +import { cookies } from 'next/headers'; +import { + accessTokenCookieKey, + refreshTokenCookieKey +} from '@/utils/constants'; +import normalInstance, { authInstance } from '@/lib/axiosInstance'; +import { RegisterData, LoginData, TokenResult } from '@/types/auth'; +import { Result, resultFail, resultOk } from '@/types/result'; +import { cache } from 'react'; + +const backendApiUrl = process.env.NEXT_PRIVATE_BACKEND_URL; + +export async function login(loginData: LoginData): Promise { + + try { + const res = await normalInstance + .post('/api/account/login', loginData) + const cookieStore = await cookies(); + + cookieStore.set( + accessTokenCookieKey, + res.data.accessToken, + { + httpOnly: true, + sameSite: 'strict', + maxAge: res.data.expiresIn * 60 + }); + cookieStore.set( + refreshTokenCookieKey, + res.data.refreshToken, + { + httpOnly: true, + sameSite: 'strict' + }); + + return resultOk(); + } catch (error) { + if (isAxiosError(error) && error.response?.data) + return resultFail(error.response?.data); + } + + throw new Error('Unexpected code flow'); +} + +const baseUrl = process.env.NEXT_PRIVATE_BASE_URL; + +export async function register(registerData: RegisterData): Promise { + try { + await normalInstance.post('/api/account/register', { + email: registerData.email, + username: registerData.username, + password: registerData.password, + returnUri: `${baseUrl}/confirmAccount`, + }); + + return resultOk(); + } catch (error) { + if (isAxiosError(error)) + return resultFail(error.response?.data!); + } + + throw new Error('Unexpected code flow'); +} + +export async function generateAccessToken(): Promise> { + try { + const cookieStore = await cookies(); + + const res = await axios. + post(`${backendApiUrl}/api/account/refresh`, + { + refreshToken: cookieStore + .get(refreshTokenCookieKey)?.value, + }); + + return resultOk(res.data); + } catch (error) { + if (isAxiosError(error)) + return resultFail(error.response?.data!); + } + + throw new Error('Unexpected code flow'); +} + +export async function setAccessTokenCookie(accessToken: string, maxAge: number) { + const cookieStore = await cookies(); + cookieStore.set( + accessTokenCookieKey, + accessToken, + { + httpOnly: true, + sameSite: 'strict', + maxAge: maxAge * 60 + }); +} + +export async function confirmEmail(token: string, email: string): Promise { + try { + await normalInstance.post('/api/account/confirmEmail', { + token: token, + email: email, + }); + + return resultOk(); + } catch (error) { + if (isAxiosError(error)) + return resultFail(error.response?.data!); + } + + throw new Error('Unexpected code flow'); +} + +export async function logout() { + const cookieStore = await cookies(); + const refreshToken = cookieStore.get(refreshTokenCookieKey)?.value; + + await authInstance.post('/api/account/invalidateRefreshToken', { + refreshToken: refreshToken, + }); + + cookieStore.delete(refreshTokenCookieKey); + cookieStore.delete(accessTokenCookieKey); +} + +export async function forgotPassword(email: string): Promise { + try { + await normalInstance.post('/api/account/forgotPassword', { + username: email, + returnUri: `${baseUrl}/resetPassword`, + }); + + return resultOk(); + } catch (error) { + if (isAxiosError(error)) + return resultFail(error.response?.data!); + } + + throw new Error('Unexpected code flow'); +} + +export async function resetPassword(email: string, token: string, password: string): Promise { + try { + await normalInstance.post('/api/account/resetPassword', { + email: email, + token: token, + newPassword: password, + }); + + return resultOk(); + } + catch (error) { + if (isAxiosError(error)) + return resultFail(error.response?.data!); + } + + throw new Error('Unexpected code flow'); +} + +export async function updatePassword(currentPassword: string, newPassword: string): Promise { + + try { + await authInstance.put('/api/account/updatePassword', { + currentPassword: currentPassword, + newPassword: newPassword + }); + + return resultOk(); + } catch (error) { + if (isAxiosError(error)) + return resultFail(error.response?.data!); + } + + throw new Error('Unexpected code flow'); +} + +export const isUserInRole = + cache(async (roleName: string): Promise => { + try { + await authInstance.get('/api/account/isInRole', { + params: { + roleName + }, + }); + + return resultOk(); + } catch (error) { + if (isAxiosError(error)) + return resultFail(error.response?.data!); + } + + throw new Error('Unexpected code flow'); + }); + +export const deleteUser = + cache(async (email: string): Promise => { + try { + await authInstance.delete('/api/account/delete', { + params: { + email, + }, + }); + + return resultOk(); + } catch (error) { + if (isAxiosError(error)) + return resultFail(error.response?.data!); + } + + throw new Error('Unexpected code flow'); + }); diff --git a/frontend/econdo.client/src/actions/condo.ts b/frontend/econdo.client/src/actions/condo.ts index 50c6e00..dcecb84 100644 --- a/frontend/econdo.client/src/actions/condo.ts +++ b/frontend/econdo.client/src/actions/condo.ts @@ -20,6 +20,7 @@ export interface BuildingResult { streetNumber: string, buildingNumber: string, entranceNumber: string, + entranceId: string, } export const getBuildingsForUser = @@ -44,10 +45,10 @@ export const getBuildingsForUser = throw new Error('Unexpected code flow'); }); -export const isUserInBuilding = cache(async (buildingId: string, entranceNumber: string): Promise => { +export const isUserInBuilding = cache(async (entranceId: string): Promise => { try { await authInstance - .get(`/api/building/isEntranceManager?buildingId=${buildingId}&entranceNumber=${entranceNumber}`); + .get(`/api/building/isEntranceManager?entranceId=${entranceId}`); return resultOk(); } catch (error) { @@ -135,8 +136,7 @@ export const deleteEntrance = export const createBill = cache(async ( - buildingId: string, - entranceNumber: string, + entranceId: string, title: string, amount: number, isRecurring: boolean, @@ -148,8 +148,7 @@ export const createBill = try { await authInstance.post( '/api/bills/create', { - buildingId, - entranceNumber, + entranceId, title, amount, isRecurring, @@ -182,13 +181,12 @@ interface StripeStatus { const baseUrl = process.env.NEXT_PRIVATE_BASE_URL; export const connectToStripe = - cache(async (buildingId: string, entranceNumber: string): + cache(async (entranceId: string): Promise> => { try { const res = await authInstance.post( '/api/stripe/connect', { - buildingId, - entranceNumber, + entranceId, returnUri: `${baseUrl}`, }); @@ -204,14 +202,13 @@ export const connectToStripe = }); export const checkStripeStatus = - cache(async (buildingId: string, entranceNumber: string): + cache(async (entranceId: string): Promise> => { try { const res = await authInstance.get( '/api/stripe/checkEntranceStatus', { params: { - buildingId, - entranceNumber, + entranceId } }); @@ -227,14 +224,13 @@ export const checkStripeStatus = }); export const getStripeLoginLink = - cache(async (buildingId: string, entranceNumber: string): + cache(async (entranceId: string): Promise> => { try { const res = await authInstance.get( '/api/stripe/getLoginLink', { params: { - buildingId, - entranceNumber, + entranceId, } }); @@ -259,14 +255,13 @@ export interface BillResult { } export const getBillsForEntrance = - cache(async (buildingId: string, entranceNumber: string, page: number, pageSize: number): + cache(async (entranceId: string, page: number, pageSize: number): Promise>> => { try { const res = await authInstance.get>( '/api/bills/getForEntrance', { params: { - buildingId, - entranceNumber, + entranceId, page, pageSize } diff --git a/frontend/econdo.client/src/actions/property.ts b/frontend/econdo.client/src/actions/property.ts index 5889492..e8c528e 100644 --- a/frontend/econdo.client/src/actions/property.ts +++ b/frontend/econdo.client/src/actions/property.ts @@ -27,14 +27,13 @@ export interface PropertyOccupantResult { } export const getPropertiesInEntrance = - cache(async (buildingId: string, entranceNumber: string, page: number, pageSize: number): + cache(async (entranceId: string, page: number, pageSize: number): Promise>> => { try { const properties = await authInstance - .get>('/api/property/getPropertiesInBuilding', { + .get>('/api/property/getPropertiesInEntrance', { params: { - buildingId, - entranceNumber, + entranceId, page, pageSize }, diff --git a/frontend/econdo.client/src/actions/propertyOccupant.ts b/frontend/econdo.client/src/actions/propertyOccupant.ts index 17ae70b..cb506a0 100644 --- a/frontend/econdo.client/src/actions/propertyOccupant.ts +++ b/frontend/econdo.client/src/actions/propertyOccupant.ts @@ -2,7 +2,7 @@ import { authInstance } from "@/lib/axiosInstance"; import { ApiError, PagedList } from "@/types/apiResponses"; -import { InvitationStatus } from "@/types/propertyOccupant"; +import { InvitationStatus, OccupantType } from "@/types/propertyOccupant"; import { Result, resultFail, resultOk } from "@/types/result"; import { isAxiosError } from "axios"; import { cache } from "react"; @@ -103,7 +103,7 @@ export interface Occupant { firstName: string, middleName: string, lastName: string, - type: string, + type: OccupantType, email?: string, invitationStatus: InvitationStatus, } diff --git a/frontend/econdo.client/src/app/(user)/(dashboard)/admin/buildings/page.tsx b/frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/@buildings/page.tsx similarity index 100% rename from frontend/econdo.client/src/app/(user)/(dashboard)/admin/buildings/page.tsx rename to frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/@buildings/page.tsx diff --git a/frontend/econdo.client/src/app/(user)/(dashboard)/admin/properties/[[...slug]]/page.tsx b/frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/@properties/[[...slug]]/page.tsx similarity index 100% rename from frontend/econdo.client/src/app/(user)/(dashboard)/admin/properties/[[...slug]]/page.tsx rename to frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/@properties/[[...slug]]/page.tsx diff --git a/frontend/econdo.client/src/app/(user)/(dashboard)/admin/properties/[[...slug]]/propertiesPageContent.tsx b/frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/@properties/[[...slug]]/propertiesPageContent.tsx similarity index 100% rename from frontend/econdo.client/src/app/(user)/(dashboard)/admin/properties/[[...slug]]/propertiesPageContent.tsx rename to frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/@properties/[[...slug]]/propertiesPageContent.tsx diff --git a/frontend/econdo.client/src/app/(user)/(dashboard)/admin/users/page.tsx b/frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/@users/page.tsx similarity index 100% rename from frontend/econdo.client/src/app/(user)/(dashboard)/admin/users/page.tsx rename to frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/@users/page.tsx diff --git a/frontend/econdo.client/src/app/(user)/(dashboard)/admin/dashboardSidebar.module.css b/frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/dashboardSidebar.module.css similarity index 100% rename from frontend/econdo.client/src/app/(user)/(dashboard)/admin/dashboardSidebar.module.css rename to frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/dashboardSidebar.module.css diff --git a/frontend/econdo.client/src/app/(user)/(dashboard)/admin/dashboardSidebar.tsx b/frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/dashboardSidebar.tsx similarity index 100% rename from frontend/econdo.client/src/app/(user)/(dashboard)/admin/dashboardSidebar.tsx rename to frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/dashboardSidebar.tsx diff --git a/frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/layout.tsx b/frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/layout.tsx new file mode 100644 index 0000000..3cce608 --- /dev/null +++ b/frontend/econdo.client/src/app/(user)/(dashboard)/admin/[activeTab]/layout.tsx @@ -0,0 +1,37 @@ +'use client'; + +import Footer from "@/components/footer"; +import { UserNavbar } from "@/components/navbar/userNavbar"; +import { AppShell, AppShellMain } from "@mantine/core"; +import { ReactNode } from "react"; +import DashboardSidebar from "./dashboardSidebar"; +import { usePathname } from "next/navigation"; + +// TODO: consider: +// 1. moving the building and property pages to be a part of the condos/building and condos/buildings respectively +// 2. fix any and all fetch errors related to the new authorization system and the fact that entrance based queries no longer take in a building id and entrance number +// they take in only the entrance id for improved simplicity +export default function AdminLayout({ children }: + Readonly<{ + children: ReactNode, + }>) { + + const pathName = usePathname(); + + return ( + <>Under construction + ); + // return ( + // + // + // + // + // {children} + // + //